private_please 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. data/.gitignore +0 -1
  2. data/.travis.yml +10 -0
  3. data/CHANGELOG +8 -0
  4. data/README.md +92 -42
  5. data/bin/pp_ruby +62 -0
  6. data/bin/ruby_pp +62 -0
  7. data/doc/dev_notes.txt +32 -0
  8. data/doc/fixtures/complex.rb +103 -0
  9. data/doc/fixtures/empty_class.rb +7 -0
  10. data/doc/fixtures/fixture_helper.rb +8 -0
  11. data/doc/fixtures/sample.rb +57 -0
  12. data/lib/private_please/candidate.rb +10 -2
  13. data/lib/private_please/report/table.rb +44 -0
  14. data/lib/private_please/report.rb +6 -0
  15. data/lib/private_please/reporter/base.rb +28 -0
  16. data/lib/private_please/reporter/helpers/options_helpers.rb +12 -0
  17. data/lib/private_please/reporter/helpers/text_table_helpers.rb +9 -0
  18. data/lib/private_please/{report/reporter.rb → reporter/simple_text.rb} +12 -18
  19. data/lib/private_please/reporter/templates/simple.txt.erb +77 -0
  20. data/lib/private_please/reporter.rb +8 -0
  21. data/lib/private_please/storage/methods_names.rb +1 -0
  22. data/lib/private_please/storage.rb +8 -0
  23. data/lib/private_please/tracking/extension.rb +3 -10
  24. data/lib/private_please/tracking/instrumentor.rb +13 -35
  25. data/lib/private_please/tracking/instruments_all_methods_below.rb +28 -0
  26. data/lib/private_please/tracking/instruments_automatically_all_methods_in_all_classes.rb +52 -0
  27. data/lib/private_please/tracking/line_change_tracker.rb +8 -18
  28. data/lib/private_please/tracking/utils.rb +34 -0
  29. data/lib/private_please/tracking.rb +48 -0
  30. data/lib/private_please/version.rb +1 -1
  31. data/lib/private_please.rb +27 -44
  32. data/private_please.gemspec +7 -1
  33. data/spec/{01_marking_candidate_methods_to_observe_spec.rb → 01_tracking_candidate_methods/explicitely_with_the_private_please_command_spec.rb} +35 -70
  34. data/spec/01_tracking_candidate_methods/systematically_in_auto_mode_spec.rb +187 -0
  35. data/spec/{02_logging_calls_on_candidate_methods_spec.rb → 03_logging_calls_on_candidate_methods_spec.rb} +2 -4
  36. data/spec/04_instrumented_program_activity_observation_result_spec.rb +2 -5
  37. data/spec/05_reporting/report_table_spec.rb +51 -0
  38. data/spec/06_at_exit_spec.rb +18 -0
  39. data/spec/fixtures/bug_22.rb +17 -0
  40. data/spec/fixtures/sample_class_for_report.rb +2 -0
  41. data/spec/sandbox/Gemfile +4 -0
  42. data/spec/sandbox/Gemfile.lock +14 -0
  43. data/spec/sandbox/README.txt +26 -0
  44. data/spec/sandbox/normal.rb +7 -0
  45. data/spec/sandbox/normal_prepended_with_require.rb +8 -0
  46. data/spec/spec_helper.rb +6 -2
  47. metadata +50 -13
  48. data/lib/private_please/report/templates/simple.txt.erb +0 -61
  49. data/lib/private_please/tracking/instruments_all_below.rb +0 -41
@@ -1,24 +1,14 @@
1
+ require File.dirname(__FILE__) + '/base'
1
2
  require 'erb'
2
- module PrivatePlease ; module Report
3
- class Reporter
3
+ require File.dirname(__FILE__) + '/helpers/options_helpers'
4
+ require File.dirname(__FILE__) + '/helpers/text_table_helpers'
5
+ module PrivatePlease ; module Reporter
4
6
 
5
- TEMPLATE_PATH = File.expand_path(File.dirname(__FILE__) + '/templates/simple.txt.erb')
6
-
7
- attr_reader :candidates_store, :calls_store,
8
- :good_candidates, :bad_candidates,
9
- :good_candidates_c, :bad_candidates_c,
10
- :never_called_candidates, :never_called_candidates_c,
11
- :building_time
12
-
13
-
14
- def initialize(candidates_store, calls_store)
15
- @candidates_store = candidates_store
16
- @calls_store = calls_store
7
+ class SimpleText < Base
17
8
 
