You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by kc...@apache.org on 2008/06/18 03:02:14 UTC

svn commit: r668930 - in /incubator/thrift/trunk/lib/rb: lib/thrift/deprecation.rb spec/deprecation_spec.rb

Author: kclark
Date: Tue Jun 17 18:02:14 2008
New Revision: 668930

URL: http://svn.apache.org/viewvc?rev=668930&view=rev
Log:
Solve the information leak problem between deprecations. Unfortunately this was caused by a nasty ruby bug.

Modified:
    incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb
    incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb

Modified: incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb?rev=668930&r1=668929&r2=668930&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb (original)
+++ incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb Tue Jun 17 18:02:14 2008
@@ -31,74 +31,91 @@
   end
 end
 
-module Thrift::DeprecationProxy
+module Thrift::DeprecationProxy # :nodoc:
+  # there's a really weird bug in Ruby where class variables behave wrong
+  # when used in a Class.new or #class_eval rather than in a class foo block.
+  CLASS_MAPPING = {}
+  MODULE_MAPPING = {}
   def self.new_class(obj, name)
-    Class.new(obj) do
+    klass = Class.new(obj) do
       klass = self
-      @@self = klass
-      @@obj = obj
       instance_methods.sort.reject { |x| [:__id__,:__send__].include? x.to_sym }.each do |sym|
         undef_method sym
       end
+      define_method :__thrift_deprecation_proxy_klass do
+        klass
+      end
       def method_missing(sym, *args, &block)
-        @@obj.instance_method(sym).bind(self).call(*args, &block)
+        klass = __thrift_deprecation_proxy_klass
+        obj, name, warned = CLASS_MAPPING[klass.__id__]
+        obj.instance_method(sym).bind(self).call(*args, &block)
       end
       (class << self;self;end).class_eval do
-        @@self = klass
-        @@obj = obj
-        @@name = name
-        @@warned = false
         instance_methods.sort.reject { |x| [:__id__,:__send__].include? x.to_sym }.each do |sym|
           undef_method sym
         end
+        define_method :__thrift_deprecation_proxy_klass do
+          klass
+        end
         def method_missing(sym, *args, &block)
-          unless @@warned
-            STDERR.puts "Warning: class #{@@name} is deprecated"
+          klass = __thrift_deprecation_proxy_klass
+          obj, name, warned = CLASS_MAPPING[klass.__id__]
+          unless warned
+            STDERR.puts "Warning: class #{name} is deprecated"
             STDERR.puts "  from #{caller.first}"
-            @@warned = true
+            CLASS_MAPPING[__thrift_deprecation_proxy_klass.__id__][2] = true
           end
-          if @@self.__id__ == self.__id__
-            @@obj.send sym, *args, &block
+          if klass.__id__ == self.__id__
+            obj.send sym, *args, &block
           else
-            @@obj.method(sym).unbind.bind(self).call(*args, &block)
+            obj.method(sym).unbind.bind(self).call(*args, &block)
           end
         end
       end
     end
+    CLASS_MAPPING[klass.__id__] = [obj, name, false]
+    klass
   end
   def self.new_module(obj, name)
-    Module.new do
-      @@obj = obj
-      @@warned = false
-      @@name = name
+    mod = Module.new do
       include obj
       instance_methods.sort.reject { |x| [:__id__,:__send__].include? x.to_sym }.each do |sym|
         undef_method sym
       end
+      define_method :__thrift_deprecation_proxy_module do
+        mod
+      end
       def method_missing(sym, *args, &block)
-        unless @@warned
-          STDERR.puts "Warning: module #{@@name} is deprecated"
+        mod = __thrift_deprecation_proxy_module
+        obj, name, warned = MODULE_MAPPING[mod.__id__]
+        unless warned
+          STDERR.puts "Warning: module #{name} is deprecated"
           STDERR.puts "  from #{caller.first}"
-          @@warned = true
+          MODULE_MAPPING[mod.__id__][2] = true
         end
-        @@obj.instance_method(sym).bind(self).call(*args, &block)
+        obj.instance_method(sym).bind(self).call(*args, &block)
       end
       (class << self;self;end).class_eval do
-        @@obj = obj
-        @@warned = false
         instance_methods.sort.reject { |x| [:__id__,:__send__].include? x.to_sym }.each do |sym|
           undef_method sym
         end
+        define_method :__thrift_deprecation_proxy_module do
+          mod
+        end
         def method_missing(sym, *args, &block)
-          unless @@warned
-            STDERR.puts "Warning: module #{@@name} is deprecated"
+          mod = __thrift_deprecation_proxy_module
+          obj, name, warned = MODULE_MAPPING[mod.__id__]
+          unless warned
+            STDERR.puts "Warning: module #{name} is deprecated"
             STDERR.puts "  from #{caller.first}"
-            @@warned = true
+            MODULE_MAPPING[mod.__id__][2] = true
           end
-          @@obj.send sym, *args, &block
+          obj.send sym, *args, &block
         end
       end
     end
+    MODULE_MAPPING[mod.__id__] = [obj, name, false]
+    mod
   end
 end
 

Modified: incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb?rev=668930&r1=668929&r2=668930&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb (original)
+++ incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb Tue Jun 17 18:02:14 2008
@@ -176,8 +176,8 @@
 describe "deprecate_class!" do
   it_should_behave_like "deprecation"
 
-  def stub_stderr(callstr, offset=1)
-    STDERR.should_receive(:puts).with("Warning: class #{callstr} is deprecated")
+  def stub_stderr(klass, offset=1)
+    STDERR.should_receive(:puts).with("Warning: class #{klass} is deprecated")
     line = caller.first[/\d+$/].to_i + offset
     STDERR.should_receive(:puts).with("  from #{__FILE__}:#{line}")
   end
@@ -259,8 +259,8 @@
 describe "deprecate_module!" do
   it_should_behave_like "deprecation"
 
-  def stub_stderr(callstr, offset=1)
-    STDERR.should_receive(:puts).with("Warning: module #{callstr} is deprecated")
+  def stub_stderr(mod, offset=1)
+    STDERR.should_receive(:puts).with("Warning: module #{mod} is deprecated")
     line = caller.first[/\d+$/].to_i + offset
     STDERR.should_receive(:puts).with("  from #{__FILE__}:#{line}")
   end
@@ -344,4 +344,27 @@
       klass.new.foo.should == "foo"
     end
   end
+
+  it "should not bleed info between deprecations" do
+    ensure_const_removed :DeprecationSpecOldModule do
+      ensure_const_removed :DeprecationSpecOldModule2 do
+        mod = Module.new do
+          def self.foo
+            "foo"
+          end
+        end
+        deprecate_module! :DeprecationSpecOldModule => mod
+        mod2 = Module.new do
+          def self.bar
+            "bar"
+          end
+        end
+        deprecate_module! :DeprecationSpecOldModule2 => mod2
+        stub_stderr(:DeprecationSpecOldModule)
+        ::DeprecationSpecOldModule.foo.should == "foo"
+        stub_stderr(:DeprecationSpecOldModule2)
+        ::DeprecationSpecOldModule2.bar.should == "bar"
+      end
+    end
+  end
 end