Forum: Ruby Rake, Hoe, Meta-Programming, and Warnings (oh my!)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Tim P. (Guest)
on 2007-01-19 17:29
(Received via mailing list)
Is there a way to disable specific warnings from within a Ruby program
(not from the command line)?

The warnings are coming from some meta-programming code that is
redefining instance methods on the fly based on user input. So maybe a
better question would be, is there a way to redefine methods without
causing Ruby to spew out a warning each time the method is redefined.

This is the result of using Hoe (thanks Ryan, Eric, and other sun
deprived Rubyists) to run my unit tests. Hoe adds the -w flag to the
Ruby interpreter when it runs tests. This is a good thing as it found
several minor flaws in my code. But redefining methods is at the heart
of what I'm trying to do.


Example:

class Pattern
  def self.create_date_format_methods( pf )
    module_eval <<-CODE
      def pf.format_date
        Time.now.strftime "#{pf.date_pattern}"
       end
    CODE
  end
end

When running unit tests with the -w flag ...

(eval):1: warning: redefine format_date



Any thoughts on how to suppress the warning and/or change my
meta-programming so the warning does not show up?

Blessings,
TwP
Daniel B. (Guest)
on 2007-01-19 17:29
(Received via mailing list)
Tim P. wrote:
> Is there a way to disable specific warnings from within a Ruby program
> (not from the command line)?
>
> The warnings are coming from some meta-programming code that is
> redefining instance methods on the fly based on user input. So maybe a
> better question would be, is there a way to redefine methods without
> causing Ruby to spew out a warning each time the method is redefined.

Sure - redefine Kernel#warn. ;)

Seriously, I think what we need are structured warnings.  I brought
this up way back in 2002: http://tinyurl.com/yfko6z

I'm certainly not the first to think of it (Perl lets you disable
specific kinds of warnings, it's been brought up on IRC several times
over the years), but some sort of structured warning that programmers
could specifically raise and/or ignore is something I've wanted for a
long time.

I would think it would just be a matter of copying exception.c, ripping
out the longjmp/exit parts of it, defining a warning hierarchy, and
adding a Warning.ignore class method.  Of course, it probably isn't
that simple.

Any, I imagine instead of doing this within your code:

warn, "redefinition of constant FOO"

Internally, you would do this:

raise RedefinedWarning, "redefinition of constant FOO"

And then, a programmer could do this:

RedefinedWarning.ignore # ignore all redefintion warnings

And, I think Sean originally suggested allowing a block syntax, so you
could temporarily ignore warnings:

RedefinedWarning.ignore do
   # Ignore redefinition warnings within this block only
end

Back to your question, though, I suppose we would have add a
Warning.disable in order to prevent the warning from ever being
generated in the first place:

RedefinedWarning.disable do
   def some_method
      # Pretend you didn't notice that I've redefined this method
   end
end

Whether that's good practice or not, I leave to the viewing audience.

Probably a much longer answer than you wanted, but there you go.

Regards,

Dan
Tim P. (Guest)
on 2007-01-19 17:29
(Received via mailing list)
On 1/12/07, Daniel B. <removed_email_address@domain.invalid> wrote:
>
> out the longjmp/exit parts of it, defining a warning hierarchy, and
>
>
> Whether that's good practice or not, I leave to the viewing audience.
>
> Probably a much longer answer than you wanted, but there you go.
>

Long answers are usually the most educational ones (or the most
inflammatory).

I can understand why this would cause a warning -- if someone
inadvertently redefined a method, this would be a nice check. However,
this is my desired behavior <sigh>.

As Florian mentioned, redefining $VERBOSE will suppress the warnings.
It "feels" a little kludgy to me, though.

Hmmm ... maybe Matz doesn't want the performance hit of having to
perform a warning table lookup for each line of code parsed. That
would be one good reason to disallow fine grained warning control.

How's the snow down in your neck of the woods?

Blessings,
TwP
Mike H. (Guest)
on 2007-01-19 17:30
(Received via mailing list)
Tim P. wrote:

> Ruby interpreter when it runs tests. This is a good thing as it found
>        Time.now.strftime "#{pf.date_pattern}"
>
> Any thoughts on how to suppress the warning and/or change my
> meta-programming so the warning does not show up?
>
> Blessings,
> TwP
>
>
I understand that this isn't identical to what you're doing, but it
demonstrates how define_method won't cause a warning.

class Foo
  define_method(:bar) do
    puts "bar"
  end
  def cat
    puts "cat"
  end
end

Foo.new.bar
Foo.new.cat

class Foo
  define_method(:bar) do
    puts "bar2"
  end
  def cat
    puts "cat2"
  end
end

Foo.new.bar
Foo.new.cat

 >ruby -w foo.rb
bar
cat
foo.rb:17: warning: method redefined; discarding old cat
bar2
cat2
Florian F. (Guest)
on 2007-01-19 17:30
(Received via mailing list)
Tim P. wrote:
> class Pattern
>  def self.create_date_format_methods( pf )
      old, $VERBOSE = $VERBOSE, nil
>    module_eval <<-CODE
>      def pf.format_date
>        Time.now.strftime "#{pf.date_pattern}"
>       end
>    CODE
    ensure
      $VERBOSE = old
James G. (Guest)
on 2007-01-19 17:31
(Received via mailing list)
On Jan 12, 2007, at 11:24 AM, Tim P. wrote:

> The warnings are coming from some meta-programming code that is
> redefining instance methods on the fly based on user input. So maybe a
> better question would be, is there a way to redefine methods without
> causing Ruby to spew out a warning each time the method is redefined.

Sure.  Watch:

#!/usr/bin/env ruby -w

class Test
   def override
     "original"
   end
end

Test.new.override  # => "original"

class Test
   def override # !> method redefined; discarding old override
     "warning"
   end
end

Test.new.override  # => "warning"

class Test
   undef :override
   def override
     "no warning"
   end
end

Test.new.override  # => "no warning"

class Test
   alias_method :old_override, :override
   def override
     "alias avoids warning too"
   end
end

Test.new.override  # => "alias avoids warning too"

__END__

Hope that helps.

James Edward G. II
Tim P. (Guest)
on 2007-01-19 17:31
(Received via mailing list)
On 1/12/07, Mike H. <removed_email_address@domain.invalid> wrote:
> end
>   end
> cat2
>
>
>

There is going to be a performance hit with define_method.  Since the
method body is a block, each time it is called a Binding to the
instance will have to be created in which the block will be run.

$ cat a.rb

require 'benchmark'

class Object
  def method() end
  define_method(:method1) {}
end

this_many = 1_000_000
::Benchmark.bm(10) do |bm|
  bm.report('method     :') {this_many.times {method()}}
  bm.report('method1    :') {this_many.times {method1()}}
end


$ ruby a.rb
                user     system      total        real
method     :  0.400000   0.000000   0.400000 (  0.400000)
method1    :  1.272000   0.000000   1.272000 (  1.282000)



It is a factor of 3 slower   :(

Blessings,
TwP
Tim P. (Guest)
on 2007-01-19 17:32
(Received via mailing list)
On 1/12/07, James Edward G. II <removed_email_address@domain.invalid> wrote:
>
>      "warning"
> end
> Test.new.override  # => "alias avoids warning too"
>
> __END__
>
> Hope that helps.
>

Hey James!  That did the trick.

I could have sworn that I tried undef before, but in my current sleep
deprived state I'm not too sure about it.  Hmmm ... I most likely did
try undef, but it chucked an exception at me when I tried to undef a
non-existent method.

Now using undef along with method_defined?

All is well :)

Blessings,
TwP
This topic is locked and can not be replied to.