private_please 0.0.5 → 0.1.0

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 (89) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +3 -5
  4. data/CHANGELOG +4 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +58 -98
  8. data/Rakefile +6 -2
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/lib/private_please/config.rb +15 -0
  12. data/lib/private_please/methods_calls_tracker.rb +44 -0
  13. data/lib/private_please/reporting/simple_text.rb +43 -0
  14. data/lib/private_please/reporting/templates/simple.txt.erb +11 -0
  15. data/lib/private_please/storage/called_methods_memory_store.rb +20 -0
  16. data/lib/private_please/tracking/debug/trace_point_data_logger.rb +81 -0
  17. data/lib/private_please/tracking/method_details.rb +27 -0
  18. data/lib/private_please/tracking/result.rb +25 -0
  19. data/lib/private_please/tracking/trace_point_details.rb +41 -0
  20. data/lib/private_please/tracking/trace_point_processor.rb +71 -0
  21. data/lib/private_please/utils/ruby_utils.rb +44 -0
  22. data/lib/private_please/utils/source_file_utils.rb +20 -0
  23. data/lib/private_please/utils/two_level_stack.rb +13 -0
  24. data/lib/private_please/version.rb +2 -1
  25. data/lib/private_please.rb +27 -34
  26. data/private_please.gemspec +32 -25
  27. metadata +106 -185
  28. data/Guardfile +0 -8
  29. data/LICENSE +0 -22
  30. data/TODO +0 -20
  31. data/bin/pp_ruby +0 -62
  32. data/bin/ruby_pp +0 -62
  33. data/doc/dev_notes.txt +0 -32
  34. data/doc/fixtures/complex.rb +0 -103
  35. data/doc/fixtures/empty_class.rb +0 -7
  36. data/doc/fixtures/fixture_helper.rb +0 -8
  37. data/doc/fixtures/sample.rb +0 -57
  38. data/lib/private_please/candidate.rb +0 -49
  39. data/lib/private_please/report/table.rb +0 -44
  40. data/lib/private_please/report.rb +0 -6
  41. data/lib/private_please/reporter/base.rb +0 -14
  42. data/lib/private_please/reporter/data_compiler.rb +0 -82
  43. data/lib/private_please/reporter/helpers/options_helpers.rb +0 -37
  44. data/lib/private_please/reporter/helpers/text_table_helpers.rb +0 -9
  45. data/lib/private_please/reporter/simple_text.rb +0 -18
  46. data/lib/private_please/reporter/templates/simple.txt.erb +0 -80
  47. data/lib/private_please/reporter.rb +0 -8
  48. data/lib/private_please/ruby_backports.rb +0 -22
  49. data/lib/private_please/storage/calls_store.rb +0 -41
  50. data/lib/private_please/storage/candidates_store.rb +0 -52
  51. data/lib/private_please/storage/methods_names.rb +0 -10
  52. data/lib/private_please/storage/methods_names_bucket.rb +0 -69
  53. data/lib/private_please/storage.rb +0 -8
  54. data/lib/private_please/tracking/extension.rb +0 -12
  55. data/lib/private_please/tracking/instrumentor.rb +0 -49
  56. data/lib/private_please/tracking/instruments_all_methods_below.rb +0 -28
  57. data/lib/private_please/tracking/instruments_automatically_all_methods_in_all_classes.rb +0 -68
  58. data/lib/private_please/tracking/line_change_tracker.rb +0 -26
  59. data/lib/private_please/tracking/load_utils/gem_utils.rb +0 -49
  60. data/lib/private_please/tracking/load_utils/standard_lib_utils.rb +0 -38
  61. data/lib/private_please/tracking/load_utils.rb +0 -32
  62. data/lib/private_please/tracking/utils.rb +0 -34
  63. data/lib/private_please/tracking.rb +0 -49
  64. data/sample.rb +0 -68
  65. data/spec/01_tracking_candidate_methods/excluding_gems_and_standard_libraries_spec.rb +0 -31
  66. data/spec/01_tracking_candidate_methods/explicitely_with_the_private_please_command_spec.rb +0 -118
  67. data/spec/01_tracking_candidate_methods/load_utils_spec.rb +0 -40
  68. data/spec/01_tracking_candidate_methods/systematically_in_auto_mode_spec.rb +0 -185
  69. data/spec/03_logging_calls_on_candidate_methods_spec.rb +0 -37
  70. data/spec/04_instrumented_program_activity_observation_result_spec.rb +0 -86
  71. data/spec/05_reporting/report_table_spec.rb +0 -51
  72. data/spec/06_at_exit_spec.rb +0 -18
  73. data/spec/_helpers/assert_helpers.rb +0 -76
  74. data/spec/fixtures/bug_22.rb +0 -17
  75. data/spec/fixtures/bug_30.rb +0 -6
  76. data/spec/fixtures/issue_25.rb +0 -12
  77. data/spec/fixtures/sample_class_for_report.rb +0 -56
  78. data/spec/fixtures/sample_class_with_all_calls_combinations.rb +0 -69
  79. data/spec/sandbox/Gemfile +0 -4
  80. data/spec/sandbox/Gemfile.lock +0 -14
  81. data/spec/sandbox/README.txt +0 -26
  82. data/spec/sandbox/normal.rb +0 -7
  83. data/spec/sandbox/normal_prepended_with_require.rb +0 -8
  84. data/spec/spec_helper.rb +0 -38
  85. data/spec/units/calls_store_spec.rb +0 -15
  86. data/spec/units/candidates_store_spec.rb +0 -55
  87. data/spec/units/reporter/data_compiler_spec.rb +0 -12
  88. data/spec/units/reporter/fixtures/simple_case_1.rb +0 -30
  89. data/spec/units/reporter/fixtures/simple_case_2.rb +0 -55
