peekaboo 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 (November 13, 2010)
4
+
5
+ Features:
6
+
7
+ - Adds support for disabling method tracing via `.disable_tracing_for`
8
+ - Removes `.enable_tracing_on` & `.peek_list`
9
+
3
10
  ## 0.3.0 (November 8, 2010)
4
11
 
5
12
  Features:
data/README.md CHANGED
@@ -33,7 +33,7 @@ a number of class methods that can be used to create and inspect traced methods.
33
33
 
34
34
  It is also possible to enable tracing without explicitly including Peekaboo. See the ["Auto-inclusion"](#Auto-inclusion) for details.
35
35
 
36
- ### Method Tracing
36
+ ### Enabling Method Tracing
37
37
 
38
38
  Once Peekaboo has been enabled within a class you can call `enable_tracing_for`, inside the class definition or
39
39
  directly on the class object, passing it a structured hash of method names. The hash should contain 1 or 2 keys,
@@ -54,13 +54,26 @@ Now, with tracing enabled, Peekaboo will report when/where those methods are cal
54
54
 
55
55
  # Peekaboo tracer receives the following message when .first_class_method is called below:
56
56
  # "File:Line ( Example.first_class_method called with [] ==> Returning: 'whatever gets returned' )"
57
+
57
58
  Example.first_class_method
58
59
 
59
60
  # @obj is an instance of Example
60
61
  # Peekaboo tracer receives the following message when #baz is called below:
61
62
  # "File:Line ( Example#an_instance_method called with [:one, 2, "three"] ==> Returning: 'whatever gets returned' )"
63
+
62
64
  @obj.an_instance_method :one, 2, "three"
63
65
 
66
+ ### Disabling Method Tracing
67
+
68
+ Because your application may only want to trace certain methods at certain times, you can disable tracing for any method that
69
+ was previously being traced. The interface arguments are the same as above except that you will pass them to `disable_tracing_for`.
70
+
71
+ # Peekaboo is tracing .something and #something_else
72
+
73
+ Example.disable_tracing_for :singleton_methods => [:something], :instance_methods => [:something_else]
74
+
75
+ # Peekaboo has now restored these methods to an "untraced" state
76
+
64
77
  ### Pre-registration of Methods
65
78
 
66
79
  Sometimes, in Ruby, we need to define methods at runtime based on some aspect of our application. Fortunately,
@@ -113,12 +126,12 @@ Simply provide a list of classes to the configuration.
113
126
  end
114
127
 
115
128
  # Then inside your code somewhere
116
- Zip.enable_tracing_on # ...
117
- Zap.enable_tracing_on # ...
118
- Boom.enable_tracing_on # ...
129
+ Zip.enable_tracing_for # ...
130
+ Zap.enable_tracing_for # ...
131
+ Boom.enable_tracing_for # ...
119
132
 
120
133
  By configuring auto-inclusion, `Peekaboo` will load itself into your class *dynamically* at runtime.
121
- All that's left for you to do is call `enable_tracing_on` with a list of methods you want to trace.
134
+ All that's left for you to do is call `enable_tracing_for` with a list of methods you want to trace.
122
135
 
123
136
  Easy, huh? *It gets better!*
124
137
 
@@ -140,8 +153,8 @@ it will be enabled for any class that inherits from that class.
140
153
  config.autoinclude_with Weapon
141
154
  end
142
155
 
143
- Pistol.enable_tracing_one # Peekaboo loaded, Weapon & Firearm still left unchanged
144
- Firearm.enable_tracing_on # Peekaboo loaded, Weapon left unchanged
156
+ Pistol.enable_tracing_for # Peekaboo loaded, Weapon & Firearm still left unchanged
157
+ Firearm.enable_tracing_for # Peekaboo loaded, Weapon left unchanged
145
158
 
146
159
  ## Issues
147
160
 
@@ -38,29 +38,11 @@ module Peekaboo
38
38
  klass.const_set :PEEKABOO_METHOD_MAP, { :singleton_methods => Set.new, :instance_methods => Set.new }.freeze
39
39
  klass.instance_variable_set :@_hooked_by_peekaboo, true
40
40
  klass.extend SingletonMethods
41
-
42
- def klass.method_added name
43
- Peekaboo.wrap self, name, :instance if traced_instance_methods.include? name
44
- end
45
-
46
- def klass.singleton_method_added name
47
- Peekaboo.wrap self, name, :singleton if traced_singleton_methods.include? name
48
- end
49
41
  end
50
42
 
51
43
  # @private
52
44
  def setup_autoinclusion klass
53
- # @note changes made to this methods to support backwards
54
- # compatibility with {#enable_tracing_on}. This will become
55
- # much simpler when that method is removed.
56
- def klass.method_missing(method_name, *args, &block)
57
- if method_name.to_s =~ /^enable_tracing_(on|for)$/
58
- instance_eval { include Peekaboo }
59
- __send__ method_name, *args
60
- else
61
- super
62
- end
63
- end
45
+ klass.extend SingletonMethods::AutoInclusion
64
46
  end
65
47
 
66
48
  # @private
@@ -81,6 +63,16 @@ module Peekaboo
81
63
  end
82
64
  end
83
65
 
66
+ # @private
67
+ def unwrap klass, method_name, target
68
+ removal_snippet = "alias_method :#{method_name}, :original_#{method_name}"
69
+ case target
70
+ when :singleton then klass.instance_eval "class << self ; #{removal_snippet} ; end"
71
+ when :instance then klass.class_eval removal_snippet
72
+ else raise 'Only :class and :instance are valid targets'
73
+ end
74
+ end
75
+
84
76
  private
85
77
 
86
78
  def wrap_instance_method klass, method_name, original_method_name
@@ -56,8 +56,35 @@ module Peekaboo
56
56
  _register_traceables_ method_map[:singleton_methods], :singleton
57
57
  end
58
58
 
59
+ # Removes singleton and instance method tracing. This can be called in
60
+ # exactly the same fashion as {#enable_tracing_for enable_tracing_for}.
61
+ #
62
+ # @param [Hash] method_map a list of methods to trace
63
+ # @option method_map [Array<Symbol>] :singleton_methods ([]) singleton method list
64
+ # @option method_map [Array<Symbol>] :instance_methods ([]) instance method list
65
+ def disable_tracing_for method_map
66
+ method_map = { :singleton_methods => [], :instance_methods => [] }.merge method_map
67
+
68
+ _unregister_traceables_ method_map[:instance_methods], :instance
69
+ _unregister_traceables_ method_map[:singleton_methods], :singleton
70
+ end
71
+
59
72
  private
60
73
 
74
+ # Hooks tracing for instance methods added after registration.
75
+ #
76
+ # @param [Symbol] name method name
77
+ def method_added name
78
+ Peekaboo.wrap self, name, :instance if traced_instance_methods.include? name
79
+ end
80
+
81
+ # Hooks tracing for singleton methods added after registration.
82
+ #
83
+ # @param [Symbol] name method name
84
+ def singleton_method_added name
85
+ Peekaboo.wrap self, name, :singleton if traced_singleton_methods.include? name
86
+ end
87
+
61
88
  # Registers a list of method signatures and optionally enables tracing on them.
62
89
  # Tracing will only be "enabled" if the method exists and has not already been registered.
63
90
  #
@@ -75,52 +102,37 @@ module Peekaboo
75
102
  end
76
103
  end
77
104
 
78
-
79
- #################### DEPRECATED ####################
80
-
81
-
82
- public
83
-
84
- # @return [Array<Symbol>]
85
- # a list of instance methods that are being traced inside calling class
86
- # @deprecated
87
- # this method will be removed in version 0.4.0, use {#traced_method_map} instead
88
- def peek_list
89
- traced_instance_methods.to_a
90
- end
91
-
92
- # Enables instance method tracing on calling class.
93
- #
94
- # @example Trace a couple of methods
95
- # class SomeClass
96
- # include Peekaboo
97
- #
98
- # def method1; end
99
- # def method2; end
100
- # def method3; end
101
- # end
102
- #
103
- # # Tracing will be performed on method1(), method2(), but NOT method3()
104
- # SomeClass.enable_tracing_on :method1, :method2
105
+ # Unregisters a list of method signatures and optionally disables tracing on them.
106
+ # Tracing will only be "disabled" if the method exists and was previously being traced.
105
107
  #
106
- # @param [*Symbol] method_names
107
- # the list of methods that you want to trace
108
- # @raise [RuntimeError]
109
- # when attempting to add a method that is already being traced
110
- # @deprecated
111
- # this method will be removed in version 0.4.0, use {#enable_tracing_for} instead
112
- def enable_tracing_on *method_names
113
- include Peekaboo unless @_hooked_by_peekaboo
108
+ # @param [Array<Symbol>] method_list methods to register
109
+ # @param [Symbol] target specifies the receiver, either +:singleton+ or +:instance+
110
+ def _unregister_traceables_ method_list, target
111
+ method_list.each do |method_name|
112
+ target_method_list = __send__ :"traced_#{target}_methods"
113
+
114
+ if target_method_list.include? method_name
115
+ target_method_list.delete method_name
116
+ existing_methods = self.__send__(:"#{target}_methods", false).map(&:to_sym)
117
+ Peekaboo.unwrap self, method_name, target if existing_methods.include? method_name
118
+ end
119
+ end
120
+ end
121
+
122
+ module AutoInclusion
123
+
124
+ private
114
125
 
115
- method_names.each do |method_name|
116
- unless peek_list.include? method_name
117
- traced_instance_methods << method_name
118
- method_list = self.instance_methods(false).map(&:to_sym)
119
- Peekaboo.wrap self, method_name, :instance if method_list.include? method_name
126
+ def method_missing(method_name, *args, &block)
127
+ if method_name.to_s =~ /^enable_tracing_for$/
128
+ instance_eval { include Peekaboo }
129
+ enable_tracing_for *args
120
130
  else
121
- raise "Already tracing `#{method_name}'"
131
+ super
122
132
  end
123
133
  end
134
+
124
135
  end
136
+
125
137
  end
126
138
  end
@@ -2,7 +2,7 @@ module Peekaboo
2
2
  # Pretty self-explanatory
3
3
  module Version
4
4
  MAJOR = 0
5
- MINOR = 3
5
+ MINOR = 4
6
6
  PATCH = 0
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH].join('.')
@@ -50,14 +50,14 @@ describe Peekaboo::Configuration do
50
50
  it "should auto-include Peekaboo into any class in its list" do