18
- prepare_report_data
19
- end
9
+ TEMPLATE_PATH = File.expand_path(File.dirname(__FILE__) + '/templates/simple.txt.erb')
20
10
 
21
- def to_s
11
+ def text
22
12
  erb = ERB.new(File.read(TEMPLATE_PATH), 0, "%<>")
23
13
  erb.result(binding)
24
14
  end
@@ -29,7 +19,7 @@ module PrivatePlease ; module Report
29
19
  start_time = Time.now
30
20
  @bad_candidates = calls_store.external_calls .clone
31
21
  @bad_candidates_c = calls_store.class_external_calls.clone
32
- # TODO : optimize
22
+ # TODO : optimize (with Hamster?)
33
23
  @good_candidates = calls_store.internal_calls .clone.remove(@bad_candidates)
34
24
  @good_candidates_c= calls_store.class_internal_calls.clone.remove(@bad_candidates_c)
35
25
 
@@ -40,6 +30,9 @@ module PrivatePlease ; module Report
40
30
  @never_called_candidates_c = candidates_store.class_methods.clone.
41
31
  remove(@good_candidates_c).
42
32
  remove(@bad_candidates_c )
33
+ [
34
+ @bad_candidates, @bad_candidates_c, @good_candidates, @good_candidates_c, @never_called_candidates, @never_called_candidates_c
35
+ ].each {|arr| arr.reject!{|k, v| v.empty?}}
43
36
  @building_time = Time.now - start_time
44
37
 
