delfos 0.0.1.pre.beta
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.
- checksums.yaml +7 -0
- data/lib/delfos.rb +58 -0
- data/lib/delfos/common_path.rb +60 -0
- data/lib/delfos/distance/calculation.rb +133 -0
- data/lib/delfos/distance/relation.rb +119 -0
- data/lib/delfos/execution_chain.rb +74 -0
- data/lib/delfos/method_logging.rb +71 -0
- data/lib/delfos/method_logging/args.rb +53 -0
- data/lib/delfos/method_logging/code_location.rb +156 -0
- data/lib/delfos/method_logging/klass_determination.rb +16 -0
- data/lib/delfos/neo4j/distance_update.rb +73 -0
- data/lib/delfos/neo4j/execution_persistence.rb +63 -0
- data/lib/delfos/neo4j/informer.rb +110 -0
- data/lib/delfos/neo4j/query_execution.rb +38 -0
- data/lib/delfos/patching.rb +105 -0
- data/lib/delfos/patching_unstubbing_spec_helper.rb +44 -0
- data/lib/delfos/perform_patching.rb +16 -0
- data/lib/delfos/remove_patching.rb +10 -0
- data/lib/delfos/version.rb +4 -0
- metadata +161 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "delfos"
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module Delfos
|
6
|
+
module Neo4j
|
7
|
+
module QueryExecution
|
8
|
+
class << self
|
9
|
+
def execute(query, url=nil)
|
10
|
+
result = JSON.parse response_for(query)
|
11
|
+
result["results"].first["data"].map{|r| r["row"]}
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def response_for(query)
|
17
|
+
body = <<-BODY.gsub(/^\s+/, "").chomp
|
18
|
+
{"statements": [ { "statement": #{query.inspect} }]}
|
19
|
+
BODY
|
20
|
+
url = "http://neo4j:password@localhost:7474/db/data/transaction/commit"
|
21
|
+
|
22
|
+
command = "curl #{headers} --data-ascii '#{body}' #{url} 2> /dev/null"
|
23
|
+
|
24
|
+
`#{command}`
|
25
|
+
end
|
26
|
+
|
27
|
+
def headers
|
28
|
+
<<-HEADERS.chomp
|
29
|
+
-H "User-Agent: delfos" -H "Accept: application/json; charset=UTF-8" -H "Content-Type: application/json"
|
30
|
+
HEADERS
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Delfos
|
3
|
+
class Patching
|
4
|
+
class << self
|
5
|
+
def perform(klass, name, private_methods, class_method:)
|
6
|
+
new(klass, name, private_methods, class_method).setup
|
7
|
+
end
|
8
|
+
|
9
|
+
def added_methods
|
10
|
+
@added_methods ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_definition_for(klass, key)
|
14
|
+
# Find method definitions defined in klass or its ancestors
|
15
|
+
super_klass = klass.ancestors.detect do |k|
|
16
|
+
added_methods[k.to_s]
|
17
|
+
end
|
18
|
+
|
19
|
+
klass_hash = added_methods[super_klass.to_s] || {}
|
20
|
+
klass_hash[key]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :klass, :name, :private_methods, :class_method
|
25
|
+
|
26
|
+
def initialize(klass, name, private_methods, class_method)
|
27
|
+
@klass = klass
|
28
|
+
@name = name
|
29
|
+
@private_methods = private_methods
|
30
|
+
@class_method = class_method
|
31
|
+
end
|
32
|
+
|
33
|
+
# Redefine the method (only once) at runtime to enabling logging to Neo4j
|
34
|
+
def setup
|
35
|
+
return if ensure_method_recorded!
|
36
|
+
original = original_method
|
37
|
+
class_method = class_method()
|
38
|
+
performer = method(:perform_call)
|
39
|
+
|
40
|
+
method_defining_method.call(name) do |*args, **keyword_args, &block|
|
41
|
+
MethodLogging.log(self, args, keyword_args, block, class_method, caller.dup, binding.dup, original)
|
42
|
+
|
43
|
+
method_to_call = class_method ? original : original.bind(self)
|
44
|
+
result = performer.call(method_to_call, args, keyword_args, block)
|
45
|
+
Delfos::ExecutionChain.pop
|
46
|
+
result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def perform_call(method_to_call, args, keyword_args, block)
|
54
|
+
if keyword_args.empty?
|
55
|
+
method_to_call.call(*args, &block)
|
56
|
+
else
|
57
|
+
method_to_call.call(*args, **keyword_args, &block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def original_method
|
62
|
+
@original_method ||= class_method ? klass.singleton_method(name) : klass.instance_method(name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def method_defining_method
|
66
|
+
class_method ? klass.method(:define_singleton_method) : klass.method(:define_method)
|
67
|
+
end
|
68
|
+
|
69
|
+
def ensure_method_recorded!
|
70
|
+
return true if bail?
|
71
|
+
|
72
|
+
self.class.added_methods[klass.to_s] ||= {}
|
73
|
+
self.class.added_methods[klass.to_s][key] = original_method.source_location
|
74
|
+
|
75
|
+
false
|
76
|
+
end
|
77
|
+
|
78
|
+
def bail?
|
79
|
+
method_has_been_added? || private_method? || exclude?
|
80
|
+
end
|
81
|
+
|
82
|
+
def method_has_been_added?
|
83
|
+
return false unless self.class.added_methods[self]
|
84
|
+
return false unless self.class.added_methods[self][klass]
|
85
|
+
|
86
|
+
self.class.added_methods[klass][key]
|
87
|
+
end
|
88
|
+
|
89
|
+
def private_method?
|
90
|
+
private_methods.include?(name.to_sym)
|
91
|
+
end
|
92
|
+
|
93
|
+
def exclude?
|
94
|
+
::Delfos::MethodLogging.exclude_from_logging?(original_method)
|
95
|
+
end
|
96
|
+
|
97
|
+
def key
|
98
|
+
"#{type}_#{name}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def type
|
102
|
+
class_method ? "ClassMethod" : "InstanceMethod"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# This existence of these `Unstubbing` modules are an unfortunate side effect of trying to
|
2
|
+
# test something that redefines methods. In order to not call the logging
|
3
|
+
# defined in `Delfos::Patching#setup` multiple times we have to keep track of
|
4
|
+
# and remove the method definitions and replace with the original definition
|
5
|
+
# (or as close to the original as possible).
|
6
|
+
#
|
7
|
+
# If there is a better way to test Delfos::Patching without doing this then
|
8
|
+
# please suggest or replace with a cleaner alternative
|
9
|
+
module Unstubbing
|
10
|
+
module ClassMethods
|
11
|
+
def add_instance_to_unstub!(object)
|
12
|
+
instances_to_unstub.push(object)
|
13
|
+
end
|
14
|
+
|
15
|
+
def unstub_all!
|
16
|
+
instances_to_unstub.each(&:unstub!)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def instances_to_unstub
|
22
|
+
@instances_to_unstub ||= []
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module InstanceMethods
|
27
|
+
def initialize(*args)
|
28
|
+
super(*args)
|
29
|
+
self.class.add_instance_to_unstub!(self) unless bail?
|
30
|
+
end
|
31
|
+
|
32
|
+
# This method is the inverse of `Delfos::Patching#setup`
|
33
|
+
def unstub!
|
34
|
+
original = original_method
|
35
|
+
class_method = class_method()
|
36
|
+
performer = method(:perform_call)
|
37
|
+
|
38
|
+
method_defining_method.call(name) do |*args, **keyword_args, &block|
|
39
|
+
method_to_call = class_method ? original : original.bind(self)
|
40
|
+
performer.call(method_to_call, args, keyword_args, block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "patching"
|
3
|
+
|
4
|
+
class BasicObject
|
5
|
+
def self.method_added(name)
|
6
|
+
return if name == __method__
|
7
|
+
|
8
|
+
::Delfos::Patching.perform(self, name, private_instance_methods, class_method: false)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.singleton_method_added(name)
|
12
|
+
return if name == __method__
|
13
|
+
|
14
|
+
::Delfos::Patching.perform(self, name, private_methods, class_method: true)
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: delfos
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.pre.beta
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Burns
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: binding_of_caller
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: what_weve_got_here_is_an_error_to_communicate
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.11'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.11'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: awesome_print
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 11.1.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 11.1.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.4.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.4.0
|
111
|
+
description: Just because
|
112
|
+
email:
|
113
|
+
- markburns@notonthehighstreet.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- lib/delfos.rb
|
119
|
+
- lib/delfos/common_path.rb
|
120
|
+
- lib/delfos/distance/calculation.rb
|
121
|
+
- lib/delfos/distance/relation.rb
|
122
|
+
- lib/delfos/execution_chain.rb
|
123
|
+
- lib/delfos/method_logging.rb
|
124
|
+
- lib/delfos/method_logging/args.rb
|
125
|
+
- lib/delfos/method_logging/code_location.rb
|
126
|
+
- lib/delfos/method_logging/klass_determination.rb
|
127
|
+
- lib/delfos/neo4j/distance_update.rb
|
128
|
+
- lib/delfos/neo4j/execution_persistence.rb
|
129
|
+
- lib/delfos/neo4j/informer.rb
|
130
|
+
- lib/delfos/neo4j/query_execution.rb
|
131
|
+
- lib/delfos/patching.rb
|
132
|
+
- lib/delfos/patching_unstubbing_spec_helper.rb
|
133
|
+
- lib/delfos/perform_patching.rb
|
134
|
+
- lib/delfos/remove_patching.rb
|
135
|
+
- lib/delfos/version.rb
|
136
|
+
homepage: https://github.com/markburns/delfos
|
137
|
+
licenses:
|
138
|
+
- MIT
|
139
|
+
metadata:
|
140
|
+
allowed_push_host: https://rubygems.org
|
141
|
+
post_install_message:
|
142
|
+
rdoc_options: []
|
143
|
+
require_paths:
|
144
|
+
- lib
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">"
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: 1.3.1
|
155
|
+
requirements: []
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 2.5.1
|
158
|
+
signing_key:
|
159
|
+
specification_version: 4
|
160
|
+
summary: Record every method call in an application
|
161
|
+
test_files: []
|