51
51
  test_class = new_test_class
52
52
  @config.autoinclude_with test_class
53
- lambda { test_class.enable_tracing_on }.should_not raise_exception
53
+ lambda { test_class.enable_tracing_for({}) }.should_not raise_exception
54
54
  end
55
55
 
56
56
  it "should auto-include Peekaboo into any class that inherits from a class in its list" do
57
57
  parent_class = new_test_class
58
58
  child_class = Class.new(parent_class)
59
59
  @config.autoinclude_with parent_class
60
- lambda { child_class.enable_tracing_on }.should_not raise_exception
60
+ lambda { child_class.enable_tracing_for({}) }.should_not raise_exception
61
61
  end
62
62
  end
63
63
 
@@ -14,7 +14,7 @@ describe Peekaboo do
14
14
  end
15
15
  end
16
16
 
17
- context "standard tracing" do
17
+ context "enabling tracing" do
18
18
  before(:each) do
19
19
  @tracer = Peekaboo.configuration.tracer
20
20
  @test_class = new_test_class.instance_eval { include Peekaboo }
@@ -268,148 +268,73 @@ describe Peekaboo do
268
268
  end
269
269
  end
270
270
 
271
-
272
- ### OLD SPECIFICATIONS: Remove when moving to version 0.4.0 ###
273
-
274
-
275
- context ".enable_tracing_on (old)" do
271
+ context "disabling tracing" do
276
272
  before(:each) do