@@ -1,69 +0,0 @@
1
- # Associates and indexes classes (name) and some of their methods (names).
2
- # Ex:
3
- # +-------------+---------------------------------------+
4
- # | class name => 1+ methods names |
5
- # +-------------+---------------------------------------+
6
- # | 'Foo' | MethodsNames.new('foo to_baz to_bar') |
7
- # | 'Bar' | MethodsNames.new('qux') |
8
- # +-------------+---------------------------------------+
9
-
10
- module PrivatePlease
11
- module Storage
12
-
13
- class MethodsNamesBucket < Hash
14
-
15
- def initialize
16
- super{|hash, class_name|
17
- #hash[class_name] = PrivatePlease::Storage::MethodsNames.new
18
- hash.set_methods_names(class_name, MethodsNames.new)
19
- }
20
- end
21
-
22
- def clone
23
- (self.class).new.tap do |klone|
24
- classes_names.each do |class_name|
25
- klone.set_methods_names(class_name, (self).get_methods_names(class_name))
26
- end
27
- end
28
- end
29
-
30
- #--------------------------------------------------------------------------
31
- # QUERIES:
32
- #--------------------------------------------------------------------------
33
-
34
- alias_method :classes_names, :keys
35
- alias_method :get_methods_names, :[]
36
- # undef :[], :keys # should be undef-ed, but that complexifies the test #TODO : undef :[], :keys
37
- # ( => must define ==(other) and cast type of 'other')
38
-
39
- #--------------------------------------------------------------------------
40
- # COMMANDS:
41
- #--------------------------------------------------------------------------
42
-
43
- alias_method :set_methods_names, :[]=
44
- undef :[]=
45
-
46
- def add_method_name(class_name, method_name)
47
- self.get_methods_names(class_name).add(method_name)
48
- end
49
-
50
- def remove(other)
51
- other.classes_names.each do |cn|
52
- next if (methods_to_remove = other.get_methods_names(cn)).empty?
53
- next if (methods_before = self .get_methods_names(cn)).empty?
54
- difference = methods_before - methods_to_remove
55
- self.set_methods_names(cn, difference)
56
- end
57
- prune!
58
- self
59
- end
60
-
61
- private
62
-
63
- def prune!
64
- self.reject!{|_, v|v.empty?}
65
- end
66
- end
67
-
68
- end
69
- end
@@ -1,8 +0,0 @@
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'
@@ -1,12 +0,0 @@
1
- module PrivatePlease ; module Tracking
2
-
3
- module Extension
4
-
5
- def private_please
6
- include PrivatePlease::Tracking::InstrumentsAllMethodsBelow
7
- set_trace_func PrivatePlease::Tracking::LineChangeTracker::MY_TRACE_FUN
8
- end
9
-
10
- end
11
-
12
- end end
@@ -1,49 +0,0 @@
1
- module PrivatePlease ; module Tracking
2
-
3
- module Instrumentor
4
- class << self
5
-
6
- def add_call_tracking_code_to(candidate)
7
- return if candidate.already_instrumented?
8
- candidate.mark_as_instrumented
9
-
10
- klass, method_name = candidate.klass, candidate.method_name
11
- candidate.instance_method? ?
12
- add_call_tracking_code_to_instance_method(klass, method_name) :
13
- add_call_tracking_code_to_class_method( klass, method_name)
14
- end
15
-
16
-
17
- private
18
-
19
- def add_call_tracking_code_to_class_method(klass, method_name)
20
- orig_method = klass.singleton_class.instance_method(method_name)
21
- klass.class_eval <<RUBY
22
- define_singleton_method(method_name) do |*args, &blk| # def self.observed_method_i(..)
23
- set_trace_func(nil) #don't track activity while here #
24
- PrivatePlease::Tracking.after_singleton_method_call(method_name, self_class=self)
25
- set_trace_func(LineChangeTracker::MY_TRACE_FUN) #
26
- # make the original call : #
27
- orig_method.bind(self).call(*args, &blk) # <call original method>
28
- end # end
29
- RUBY
30
- end
31
-
32
-
33
- def add_call_tracking_code_to_instance_method(klass, method_name)
34
- orig_method = klass.instance_method(method_name)
35
- klass.class_eval <<RUBY
36
- define_method(method_name) do |*args, &blk| # def observed_method_i(..)
37
- set_trace_func(nil) #don't track activity while here #
38
- PrivatePlease::Tracking.after_instance_method_call(method_name, self.class)
39
- set_trace_func(LineChangeTracker::MY_TRACE_FUN) #
40
- # make the original call : #
41
- orig_method.bind(self).call(*args, &blk) # <call original method>
42
- end # end
43
- RUBY
44
- end
45
-
46
- end
47
- end
48
-
49
- end end
@@ -1,28 +0,0 @@
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
@@ -1,68 +0,0 @@
1
- module Kernel
2
-
3
- alias_method :_orig_require, :require
4
-
5
- def require string
6
- prev_val = PrivatePlease.pp_automatic_mode_enabled?
7
- if PrivatePlease::Tracking::LoadUtils.standard_lib_or_gem?(string)
8
- PrivatePlease.pp_automatic_mode_disable
9
- end
10
-
11
- send :_orig_require, string
12
-
13
- PrivatePlease.pp_automatic_mode_enable(prev_val)
14
- end
15
-
16
- end
17
-
18
- class Class
19
-
20
- def singleton_method_added(method_name)
21
- return unless PrivatePlease.pp_automatic_mode_enabled?
22
-
23
- return if PrivatePlease::Tracking::Utils.private_singleton_method?(self, method_name) \
24
- || PrivatePlease::Tracking::Utils.singleton_method_defined_by_ancestor?(self, method_name)
25
-
26
- candidate = PrivatePlease::Candidate.for_class_method(klass = self, method_name)
27
- PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
28
- end
29
-
30
-
31
- def method_added(method_name)
32
- return unless PrivatePlease.pp_automatic_mode_enabled?
33
-
34
- return if [:method_added].include?(method_name)
35
- return if PrivatePlease::Tracking::Utils.private_instance_method?(self, method_name) \
36
- || PrivatePlease::Tracking::Utils.instance_method_defined_by_ancestor?(self, method_name)
37
-
38
- candidate = PrivatePlease::Candidate.for_instance_method(klass = self, method_name)
39
- PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
40
- end
41
-
42
- end
43
-
44
-
45
- class Module
46
-
47
- def singleton_method_added(method_name)
48
- return unless PrivatePlease.pp_automatic_mode_enabled?
49
-
50
- return if [:included].include?(method_name) #&& !self.is_a?(Class)
51
- return if PrivatePlease::Tracking::Utils.private_singleton_method?(self, method_name)
52
-
53
- candidate = PrivatePlease::Candidate.for_class_method(klass = self, method_name)
54
- PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
55
- end
56
-
57
-
58
- def method_added(method_name)
59
- return unless PrivatePlease.pp_automatic_mode_enabled?
60
-
61
- return if [:method_added, :singleton_method_added].include?(method_name)
62
- return if PrivatePlease::Tracking::Utils.private_instance_method?(self, method_name)
63
-
64
- candidate = PrivatePlease::Candidate.for_instance_method(klass = self, method_name)
65
- PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
66
- end
67
- end
68
-
@@ -1,26 +0,0 @@
1
- module PrivatePlease ; module Tracking
2
-
3
- class LineChangeTracker
4
- class << self
5
-
6
- attr_accessor :prev_prev_self, :prev_self, :curr_self
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
14
- end
15
-
16
- MY_TRACE_FUN = lambda do |event, file, line, id, binding, klass|
17
- return unless 'line'==event
18
- LineChangeTracker.prev_prev_self = LineChangeTracker.prev_self
19
- LineChangeTracker.prev_self = LineChangeTracker.curr_self
20
- LineChangeTracker.curr_self = (eval 'self', binding)
21
- #puts "my : #{event} in #{file}/#{line} id:#{id} klass:#{klass} - self = #{(eval'self', binding).inspect}"
22
- end
23
-
24
- end
25
-
26
- end end
@@ -1,49 +0,0 @@
1
- # OPTIMISATION :
2
- # Calls to `$ gem ..` are slow (esp. on jruby!)
3
- # => we 1/ pre-perform them asynchronously (Threads) when this file is loaded,
4
- # 2/ cache the obtained value in a variable,
5
- # 3/ rewrite the slow method as a noop version that simply returns the cached value.
6
-
7
- module PrivatePlease::Tracking::LoadUtils
8
-
9
- module GemUtils
10
-
11
- class << self
12
-
13
- # performs `$ gem env`
14
- #
15
- def gem_env
16
- GEM_ENV_PRELOADER.join
17
- gem_env # call the fast/just rewritten version
18
- end
19
-
20
- # performs `$ gem list` + extracts the names
21
- #
22
- def gems_names
23
- GEMS_NAMES_PRELOADER.join
24
- gems_names
25
- end
26
-
27
- #-------------------------------------------------------------------------------------------------------------------
28
- private
29
-
30
- GEM_ENV_PRELOADER = Thread.new do
31
- @@_cached_gem_env = `gem env`
32
- def GemUtils.gem_env
33
- @@_cached_gem_env
34
- end
35
- end
36
-
37
- GEMS_NAMES_PRELOADER = Thread.new do
38
- @@_cached_gems_names = `gem list`. # very slow on jruby
39
- split("\n").
40
- map { |l| l.match(/(\S+)\s+.*/)[1]} # ["bundle", "bundler", "rspec", ..]
41
- def GemUtils.gems_names
42
- @@_cached_gems_names
43
- end
44
- end
45
-
46
- end
47
- end
48
-
49
- end
@@ -1,38 +0,0 @@
1
- module PrivatePlease::Tracking::LoadUtils
2
-
3
- module StandardLibUtils
4
-
5
- class << self
6
-
7
- def standard_lib?(requiree)
8
- path_base = "#{std_lib_home}/#{requiree}"
9
- if File.exists?(path_base)
10
- path_base
11
- elsif File.exists?("#{path_base}.rb")
12
- "#{path_base}.rb"
13
- end
14
- end
15
-
16
- #-------------------------------------------------------------------------------------------------------------------
17
- private
18
-
19
- # Ex: "/Users/ara/.rbenv/versions/jruby-1.7.3/bin/jruby"
20
- def ruby_executable
21
- @@_ruby_executable ||= GemUtils.gem_env.match(/RUBY EXECUTABLE:\s*(.*)/)[1]
22
- end
23
-
24
- # Ex: "/Users/ara/.rbenv/versions/jruby-1.7.3/lib/ruby/1.9"
25
- def std_lib_home
26
- @@_std_lib_home ||= begin
27
- basedir = ruby_executable.gsub(/bin\/[j]?ruby/, 'lib/ruby') # => "/Users/ara/.rbenv/versions/jruby-1.7.3/lib/ruby"
28
- # jruby has 2+ directories of std. libs under the basedir : 1.8 and 1.9
29
- $:.detect {|path| # We choose the one that is also in the load path.
30
- path =~ /#{basedir}\/[12][^\/]+$/ #
31
- } # => "/Users/ara/.rbenv/versions/jruby-1.7.3/lib/ruby/1.9"
32
- end # ^^^ == the mode
33
- end
34
-
35
- end
36
- end
37
-
38
- end
@@ -1,32 +0,0 @@
1
- module PrivatePlease::Tracking
2
-
3
- module LoadUtils
4
- require File.dirname(__FILE__) + '/load_utils/gem_utils'
5
- require File.dirname(__FILE__) + '/load_utils/standard_lib_utils'
6
-
7
- class << self
8
-
9
- def standard_lib_or_gem?(requiree)
10
- (@@_standard_lib_or_gem ||= {})[requiree] ||= begin
11
- standard_lib?(requiree) || gem?(requiree)
12
- end
13
- end
14
-
15
- def standard_lib?(requiree)
16
- (@@_standard_lib ||= {})[requiree] ||= StandardLibUtils.standard_lib?(requiree)
17
- end
18
-
19
- def gem?(requiree)
20
- (@@_gems ||= {})[requiree] ||= begin
21
- base_name = requiree.include?('/') ?
22
- requiree.split('/').first : # ex: require 'rspec/autorun'
23
- requiree # ex: require 'rspec'
24
- GemUtils.gems_names.include?(base_name)
25
- end
26
-
27
- end
28
-
29
- end
30
- end
31
-
32
- end
@@ -1,34 +0,0 @@
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
@@ -1,49 +0,0 @@
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/load_utils'
46
- require 'private_please/tracking/instrumentor'
47
- require 'private_please/tracking/extension'
48
- require 'private_please/tracking/instruments_all_methods_below'
49
- require 'private_please/tracking/instruments_automatically_all_methods_in_all_classes'