45
38
  @candidates_classes_names = (candidates_store.instance_methods.classes_names +
@@ -49,4 +42,5 @@ module PrivatePlease ; module Report
49
42
  @never_called_candidates_classes_names = (@never_called_candidates_c .classes_names + @never_called_candidates.classes_names).uniq.sort
50
43
  end
51
44
  end
45
+
52
46
  end end
@@ -0,0 +1,77 @@
1
+ ====================================================================================
2
+ = PrivatePlease report : =
3
+ ====================================================================================
4
+ % @candidates_classes_names .sort.each do |class_name|
5
+ %
6
+ % show_good_candidates_section = true
7
+ % show_bad_candidates_section = show_bad_candidates_section?
8
+ % show_never_candidates_section = show_never_called_candidates_section?
9
+ %
10
+ % if show_good_candidates_section
11
+ % good_candidates_table = table_for(
12
+ % names_from(class_name, good_candidates , prefix = "#"),
13
+ % names_from(class_name, good_candidates_c, prefix = "."))
14
+ % end
15
+ % if show_bad_candidates_section
16
+ % bad_candidates_table = table_for(
17
+ % names_from(class_name, bad_candidates , prefix = "#"),
18
+ % names_from(class_name, bad_candidates_c, prefix = "."))
19
+ % end
20
+ % if show_never_candidates_section
21
+ % never_called_candidates_table = table_for(
22
+ % names_from(class_name, never_called_candidates , prefix = "#"),
23
+ % names_from(class_name, never_called_candidates_c, prefix = "."))
24
+ % end
25
+ %
26
+ % # Always hide empty tables :
27
+ % ###########################
28
+ % show_good_candidates_section &&= !good_candidates_table.empty?
29
+ % show_bad_candidates_section &&= !bad_candidates_table.empty?
30
+ % show_never_candidates_section &&= !never_called_candidates_table.empty?
31
+ %
32
+ % nothing_to_show = !(show_good_candidates_section || show_bad_candidates_section || show_never_candidates_section)
33
+ % next if nothing_to_show && !show_empty_classes?
34
+ %
35
+ <%= class_name
36
+ %>
37
+ %
38
+ % if show_good_candidates_section
39
+ % t = good_candidates_table
40
+
41
+ * Good candidates : can be made private :
42
+ ------------------------------------------
43
+ % cell_width = 3 + [38, t.longest_value_length].max
44
+ % t.rows.each do |inst_m, class_m|
45
+ <%= inst_m && inst_m.ljust(cell_width) %><%= class_m && class_m.ljust(cell_width) %>
46
+ % end
47
+ % end
48
+ %
49
+ % if show_bad_candidates_section
50
+ % t = bad_candidates_table
51
+
52
+ * Bad candidates : must stay public/protected:
53
+ . . . . . . . . . . . . . . . . . . . . .
54
+ % cell_width = 3 + [38, t.longest_value_length].max
55
+ % t.rows.each do |inst_m, class_m|
56
+ <%= inst_m && inst_m.ljust(cell_width) %><%= class_m && class_m.ljust(cell_width) %>
57
+ % end
58
+ % end
59
+ %
60
+ % if show_never_candidates_section
61
+ % t = never_called_candidates_table
62
+
63
+ * Methods that were never called :
64
+ . . . . . . . . . . . . . . . . . . . . .
65
+ % cell_width = 3 + [38, t.longest_value_length].max
66
+ % t.rows.each do |inst_m, class_m|
67
+ <%= inst_m && inst_m.ljust(cell_width) %><%= class_m && class_m.ljust(cell_width) %>
68
+ % end
69
+ % end
70
+ %
71
+ % end
72
+
73
+ ====================================================================================
74
+ % if ENV['PP_OPTIONS']
75
+ Default display overriden :
76
+ $PP_OPTIONS = <%= ENV['PP_OPTIONS'].inspect %>
77
+ % end
@@ -0,0 +1,8 @@
1
+ module PrivatePlease
2
+ module Reporter
3
+
4
+ end
5
+ end
6
+
7
+ require File.dirname(__FILE__) + '/reporter/base'
8
+ require File.dirname(__FILE__) + '/reporter/simple_text'
@@ -1,3 +1,4 @@
1
+ require 'set'
1
2
  module PrivatePlease
2
3
  module Storage
3
4
 
@@ -0,0 +1,8 @@
1
+ module PrivatePlease
2
+ module Storage
3
+ end
4
+ end
5
+ require File.dirname(__FILE__) + '/storage/calls_store'
6
+ require File.dirname(__FILE__) + '/storage/candidates_store'
7
+ require File.dirname(__FILE__) + '/storage/methods_names'
8
+ require File.dirname(__FILE__) + '/storage/methods_names_bucket'
@@ -2,16 +2,9 @@ module PrivatePlease ; module Tracking
2
2
 
3
3
  module Extension
4
4
 
5
- def private_please(*methods_to_observe)
6
- parameterless_call = methods_to_observe.empty?
7
- klass = self
8
-
9
- if parameterless_call
10
- klass.send :include, PrivatePlease::Tracking::InstrumentsAllBelow
11
-
12
- else
13
- Instrumentor.instrument_instance_methods_for_pp_observation(klass, methods_to_observe)
14
- end
5
+ def private_please
6
+ include PrivatePlease::Tracking::InstrumentsAllMethodsBelow
7
+ set_trace_func PrivatePlease::Tracking::LineChangeTracker::MY_TRACE_FUN
15
8
  end
16
9
 
17
10
  end
@@ -1,71 +1,49 @@
1
1
  module PrivatePlease ; module Tracking
2
2
 
3
3
  module Instrumentor
4
+ class << self
4
5
 
5
- def self.instrument_instance_methods_for_pp_observation(klass, methods_to_observe)
6
- class_instance_methods = klass.instance_methods.collect(&:to_sym)
7
- methods_to_observe = methods_to_observe.collect(&:to_sym)
8
- # reject invalid methods names
9
- methods_to_observe.reject! do |m|
10
- already_defined_instance_method = class_instance_methods.include?(m)
11
- invalid = !already_defined_instance_method
12
- end
13
-
14
- methods_to_observe.each do |method_name|
15
- candidate = Candidate.for_instance_method(klass, method_name)
16
- instrument_candidate_for_pp_observation(candidate) # end
17
- end
18
- end
19
-
20
-
21
- def self.instrument_candidate_for_pp_observation(candidate)
6
+ def add_call_tracking_code_to(candidate)
22
7
  return if candidate.already_instrumented?
23
- PrivatePlease.remember_candidate(candidate)
8
+ candidate.mark_as_instrumented
24
9
 
25
10
  klass, method_name = candidate.klass, candidate.method_name
26
11
  candidate.instance_method? ?
27
- instrument_instance_method_with_pp_observation(klass, method_name) :
28
- instrument_class_method_with_pp_observation( klass, method_name)
12
+ add_call_tracking_code_to_instance_method(klass, method_name) :
13
+ add_call_tracking_code_to_class_method( klass, method_name)
29
14
  end
30
15
 
31
16
 
17
+ private
32
18
 
33
- def self.instrument_class_method_with_pp_observation(klass, method_name)
19
+ def add_call_tracking_code_to_class_method(klass, method_name)
34
20
  orig_method = klass.singleton_class.instance_method(method_name)
35
21
  klass.class_eval <<RUBY
36
22
  define_singleton_method(method_name) do |*args, &blk| # def self.observed_method_i(..)
37
23
  set_trace_func(nil) #don't track activity while here #
38
- #
39
- zelf_class=self #
40
- candidate = PrivatePlease::Candidate.for_class_method(zelf_class, method_name)
41
- PrivatePlease.after_method_call(candidate, LineChangeTracker.outside_class_method_call_detected?(zelf_class))
42
- #
24
+ PrivatePlease::Tracking.after_singleton_method_call(method_name, self_class=self)
43
25
  set_trace_func(LineChangeTracker::MY_TRACE_FUN) #
44
- # make the call : #
26
+ # make the original call : #
45
27
  orig_method.bind(self).call(*args, &blk) # <call original method>
46
28
  end # end
47
29
  RUBY
48
30
  end
49
- private_class_method :instrument_class_method_with_pp_observation
50
31
 
51
32
 
52
- def self.instrument_instance_method_with_pp_observation(klass, method_name)
33
+ def add_call_tracking_code_to_instance_method(klass, method_name)
53
34
  orig_method = klass.instance_method(method_name)
54
35
  klass.class_eval <<RUBY
55
36
  define_method(method_name) do |*args, &blk| # def observed_method_i(..)
56
37
  set_trace_func(nil) #don't track activity while here #
57
- #
58
- candidate = PrivatePlease::Candidate.for_instance_method(self.class, method_name)
59
- PrivatePlease.after_method_call(candidate, LineChangeTracker.outside_instance_method_call_detected?(self)) #
60
- #
38
+ PrivatePlease::Tracking.after_instance_method_call(method_name, self.class)
61
39
  set_trace_func(LineChangeTracker::MY_TRACE_FUN) #
62
- # make the call : #
40
+ # make the original call : #
63
41
  orig_method.bind(self).call(*args, &blk) # <call original method>
64
42
  end # end
65
43
  RUBY
66
44
  end
67
- private_class_method :instrument_instance_method_with_pp_observation
68
45
 
69
46
  end
47
+ end
70
48
 
71
49
  end end
@@ -0,0 +1,28 @@
1
+ module PrivatePlease ; module Tracking
2
+
3
+ module InstrumentsAllMethodsBelow
4
+ include PrivatePlease::Tracking::Extension
5
+
6
+ def self.included(base)
7
+
8
+ def base.singleton_method_added(method_name)
9
+ return if Utils.private_singleton_method?(self, method_name) \
10
+ || Utils.singleton_method_defined_by_ancestor?(self, method_name)
11
+
12
+ candidate = Candidate.for_class_method(klass = self, method_name)
13
+ Instrumentor.add_call_tracking_code_to(candidate)
14
+ end
15
+
16
+
17
+ def base.method_added(method_name)
18
+ return if Utils.private_instance_method?(self, method_name) \
19
+ || Utils.instance_method_defined_by_ancestor?(self, method_name)
20
+
21
+ candidate = Candidate.for_instance_method(klass = self, method_name)
22
+ Instrumentor.add_call_tracking_code_to(candidate)
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end end
@@ -0,0 +1,52 @@
1
+
2
+ class Class
3
+
4
+ def singleton_method_added(method_name)
5
+ return unless PrivatePlease.pp_automatic_mode_enabled?
6
+
7
+ return if PrivatePlease::Tracking::Utils.private_singleton_method?(self, method_name) \
8
+ || PrivatePlease::Tracking::Utils.singleton_method_defined_by_ancestor?(self, method_name)
9
+
10
+ candidate = PrivatePlease::Candidate.for_class_method(klass = self, method_name)
11
+ PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
12
+ end
13
+
14
+
15
+ def method_added(method_name)
16
+ return unless PrivatePlease.pp_automatic_mode_enabled?
17
+
18
+ return if [:method_added].include?(method_name)
19
+ return if PrivatePlease::Tracking::Utils.private_instance_method?(self, method_name) \
20
+ || PrivatePlease::Tracking::Utils.instance_method_defined_by_ancestor?(self, method_name)
21
+
22
+ candidate = PrivatePlease::Candidate.for_instance_method(klass = self, method_name)
23
+ PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
24
+ end
25
+
26
+ end
27
+
28
+
29
+ class Module
30
+
31
+ def singleton_method_added(method_name)
32
+ return unless PrivatePlease.pp_automatic_mode_enabled?
33
+
34
+ return if [:included].include?(method_name) #&& !self.is_a?(Class)
35
+ return if PrivatePlease::Tracking::Utils.private_singleton_method?(self, method_name)
36
+
37
+ candidate = PrivatePlease::Candidate.for_class_method(klass = self, method_name)
38
+ PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
39
+ end
40
+
41
+
42
+ def method_added(method_name)
43
+ return unless PrivatePlease.pp_automatic_mode_enabled?
44
+
45
+ return if [:method_added, :singleton_method_added].include?(method_name)
46
+ return if PrivatePlease::Tracking::Utils.private_instance_method?(self, method_name)
47
+
48
+ candidate = PrivatePlease::Candidate.for_instance_method(klass = self, method_name)
49
+ PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
50
+ end
51
+ end
52
+
@@ -2,8 +2,15 @@ module PrivatePlease ; module Tracking
2
2
 
3
3
  class LineChangeTracker
4
4
  class << self
5
+
5
6
  attr_accessor :prev_prev_self, :prev_self, :curr_self
6
7
  @@prev_self = @@curr_self = nil
8
+
9
+ alias :call_initiator :prev_self
10
+
11
+ def reset
12
+ prev_prev_self = prev_self = curr_self = nil
13
+ end
7
14
  end
8
15
 
9
16
  MY_TRACE_FUN = lambda do |event, file, line, id, binding, klass|
@@ -14,23 +21,6 @@ module PrivatePlease ; module Tracking
14
21
  #puts "my : #{event} in #{file}/#{line} id:#{id} klass:#{klass} - self = #{(eval'self', binding).inspect}"
15
22
  end
16
23
 
17
- def self.outside_instance_method_call_detected?(zelf)
18
- caller_class != zelf.class
19
- end
20
-
21
- def self.outside_class_method_call_detected?(zelf_class)
22
- caller_class != zelf_class
23
- end
24
-
25
- private
26
-
27
- def self.caller_class
28
- call_initiator = LineChangeTracker.prev_self
29
- (caller_is_class_method = call_initiator.is_a?(Class)) ?
30
- call_initiator :
31
- call_initiator.class
32
- end
33
24
  end
34
- end end
35
25
 
36
- set_trace_func(PrivatePlease::Tracking::LineChangeTracker::MY_TRACE_FUN) #
26
+ end end
@@ -0,0 +1,34 @@
1
+ module PrivatePlease::Tracking
2
+
3
+ module Utils
4
+ class << self
5
+
6
+ def private_instance_method?(klass, method_name)
7
+ klass.private_method_defined?(method_name)
8
+ end
9
+
10
+ def private_singleton_method?(klass, method_name)
11
+ klass.singleton_class.private_method_defined?(method_name)
12
+ end
13
+
14
+ def instance_method_defined_by_ancestor?(klass, method_name)
15
+ ancestor_of(klass).any? do |a|
16
+ a.method_defined?(method_name) || a.private_method_defined?(method_name)
17
+ end
18
+ end
19
+
20
+ def singleton_method_defined_by_ancestor?(klass, method_name)
21
+ ancestor_of(klass).any? do |a|
22
+ a.singleton_class.method_defined?(method_name) || a.singleton_class.private_method_defined?(method_name)
23
+ end
24
+ end
25
+
26
+ private
27
+ def ancestor_of(klass)
28
+ klass.ancestors - [klass]
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,48 @@
1
+ require 'private_please/tracking/line_change_tracker'
2
+ module PrivatePlease
3
+ module Tracking
4
+
5
+ class << self
6
+
7
+ def after_instance_method_call(method_name, zelf_class)
8
+ store_call_to_tracked_method(
9
+ candidate = PrivatePlease::Candidate.for_instance_method(zelf_class, method_name),
10
+ is_outside_call = (caller_class != zelf_class)
11
+ )
12
+ end
13
+
14
+ def after_singleton_method_call(method_name, zelf_class)
15
+ store_call_to_tracked_method(
16
+ candidate = PrivatePlease::Candidate.for_class_method(zelf_class, method_name),
17
+ is_outside_call = (caller_class != zelf_class)
18
+ )
19
+ end
20
+
21
+ private
22
+
23
+ def caller_class
24
+ call_initiator = LineChangeTracker.call_initiator
25
+ if call_initiator.nil?
26
+ #TODO : investigate why and how this happens
27
+ end
28
+ (caller_is_class_method = call_initiator.is_a?(Class)) ?
29
+ call_initiator :
30
+ call_initiator.class
31
+ end
32
+
33
+ def store_call_to_tracked_method(candidate, is_outside_call)
34
+ is_outside_call ?
35
+ PrivatePlease.calls_store.store_outside_call(candidate) :
36
+ PrivatePlease.calls_store.store_inside_call( candidate)
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+
44
+ require 'private_please/tracking/utils'
45
+ require 'private_please/tracking/instrumentor'
46
+ require 'private_please/tracking/extension'
47
+ require 'private_please/tracking/instruments_all_methods_below'
48
+ require 'private_please/tracking/instruments_automatically_all_methods_in_all_classes'
@@ -1,3 +1,3 @@
1
1
  module PrivatePlease
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -1,66 +1,49 @@
1
1
  require 'private_please/version'
2
2
  require 'private_please/ruby_backports'
3
3
  require 'private_please/candidate'
4
- require 'private_please/storage/calls_store'
5
- require 'private_please/storage/candidates_store'
6
- require 'private_please/storage/methods_names'
7
- require 'private_please/storage/methods_names_bucket'
8
- require 'private_please/report/reporter'
9
- require 'private_please/tracking/line_change_tracker'
10
- require 'private_please/tracking/extension'
11
- require 'private_please/tracking/instrumentor'
12
- require 'private_please/tracking/instruments_all_below'
4
+ require 'private_please/storage'
5
+ require 'private_please/report'
6
+ require 'private_please/reporter'
7
+
8
+ at_exit do
9
+ PrivatePlease.at_exit
10
+ end
13
11
 
14
12
  module PrivatePlease
15
13
 
16
14
  def self.install
17
15
  Module.send :include, PrivatePlease::Tracking::Extension
16
+ PrivatePlease.pp_automatic_mode_enable
17
+ set_trace_func PrivatePlease::Tracking::LineChangeTracker::MY_TRACE_FUN
18
18
  end
19
19
 
20
- #--------------
21
- # config
22
- #--------------
23
-
24
- def self.after_method_call(candidate, outside_call)
25
- outside_call ?
26
- calls_store.store_outside_call(candidate) :
27
- calls_store.store_inside_call(candidate)
28
- end
29
-
30
- def self.remember_candidate(candidate)
31
- candidates_store.store(candidate)
32
- end
33
-
34
-
35
- #--------------
36
- # data & config containers :
37
- #--------------
20
+ def self.pp_automatic_mode_enabled? ; !!$pp_automatic_mode_enabled end
21
+ def self.pp_automatic_mode_enable ; $pp_automatic_mode_enabled = true end
22
+ def self.pp_automatic_mode_disable ; $pp_automatic_mode_enabled = false end
38
23
 
39
- def self.reset_before_new_test
40
- @@_calls_store = @@_candidates_store = nil
24
+ # TODO : replace class methods by PP instance + instance methods
25
+ def self.calls_store
26
+ @@_calls_store ||= Storage::CallsStore.new
41
27
  end
42
28
 
43
- #--------------
44
- # report
45
- #--------------
46
-
47
- def self.report
48
- Report::Reporter.new(candidates_store, calls_store)
29
+ def self.candidates_store
30
+ @@_candidates_store ||= Storage::CandidatesStore.new
49
31
  end
50
32
 
51
- private
52
-
53
- def self.calls_store
54
- @@_calls_store ||= Storage::CallsStore.new
33
+ def self.reset
34
+ @@_candidates_store = @@_calls_store = nil
35
+ Tracking::LineChangeTracker.reset
36
+ set_trace_func nil
55
37
  end
56
38
 
57
- def self.candidates_store
58
- @@_candidates_store ||= Storage::CandidatesStore.new
39
+ def self.at_exit
40
+ report = PrivatePlease::Reporter::SimpleText.new(PrivatePlease.candidates_store, PrivatePlease.calls_store)
41
+ unless $private_please_tests_are_running
42
+ $stdout.puts report.text
43
+ end
59
44
  end
60
45
  end
61
46
 
47
+ require 'private_please/tracking'
62
48
 
63
49
  PrivatePlease.install
64
- at_exit {
65
- puts PrivatePlease.report.to_s
66
- }
@@ -1,5 +1,11 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/private_please/version', __FILE__)
2
+ if RUBY_VERSION == '1.8.7'
3
+ # avoid double-require of version.rb - see http://bit.ly/18lspBV
4
+ $:.unshift File.expand_path("../lib", __FILE__)
5
+ require "private_please/version"
6
+ else
7
+ require File.expand_path('../lib/private_please/version', __FILE__)
8
+ end
3
9
 
4
10
  Gem::Specification.new do |gem|
5
11
  gem.authors = ["Alain Ravet"]