277
- @test_class = new_test_class
278
- @test_class.instance_eval { include Peekaboo }
279
- end
280
-
281
- it "should be a singleton method added to any including class" do
282
- @test_class.should respond_to :enable_tracing_on
283
- end
284
-
285
- it "should store a list of methods to trace on any including class" do
286
- methods_to_trace = [:method_no_args, :method_one_arg]
287
- @test_class.enable_tracing_on *methods_to_trace
288
- @test_class.peek_list.should =~ methods_to_trace
289
- end
290
-
291
- it "should raise an exception when trying to add a method that is already being traced" do
292
- @test_class.enable_tracing_on :some_method
293
- lambda {
294
- @test_class.enable_tracing_on :some_method
295
- }.should raise_exception "Already tracing `some_method'"
296
- end
297
- end
298
-
299
- context "instance method tracing (old)" do
300
- before(:all) do
301
- @test_class = new_test_class
302
- @test_class.instance_eval do
303
- include Peekaboo
304
- enable_tracing_on :method_no_args, :method_one_arg, :method_two_args, :method_optional_args, :method_variable_args, :method_raises
305
- end
306
-
307
- @test_instance = @test_class.new
308
273
  @tracer = Peekaboo.configuration.tracer
274
+ @test_class = new_test_class.instance_eval { include Peekaboo }
275
+ @test_class.enable_tracing_for :singleton_methods => [:say_hello, :hello, :add, :happy?, :comma_list, :kaboom],
276
+ :instance_methods => [:say_goodbye, :goodbye, :subtract, :sad?, :pipe_list, :crash]
309
277
  end
