From: Kevin Clark Date: Wed, 18 Jun 2008 00:54:53 +0000 (+0000) Subject: Re-define the semantics of deprecate! and add deprecate_class! Include full specs... X-Git-Tag: 0.2.0~643 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=3eca0785978e545530939e568ba3a7f47029f0ab;p=common%2Fthrift.git Re-define the semantics of deprecate! and add deprecate_class! Include full specs for deprecate!/deprecate_class! git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@668906 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/lib/rb/lib/thrift/deprecation.rb b/lib/rb/lib/thrift/deprecation.rb index 7456f1cd..0ee4e264 100644 --- a/lib/rb/lib/thrift/deprecation.rb +++ b/lib/rb/lib/thrift/deprecation.rb @@ -1,19 +1,53 @@ +# provide a backwards-compatible wrapper API and deprecate it + +unless Thrift.const_defined?(:DEPRECATION) + Thrift::DEPRECATION = true +end + class Module - def deprecate!(*method_names) - method_names.each do |method_name| - module_eval <<-END - alias_method :deprecated_#{method_name}, :#{method_name} - def #{method_name}(*args, &block) - $stderr.puts "Warning: calling deprecated method: #{self}.#{method_name}" - deprecated_#{method_name}(*args, &block) - end - END - end - end + # Wraps the given methods to print a warning and call the real method + # Example: + # deprecate! :readAll => :read_all + def deprecate!(methods) + methods.each_pair do |old, new| + module_eval <<-EOF + def #{old}(*args, &block) + old, new = #{[old,new].inspect} + STDERR.puts "Warning: calling deprecated method \#{self.is_a?(Module) ? "\#{self}." : "\#{self.class}#"}\#{old}" + target = (self.is_a?(Module) ? (class << self;self;end) : self.class) + target.send :define_method, old, target.instance_method(new) # unwrap + target.instance_method(new).bind(self).call(*args, &block) + end + EOF + end + end end -require 'thrift/transport/ttransport' +module Kernel + # Provides an alternate name for the class for deprecation purposes + # Example: + # deprecate_class! :TBinaryProtocol => Thrift::BinaryProtocol + #-- + # at the moment this only works for creating top-level constants + # if necessary, this can be extended to take something like :'Thrift::TBinaryProtocol' + # alternately, Module can be extended with a similar method + # + # another idea is to not make the old name a pointer to the new, but rather + # a pointer to a proxy class that logs deprecation warnings and forwards methods + def deprecate_class!(klasses) + klasses.each_pair do |old, new| + Object.const_set old, new + end + end +end -class TTransport - deprecate! :isOpen, :readAll -end \ No newline at end of file +# TProtocol = Thrift::Protocol +# TProtocolException = Thrift::ProtocolException +# ThriftStruct = Thrift::Struct +# ThriftClient = Thrift::Client +# TProcessor = Thrift::Processor +# TType = Thrift::Types +# TMessageType = Thrift::MessageTypes +# TException = Thrift::Exception +# TApplicationException = Thrift::ApplicationException +# TBinaryProtocol = Thrift::BinaryProtocol diff --git a/lib/rb/spec/deprecation_spec.rb b/lib/rb/spec/deprecation_spec.rb new file mode 100644 index 00000000..62ff3965 --- /dev/null +++ b/lib/rb/spec/deprecation_spec.rb @@ -0,0 +1,152 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe 'deprecate!' do + def stub_stderr(callstr) + STDERR.should_receive(:puts).with("Warning: calling deprecated method #{callstr}") + end + + it "should work for Module methods" do + mod = Module.new do + class << self + def new + "new" + end + deprecate! :old => :new + end + end + stub_stderr "#{mod.inspect}.old" + mod.old.should == "new" + end + + it "should work with Modules that extend themselves" do + mod = Module.new do + extend self + def new + "new" + end + deprecate! :old => :new + end + stub_stderr "#{mod.inspect}.old" + mod.old.should == "new" + end + + it "should work wtih Class methods" do + klass = Class.new do + class << self + def new + "new" + end + deprecate! :old => :new + end + end + stub_stderr "#{klass.inspect}.old" + klass.old.should == "new" + end + + it "should work with Classes that include Modules" do + mod = Module.new do + def new + "new" + end + deprecate! :old => :new + end + klass = Class.new do + include mod + end + stub_stderr "#{klass.inspect}#old" + klass.new.old.should == "new" + end + + it "should work with instance methods" do + klass = Class.new do + def new + "new" + end + deprecate! :old => :new + end + stub_stderr "#{klass.inspect}#old" + klass.new.old.should == "new" + end + + it "should work with multiple method names" do + klass = Class.new do + def new1 + "new 1" + end + def new2 + "new 2" + end + deprecate! :old1 => :new1, :old2 => :new2 + end + stub_stderr("#{klass.inspect}#old1").ordered + stub_stderr("#{klass.inspect}#old2").ordered + inst = klass.new + inst.old1.should == "new 1" + inst.old2.should == "new 2" + end + + it "should only log a message once, even across multiple instances" do + klass = Class.new do + def new + "new" + end + deprecate! :old => :new + end + stub_stderr("#{klass.inspect}#old").once + klass.new.old.should == "new" + klass.new.old.should == "new" + end + + it "should pass arguments" do + klass = Class.new do + def new(a, b) + "new: #{a + b}" + end + deprecate! :old => :new + end + stub_stderr("#{klass.inspect}#old") + klass.new.old(3, 5).should == "new: 8" + end + + it "should pass blocks" do + klass = Class.new do + def new + "new #{yield}" + end + deprecate! :old => :new + end + stub_stderr("#{klass.inspect}#old") + klass.new.old { "block" }.should == "new block" + end + + it "should not freeze the definition of the new method" do + klass = Class.new do + def new + "new" + end + deprecate! :old => :new + end + klass.send :define_method, :new do + "new 2" + end + stub_stderr("#{klass.inspect}#old") + klass.new.old.should == "new 2" + end +end + +describe "deprecate_class!" do + it "should create a new global constant that points to the old one" do + begin + klass = Class.new do + def foo + "foo" + end + end + deprecate_class! :DeprecationSpecOldClass => klass + DeprecationSpecOldClass.should eql(klass) + DeprecationSpecOldClass.new.foo.should == "foo" + ensure + Object.send :remove_const, :DeprecationSpecOldClass + end + end +end diff --git a/lib/rb/spec/spec_helper.rb b/lib/rb/spec/spec_helper.rb new file mode 100644 index 00000000..1c67cb25 --- /dev/null +++ b/lib/rb/spec/spec_helper.rb @@ -0,0 +1,4 @@ +require 'rubygems' +require 'spec' + +require File.dirname(__FILE__) + '/../lib/thrift'