delfos 0.0.1.pre.rc1 → 0.0.1

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/delfos.rb +22 -78
  3. data/lib/delfos/call_stack.rb +39 -0
  4. data/lib/delfos/call_stack/stack.rb +59 -0
  5. data/lib/delfos/file_system/common_path.rb +62 -0
  6. data/lib/delfos/{distance/calculation.rb → file_system/distance_calculation.rb} +4 -15
  7. data/lib/delfos/file_system/path_determination.rb +37 -0
  8. data/lib/delfos/{distance → file_system}/relation.rb +1 -1
  9. data/lib/delfos/method_logging.rb +32 -49
  10. data/lib/delfos/method_logging/call_site_parsing.rb +74 -0
  11. data/lib/delfos/method_logging/code_location.rb +34 -98
  12. data/lib/delfos/method_logging/{args.rb → method_parameters.rb} +17 -18
  13. data/lib/delfos/neo4j.rb +58 -0
  14. data/lib/delfos/neo4j/batch/execution.rb +149 -0
  15. data/lib/delfos/neo4j/{execution_persistence.rb → call_stack_query.rb} +12 -22
  16. data/lib/delfos/neo4j/distance/call_site_fetcher.rb +19 -0
  17. data/lib/delfos/neo4j/distance/update.rb +50 -0
  18. data/lib/delfos/neo4j/informer.rb +62 -34
  19. data/lib/delfos/neo4j/query_execution/errors.rb +30 -0
  20. data/lib/delfos/neo4j/query_execution/http.rb +61 -0
  21. data/lib/delfos/neo4j/query_execution/http_query.rb +67 -0
  22. data/lib/delfos/neo4j/query_execution/sync.rb +35 -0
  23. data/lib/delfos/neo4j/query_execution/transactional.rb +68 -0
  24. data/lib/delfos/neo4j/schema.rb +73 -0
  25. data/lib/delfos/patching/basic_object.rb +1 -5
  26. data/lib/delfos/patching/method_cache.rb +83 -0
  27. data/lib/delfos/patching/method_override.rb +76 -66
  28. data/lib/delfos/patching/module_defining_methods.rb +105 -0
  29. data/lib/delfos/patching/unstubber.rb +34 -0
  30. data/lib/delfos/setup.rb +88 -0
  31. metadata +42 -15
  32. data/lib/delfos/common_path.rb +0 -58
  33. data/lib/delfos/execution_chain.rb +0 -75
  34. data/lib/delfos/method_logging/added_methods.rb +0 -67
  35. data/lib/delfos/neo4j/distance_update.rb +0 -73
  36. data/lib/delfos/neo4j/query_execution.rb +0 -79
  37. data/lib/delfos/patching/unstubbing_spec_helper.rb +0 -58
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+ module Delfos
3
+ module Patching
4
+ # containers for the individual modules created to log each method call
5
+ module ClassMethodLogging
6
+ end
7
+
8
+ module InstanceMethodLogging
9
+ end
10
+
11
+ module ModuleDefiningMethods
12
+ def module_definition(klass, method_name, class_method, &block)
13
+ definer = ModuleDefiner.new(klass, method_name, class_method)
14
+
15
+ if block_given?
16
+ definer.perform(&block)
17
+ else
18
+ definer.perform
19
+ end
20
+ end
21
+ end
22
+
23
+ class ModuleDefiner
24
+ attr_reader :klass, :method_name, :class_method
25
+
26
+ def initialize(klass, method_name, class_method)
27
+ @klass, @method_name, @class_method = klass, method_name, class_method
28
+ end
29
+
30
+ def perform(&block)
31
+ safe_method_name = safe_method_name()
32
+ safe_class_name = safe_class_name()
33
+ module_type = class_method ? "ClassMethodLogging" : "InstanceMethodLogging"
34
+ find_or_create = method(:find_or_create)
35
+
36
+ m = nil
37
+ Patching.const_get(module_type).instance_eval do
38
+ namespace = find_or_create.call(self, safe_class_name)
39
+
40
+ m = find_or_create.call(namespace, safe_method_name)
41
+
42
+ m.class_eval(&block) if block_given?
43
+
44
+ m
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def safe_class_name
51
+ module_safe_name(klass.name || klass.to_s)
52
+ end
53
+
54
+ def safe_method_name
55
+ module_safe_name(method_name.to_s)
56
+ end
57
+
58
+ def find_or_create(container, module_name)
59
+ module_name = module_name.tr(":", "_")
60
+
61
+ result = container.const_get(module_name)
62
+
63
+ # E.g. finding `::A' instead of Delfos::Patching::InstanceMethodLogging::A
64
+ if result == klass || result.name[module_name] == result.name
65
+ create(container, module_name)
66
+ else
67
+ result
68
+ end
69
+ rescue NameError => e
70
+ raise unless e.message[module_name]
71
+ create(container, module_name)
72
+ end
73
+
74
+ def create(container, module_name)
75
+ m = Module.new
76
+
77
+ container.const_set(module_name, m)
78
+ return m
79
+ rescue Exception => e
80
+ m
81
+ end
82
+
83
+ def module_safe_name(string, _uppercase_first_letter = true)
84
+ string = string.sub(/^[a-z\d]*/) { $&.capitalize }
85
+
86
+ string.
87
+ gsub(/(?:_|(\/))([a-z\d]*)/) { "#{Regexp.last_match(1)}#{Regexp.last_match(2).capitalize}" }.
88
+ gsub("/", "::").
89
+ gsub(/\=/, "Equals").
90
+ gsub(/\<\=\>/, "Spaceship").
91
+ gsub(/\<\=/, "LessThanOrEqualTo").
92
+ gsub(/\>\=/, "GreaterThanOrEqualTo").
93
+ gsub(/\#\<Class\:0x(.*)\>/) { "AnonymousClass_#{Regexp.last_match(1)}" }.
94
+ gsub(/\>/, "GreaterThan").
95
+ gsub(/\</, "LessThan").
96
+ gsub(/!\~/, "NotMatchOperator").
97
+ gsub(/\~/, "MatchOperator").
98
+ gsub(/\?/, "QuestionMark").
99
+ gsub(/\!$/, "Bang").
100
+ gsub(/\+/, "Plus").
101
+ gsub(/\[\]/, "SquareBrackets")
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ module Delfos
3
+ module Patching
4
+ class Unstubber
5
+ extend ModuleDefiningMethods
6
+
7
+ def self.unstub_all!
8
+ MUTEX.synchronize do
9
+ Thread.current[:__delfos_disable_patching] = true
10
+ end
11
+
12
+ MethodCache.each_method do |klass_name, method, class_method|
13
+ klass = eval(klass_name)
14
+
15
+ unstub!(klass, method.name, class_method)
16
+ end
17
+
18
+ MUTEX.synchronize do
19
+ Thread.current[:__delfos_disable_patching] = false
20
+ end
21
+ end
22
+
23
+ def self.unstub!(klass, method_name, class_method)
24
+ module_definition(klass, method_name, class_method) do |m|
25
+ begin
26
+ remove_method :"#{method_name}"
27
+ rescue NameError => e
28
+ raise unless e.message["method `#{method_name}' not defined in"]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+ module Delfos
3
+ module Setup
4
+ extend self
5
+ attr_accessor :neo4j
6
+
7
+ def perform!(call_site_logger: nil, application_directories: nil)
8
+ self.application_directories = application_directories
9
+ self.call_site_logger = call_site_logger
10
+
11
+ perform_patching!
12
+ end
13
+
14
+ def application_directories=(dirs)
15
+ dirs ||= %w(app lib)
16
+ require "pathname"
17
+ Delfos.application_directories = Array(dirs).map { |f| Pathname.new(File.expand_path(f.to_s)) }
18
+ end
19
+
20
+ def call_site_logger
21
+ @call_site_logger ||= default_call_site_logger
22
+ end
23
+
24
+ def call_site_logger=(call_site_logger)
25
+ @call_site_logger = call_site_logger || default_call_site_logger
26
+ end
27
+
28
+ def default_call_site_logger
29
+ Delfos.setup_neo4j!
30
+
31
+ require "delfos/neo4j/informer"
32
+ Delfos:: Neo4j::Informer.new
33
+ end
34
+
35
+ def reset!
36
+ if defined? Delfos::CallStack
37
+ Delfos::CallStack.pop_until_top!
38
+ Delfos::CallStack.reset!
39
+ end
40
+
41
+ if defined? Delfos::Neo4j::Batch::Execution
42
+ begin
43
+ Delfos::Neo4j::Batch::Execution.flush!
44
+ rescue
45
+ Delfos::Neo4j::QueryExecution::ExpiredTransaction
46
+ end
47
+
48
+ Delfos::Neo4j::Batch::Execution.reset!
49
+ end
50
+
51
+ # unstubbing depends upon MethodCache being still defined
52
+ # so this order is important
53
+ unstub_all!
54
+ remove_cached_methods!
55
+
56
+ remove_patching!
57
+
58
+ Delfos::MethodLogging.reset! if defined?(Delfos::MethodLogging) && Delfos::MethodLogging.respond_to?(:reset!)
59
+
60
+ Delfos.neo4j = nil
61
+ Delfos.logger = nil
62
+ Delfos.application_directories = nil
63
+ Delfos.call_site_logger = nil
64
+ @call_site_logger = nil
65
+ Delfos.neo4j = nil
66
+ end
67
+
68
+ def unstub_all!
69
+ return unless defined? Delfos::Patching::Unstubber
70
+
71
+ Delfos::Patching::Unstubber.unstub_all!
72
+ end
73
+
74
+ def remove_cached_methods!
75
+ return unless defined? Delfos::Patching::MethodCache
76
+
77
+ Delfos::Patching::MethodCache.reset!
78
+ end
79
+
80
+ def remove_patching!
81
+ load "delfos/patching/basic_object_remove.rb"
82
+ end
83
+
84
+ def perform_patching!
85
+ load "delfos/patching/basic_object.rb"
86
+ end
87
+ end
88
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delfos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre.rc1
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Burns
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-08 00:00:00.000000000 Z
11
+ date: 2016-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: binding_of_caller
@@ -30,6 +30,20 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 0.7.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: webmock
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
33
47
  - !ruby/object:Gem::Dependency
34
48
  name: pry-byebug
35
49
  requirement: !ruby/object:Gem::Requirement
@@ -99,22 +113,35 @@ extensions: []
99
113
  extra_rdoc_files: []
100
114
  files:
101
115
  - lib/delfos.rb
102
- - lib/delfos/common_path.rb
103
- - lib/delfos/distance/calculation.rb
104
- - lib/delfos/distance/relation.rb
105
- - lib/delfos/execution_chain.rb
116
+ - lib/delfos/call_stack.rb
117
+ - lib/delfos/call_stack/stack.rb
118
+ - lib/delfos/file_system/common_path.rb
119
+ - lib/delfos/file_system/distance_calculation.rb
120
+ - lib/delfos/file_system/path_determination.rb
121
+ - lib/delfos/file_system/relation.rb
106
122
  - lib/delfos/method_logging.rb
107
- - lib/delfos/method_logging/added_methods.rb
108
- - lib/delfos/method_logging/args.rb
123
+ - lib/delfos/method_logging/call_site_parsing.rb
109
124
  - lib/delfos/method_logging/code_location.rb
110
- - lib/delfos/neo4j/distance_update.rb
111
- - lib/delfos/neo4j/execution_persistence.rb
125
+ - lib/delfos/method_logging/method_parameters.rb
126
+ - lib/delfos/neo4j.rb
127
+ - lib/delfos/neo4j/batch/execution.rb
128
+ - lib/delfos/neo4j/call_stack_query.rb
129
+ - lib/delfos/neo4j/distance/call_site_fetcher.rb
130
+ - lib/delfos/neo4j/distance/update.rb
112
131
  - lib/delfos/neo4j/informer.rb
113
- - lib/delfos/neo4j/query_execution.rb
132
+ - lib/delfos/neo4j/query_execution/errors.rb
133
+ - lib/delfos/neo4j/query_execution/http.rb
134
+ - lib/delfos/neo4j/query_execution/http_query.rb
135
+ - lib/delfos/neo4j/query_execution/sync.rb
136
+ - lib/delfos/neo4j/query_execution/transactional.rb
137
+ - lib/delfos/neo4j/schema.rb
114
138
  - lib/delfos/patching/basic_object.rb
115
139
  - lib/delfos/patching/basic_object_remove.rb
140
+ - lib/delfos/patching/method_cache.rb
116
141
  - lib/delfos/patching/method_override.rb
117
- - lib/delfos/patching/unstubbing_spec_helper.rb
142
+ - lib/delfos/patching/module_defining_methods.rb
143
+ - lib/delfos/patching/unstubber.rb
144
+ - lib/delfos/setup.rb
118
145
  homepage: https://github.com/markburns/delfos
119
146
  licenses:
120
147
  - MIT
@@ -131,12 +158,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
158
  version: '0'
132
159
  required_rubygems_version: !ruby/object:Gem::Requirement
133
160
  requirements:
134
- - - ">"
161
+ - - ">="
135
162
  - !ruby/object:Gem::Version
136
- version: 1.3.1
163
+ version: '0'
137
164
  requirements: []
138
165
  rubyforge_project:
139
- rubygems_version: 2.5.1
166
+ rubygems_version: 2.5.2
140
167
  signing_key:
141
168
  specification_version: 4
142
169
  summary: Runtime type analysis
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
- require "pathname"
3
-
4
- module Delfos
5
- module CommonPath
6
- class << self
7
- SEPARATOR = "/"
8
-
9
- def included_in?(p1, paths)
10
- paths = paths.map do |p2|
11
- common = common_parent_directory_path(p1, p2)
12
- common.to_s.length >= p2.to_s.length
13
- end
14
-
15
- paths.compact.detect { |v| v }
16
- end
17
-
18
- def common_parent_directory_path(path_a, path_b)
19
- dirs = [File.expand_path(path_a.to_s), File.expand_path(path_b.to_s)]
20
-
21
- dir1, dir2 = dirs.minmax.map { |dir| dir.split(SEPARATOR) }
22
-
23
- path_from(dir1, dir2, path_a, path_b)
24
- end
25
-
26
- private
27
-
28
- def path_from(dir1, dir2, path_a, path_b)
29
- common_path = common_path(dir1, dir2)
30
- common_path, path_a, path_b = append_trailing_slashes!(common_path, path_a, path_b)
31
-
32
- Pathname.new(common_path) if valid_length?(common_path, path_a, path_b)
33
- end
34
-
35
- def valid_length?(common_path, path_a, path_b)
36
- (common_path.to_s.length <= path_a.to_s.length) || (common_path.to_s.length <= path_b.to_s.length)
37
- end
38
-
39
- def common_path(dir1, dir2)
40
- dir1.
41
- zip(dir2).
42
- take_while { |dn1, dn2| dn1 == dn2 }.
43
- map(&:first).
44
- join(SEPARATOR)
45
- end
46
-
47
- def append_trailing_slashes!(*paths)
48
- paths.map do |path|
49
- if Pathname.new(path).directory?
50
- path += SEPARATOR if path && path.to_s[-1] != SEPARATOR
51
- end
52
-
53
- path
54
- end
55
- end
56
- end
57
- end
58
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "neo4j/execution_persistence"
3
-
4
- module Delfos
5
- class ExecutionChain
6
- EXECUTION_CHAIN_MUTEX = Mutex.new
7
-
8
- def self.reset!
9
- EXECUTION_CHAIN_MUTEX.synchronize do
10
- Thread.current[:_delfos__execution_chain] = nil
11
- end
12
- end
13
-
14
- def self.execution_chain
15
- EXECUTION_CHAIN_MUTEX.synchronize do
16
- Thread.current[:_delfos__execution_chain] ||= new
17
- end
18
- end
19
-
20
- def self.push(method_object)
21
- execution_chain.push(method_object)
22
- end
23
-
24
- def self.pop
25
- execution_chain.pop
26
- end
27
-
28
- def push(method_object)
29
- call_sites.push(method_object)
30
- self.stack_depth += 1
31
-
32
- self.execution_count += self.stack_depth == 1 ? 1 : 0
33
- end
34
-
35
- def pop
36
- popping_empty_stack! if self.stack_depth.zero?
37
-
38
- self.stack_depth -= 1
39
-
40
- save_and_reset! if self.stack_depth.zero?
41
- end
42
-
43
- def stack_depth
44
- @stack_depth ||= 0
45
- end
46
-
47
- def execution_count
48
- @execution_count ||= 0
49
- end
50
-
51
- def call_sites
52
- @call_sites ||= []
53
- end
54
-
55
- def step_count
56
- call_sites.length
57
- end
58
-
59
- attr_writer :stack_depth, :step_count, :execution_count, :call_sites
60
-
61
- private
62
-
63
- class PoppingEmptyStackError < StandardError
64
- end
65
-
66
- def popping_empty_stack!
67
- raise PoppingEmptyStackError
68
- end
69
-
70
- def save_and_reset!
71
- Neo4j::ExecutionPersistence.save!(self) if call_sites.length.positive?
72
- self.call_sites = []
73
- end
74
- end
75
- end