310
278
 
311
- it "should not take place on unlisted methods" do
312
- @tracer.should_not_receive :info
313
- @test_instance.method_no_tracing
314
- end
315
-
316
- it "should show listed methods with no arguments" do
317
- @tracer.should_receive(:info).with trace_message "Invoking: #{@test_class}#method_no_args with [] ==> Returning: nil"
318
- @test_instance.method_no_args
319
- end
320
-
321
- it "should show listed methods with standard arguments" do
322
- @tracer.should_receive(:info).
323
- with trace_message %{Invoking: #{@test_class}#method_one_arg with ["one"] ==> Returning: nil}
324
- @test_instance.method_one_arg 'one'
325
-
326
- @tracer.should_receive(:info).
327
- with trace_message %{Invoking: #{@test_class}#method_two_args with ["one", "two"] ==> Returning: nil}
328
- @test_instance.method_two_args 'one', 'two'
329
- end
330
-
331
- it "should show methods with optional arguments" do
332
- @tracer.should_receive(:info).
333
- with trace_message %{Invoking: #{@test_class}#method_optional_args with [] ==> Returning: nil}
334
- @test_instance.method_optional_args
335
-
336
- @tracer.should_receive(:info).
337
- with trace_message %{Invoking: #{@test_class}#method_optional_args with ["override"] ==> Returning: nil}
338
- @test_instance.method_optional_args 'override'
279
+ it "should not raise an exception when methods do not exist and have not been pre-registered" do
280
+ methods = { :singleton_methods => [:missing_class_def], :instance_methods => [:missing_instance_def] }
281
+ lambda { @test_class.disable_tracing_for methods }.should_not raise_exception
339
282
  end
340
283
 
341
- it "should show methods with variable arguments" do
342
- @tracer.should_receive(:info).
343
- with trace_message %{Invoking: #{@test_class}#method_variable_args with [] ==> Returning: nil}
344
- @test_instance.method_variable_args
345
-
346
- @tracer.should_receive(:info).
347
- with trace_message %{Invoking: #{@test_class}#method_variable_args with ["one"] ==> Returning: nil}
348
- @test_instance.method_variable_args 'one'
349
-
350
- @tracer.should_receive(:info).
351
- with trace_message %{Invoking: #{@test_class}#method_variable_args with ["one", "two"] ==> Returning: nil}
352
- @test_instance.method_variable_args 'one', 'two'
284
+ it "should not raise an exception when methods do not exist and have been pre-registered" do
285
+ methods = { :singleton_methods => [:missing_class_def], :instance_methods => [:missing_instance_def] }
286
+ @test_class.enable_tracing_for methods
287
+ lambda { @test_class.disable_tracing_for methods }.should_not raise_exception
353
288
  end
354
289
 
355
- it "should show methods that raise an exception" do
356
- lambda do
357
- @tracer.should_receive(:info).
358
- with trace_message %{Invoking: #{@test_class}#method_raises with [] !!! Raising: "something went wrong"}
359
- @test_instance.method_raises
360
- end.should raise_exception
361
- end
362
- end
363
-
364
- context "autoinclusion tracing (old)" do
365
- before(:all) do
366
- @tracer = Peekaboo.configuration.tracer
367
- end
368
-
369
- it "should inject functionality into an auto-included class" do
370
- test_class = new_test_class
371
- Peekaboo.configure { |config| config.autoinclude_with test_class }
372
- test_class.enable_tracing_on :method_no_args
373
-
374
- @tracer.should_receive(:info).with trace_message "Invoking: #{test_class}#method_no_args with [] ==> Returning: nil"
375
- test_class.new.method_no_args
376
- end
377
-
378
- it "should inject functionality into any class that inherits from an auto-included class" do
379
- parent_class = new_test_class
380
- child_class = Class.new(parent_class) do
381
- def another_method() ; end
290
+ context "on class methods" do
291
+ it "should remove the method name for the list of traced methods" do
292
+ lambda {
293
+ @test_class.disable_tracing_for :singleton_methods => [:say_hello]
294
+ }.should change(@test_class.traced_singleton_methods, :size).by(-1)
295
+
296
+ lambda {
297
+ @test_class.disable_tracing_for :singleton_methods => [:hello, :add]
298
+ }.should change(@test_class.traced_singleton_methods, :size).by(-2)
382
299
  end
383
-
384
- Peekaboo.configure { |config| config.autoinclude_with parent_class }
385
- child_class.enable_tracing_on :another_method
386
300
 
387
- @tracer.should_receive(:info).with trace_message "Invoking: #{child_class}#another_method with [] ==> Returning: nil"
388
- child_class.new.another_method
389
- end
390
-
391
- it "should not inject functionality into classes that are not auto-included" do
392
- test_class = new_test_class
393
- another_test_class = new_test_class
394
-
395
- Peekaboo.configure { |config| config.autoinclude_with test_class }
396
-
397
- lambda { another_test_class.enable_tracing_on :method_no_args }.should raise_exception NoMethodError
301
+ it "should properly restore the original method to an untraced state" do
302
+ @test_class.disable_tracing_for :singleton_methods => [:say_hello]
303
+ @tracer.should_not_receive :info
304
+ @test_class.say_hello.should == 'hello'
305
+
306
+ @test_class.disable_tracing_for :singleton_methods => [:hello, :add]
307
+ @tracer.should_not_receive :info
308
+ @test_class.hello('you').should == 'hello you'
309
+ @test_class.add(5, 4).should == 9
310
+ end
398
311
  end
399
312
 
400
- it "should maintain unique tracing method lists across an inheritance chain" do
401
- parent_class = new_test_class
402
- child_class = Class.new(parent_class) do
403
- def another_method() ; end
313
+ context "on instance methods" do
314
+ before(:each) do
315
+ @test_instance = @test_class.new
404
316
  end
405
317
 
406
- Peekaboo.configure { |config| config.autoinclude_with parent_class }
407
-
408
- parent_class.enable_tracing_on :method_no_args
409
- child_class.enable_tracing_on :another_method
410
-
411
- parent_class.peek_list.should =~ [:method_no_args]
412
- child_class.peek_list.should =~ [:another_method]
318
+ it "should remove the method name for the list of traced methods" do
319
+ lambda {
320
+ @test_class.disable_tracing_for :instance_methods => [:say_goodbye]
321
+ }.should change(@test_class.traced_instance_methods, :size).by(-1)
322
+
323
+ lambda {
324
+ @test_class.disable_tracing_for :instance_methods => [:goodbye, :subtract]
325
+ }.should change(@test_class.traced_instance_methods, :size).by(-2)
326
+ end
327
+
328
+ it "should properly restore the original method to an untraced state" do
329
+ @test_class.disable_tracing_for :instance_methods => [:say_goodbye]
330
+ @tracer.should_not_receive :info
331
+ @test_instance.say_goodbye.should == 'goodbye'
332
+
333
+ @test_class.disable_tracing_for :instance_methods => [:goodbye, :subtract]
334
+ @tracer.should_not_receive :info
335
+ @test_instance.goodbye('mother').should == 'goodbye mother'
336
+ @test_instance.subtract(100, 99).should == 1
337
+ end
413
338
  end
414
339
  end
415
340
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peekaboo
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 15
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 3
8
+ - 4
8
9
  - 0
9
- version: 0.3.0
10
+ version: 0.4.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Sonny Ruben Garcia
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-11-08 00:00:00 -06:00
18
+ date: 2010-11-13 00:00:00 -06:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
@@ -25,6 +26,7 @@ dependencies:
25
26
  requirements:
26
27
  - - "="
27
28
  - !ruby/object:Gem::Version
29
+ hash: 17
28
30
  segments:
29
31
  - 1
30
32
  - 0
@@ -70,6 +72,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
72
  requirements:
71
73
  - - ">="
72
74
  - !ruby/object:Gem::Version
75
+ hash: 3
73
76
  segments:
74
77
  - 0
75
78
  version: "0"
@@ -78,6 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
81
  requirements:
79
82
  - - ">="
80
83
  - !ruby/object:Gem::Version
84
+ hash: 3
81
85
  segments:
82
86
  - 0
83
87
  version: "0"