[前][次][番号順一覧][スレッド一覧]

ruby-changes:62800

From: eileencodes <ko1@a...>
Date: Wed, 2 Sep 2020 08:16:32 +0900 (JST)
Subject: [ruby-changes:62800] 6e8ec9ab6d (master): Support passing a category to `Warning.warn`

https://git.ruby-lang.org/ruby.git/commit/?id=6e8ec9ab6d

From 6e8ec9ab6da228ade70fe7d0dd16540d8f859f00 Mon Sep 17 00:00:00 2001
From: eileencodes <eileencodes@g...>
Date: Thu, 6 Aug 2020 13:25:11 -0400
Subject: Support passing a category to `Warning.warn`

This change adds a `category` kwarg to make it easier to monkey patch
`Warning.warn`. Warnings already have a category, but that warning isn't
exposed. This implements a way to get the category so that warnings with
a specific category, like deprecated, can be treated differently than
other warnings in an application.

The change here does an arity check on the method to support backwards
compatibility for applications that may already have a warning monkey
patch.

For our usecase we want to `raise` for deprecation warnings in order to
get the behavior for the next Ruby version. For example, now that we
fixed all our warnings and deployed Ruby 2.7 to production, we want to
be able to have deprecation warnings behave like they would in 3.0: raise
an error. For other warnings, like uninialized constants, that behavior
won't be removed from Ruby in the next version, so we don't need to
raise errors.

Co-authored-by: Aaron Patterson <tenderlove@r...>

diff --git a/NEWS.md b/NEWS.md
index 075c5ec..1bc19e8 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -165,6 +165,13 @@ Outstanding ones only. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L165
         * Symbol#to_proc now returns a lambda Proc.
           [[Feature #16260]]
 
+* Warning
+
+    * Modified method
+
+        * Warning#warn now supports a category kwarg.
+        [[Feature #17122]]
+
 ## Stdlib updates
 
 Outstanding ones only.
@@ -342,3 +349,4 @@ Excluding feature bug fixes. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L349
 [Feature #16686]: https://bugs.ruby-lang.org/issues/16686
 [Misc #16961]:    https://bugs.ruby-lang.org/issues/16961
 [Bug #8446]:      https://bugs.ruby-lang.org/issues/8446
+[Feature #17122]: https://bugs.ruby-lang.org/issues/17122
diff --git a/error.c b/error.c
index ce936ac..841ab6c 100644
--- a/error.c
+++ b/error.c
@@ -229,15 +229,20 @@ rb_warning_s_aset(VALUE mod, VALUE category, VALUE flag) https://github.com/ruby/ruby/blob/trunk/error.c#L229
 
 /*
  * call-seq:
- *    warn(msg)  -> nil
+ *    warn(msg, **kw)  -> nil
  *
  * Writes warning message +msg+ to $stderr. This method is called by
- * Ruby for all emitted warnings.
+ * Ruby for all emitted warnings. A +category+ may be included with
+ * the warning.
  */
 
 static VALUE
-rb_warning_s_warn(VALUE mod, VALUE str)
+rb_warning_s_warn(int argc, VALUE *argv, VALUE mod)
 {
+    VALUE str;
+    VALUE opt;
+
+    rb_scan_args(argc, argv, "1:", &str, &opt);
     Check_Type(str, T_STRING);
     rb_must_asciicompat(str);
     rb_write_error_str(str);
@@ -401,7 +406,22 @@ rb_warn_deprecated_to_remove(const char *fmt, const char *removal, ...) https://github.com/ruby/ruby/blob/trunk/error.c#L406
     va_end(args);
     rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1);
     rb_str_catf(mesg, " is deprecated and will be removed in Ruby %s\n", removal);
-    rb_write_warning_str(mesg);
+
+    VALUE warn_args[2];
+    warn_args[0] = mesg;
+
+    const rb_method_entry_t * me;
+    me = rb_method_entry(rb_mWarning, id_warn);
+
+    if (rb_method_entry_arity(me) != 1) {
+        VALUE kwargs = rb_hash_new();
+        rb_hash_aset(kwargs, ID2SYM(rb_intern("category")), ID2SYM(rb_intern("deprecated")));
+        warn_args[1] = kwargs;
+
+        rb_funcallv_kw(rb_mWarning, id_warn, 2, warn_args, RB_PASS_KEYWORDS);
+    } else {
+        rb_funcall(rb_mWarning, id_warn, 1, mesg);
+    }
 }
 
 static inline int
@@ -2658,7 +2678,7 @@ Init_Exception(void) https://github.com/ruby/ruby/blob/trunk/error.c#L2678
     rb_mWarning = rb_define_module("Warning");
     rb_define_singleton_method(rb_mWarning, "[]", rb_warning_s_aref, 1);
     rb_define_singleton_method(rb_mWarning, "[]=", rb_warning_s_aset, 2);
-    rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, 1);
+    rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, -1);
     rb_extend_object(rb_mWarning, rb_mWarning);
 
     /* :nodoc: */
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 4decddc..a89aed8 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -915,7 +915,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| https://github.com/ruby/ruby/blob/trunk/test/ruby/test_exception.rb#L915
     end
   end
 
-  def capture_warning_warn
+  def capture_warning_warn(category: false)
     verbose = $VERBOSE
     deprecated = Warning[:deprecated]
     warning = []
@@ -924,8 +924,14 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| https://github.com/ruby/ruby/blob/trunk/test/ruby/test_exception.rb#L924
       alias_method :warn2, :warn
       remove_method :warn
 
-      define_method(:warn) do |str|
-        warning << str
+      if category
+        define_method(:warn) do |str, **kw|
+          warning << [str, kw[:category]]
+        end
+      else
+        define_method(:warn) do |str|
+          warning << str
+        end
       end
     end
 
@@ -954,6 +960,18 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| https://github.com/ruby/ruby/blob/trunk/test/ruby/test_exception.rb#L960
     assert_equal(["\n"],     capture_warning_warn {warn ""})
   end
 
+  def test_warn_backwards_compatibility
+    warning = capture_warning_warn { Object.new.tainted? }
+
+    assert_match(/deprecated/, warning[0])
+  end
+
+  def test_warn_category
+    warning = capture_warning_warn(category: true) { Object.new.tainted? }
+
+    assert_equal :deprecated, warning[0][1]
+  end
+
   def test_kernel_warn_uplevel
     warning = capture_warning_warn {warn("test warning", uplevel: 0)}
     assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0])
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]