grumlin 0.23.0 → 1.0.0.rc2
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 +4 -4
- data/.rubocop.yml +9 -9
- data/Gemfile.lock +1 -1
- data/README.md +100 -142
- data/Rakefile +1 -1
- data/bin/console +18 -3
- data/doc/middlewares.md +49 -10
- data/lib/async/channel.rb +54 -56
- data/lib/grumlin/benchmark/repository.rb +10 -14
- data/lib/grumlin/client.rb +93 -95
- data/lib/grumlin/config.rb +33 -33
- data/lib/grumlin/dummy_transaction.rb +13 -15
- data/lib/grumlin/edge.rb +18 -20
- data/lib/grumlin/expressions/cardinality.rb +5 -9
- data/lib/grumlin/expressions/column.rb +5 -9
- data/lib/grumlin/expressions/expression.rb +7 -11
- data/lib/grumlin/expressions/operator.rb +5 -9
- data/lib/grumlin/expressions/order.rb +5 -9
- data/lib/grumlin/expressions/p.rb +27 -31
- data/lib/grumlin/expressions/pop.rb +5 -9
- data/lib/grumlin/expressions/scope.rb +5 -9
- data/lib/grumlin/expressions/t.rb +5 -9
- data/lib/grumlin/expressions/text_p.rb +5 -9
- data/lib/grumlin/expressions/with_options.rb +17 -21
- data/lib/grumlin/features/feature_list.rb +8 -12
- data/lib/grumlin/features/neptune_features.rb +5 -9
- data/lib/grumlin/features/tinkergraph_features.rb +5 -9
- data/lib/grumlin/features.rb +8 -10
- data/lib/grumlin/middlewares/apply_shortcuts.rb +4 -8
- data/lib/grumlin/middlewares/build_query.rb +16 -20
- data/lib/grumlin/middlewares/builder.rb +15 -0
- data/lib/grumlin/middlewares/cast_results.rb +3 -7
- data/lib/grumlin/middlewares/find_blocklisted_steps.rb +14 -0
- data/lib/grumlin/middlewares/find_mutating_steps.rb +9 -0
- data/lib/grumlin/middlewares/middleware.rb +6 -10
- data/lib/grumlin/middlewares/run_query.rb +3 -7
- data/lib/grumlin/middlewares/serialize_to_bytecode.rb +5 -9
- data/lib/grumlin/middlewares/serialize_to_steps.rb +4 -8
- data/lib/grumlin/path.rb +11 -13
- data/lib/grumlin/property.rb +14 -16
- data/lib/grumlin/query_validators/blocklisted_steps_validator.rb +22 -0
- data/lib/grumlin/query_validators/validator.rb +36 -0
- data/lib/grumlin/repository/error_handling_strategy.rb +36 -40
- data/lib/grumlin/repository/instance_methods.rb +115 -118
- data/lib/grumlin/repository.rb +82 -58
- data/lib/grumlin/request_dispatcher.rb +55 -57
- data/lib/grumlin/request_error_factory.rb +53 -55
- data/lib/grumlin/shortcut.rb +19 -21
- data/lib/grumlin/shortcuts/properties.rb +12 -16
- data/lib/grumlin/shortcuts/storage.rb +67 -74
- data/lib/grumlin/shortcuts/upserts.rb +19 -22
- data/lib/grumlin/shortcuts.rb +23 -25
- data/lib/grumlin/shortcuts_applyer.rb +27 -29
- data/lib/grumlin/step.rb +88 -90
- data/lib/grumlin/step_data.rb +12 -14
- data/lib/grumlin/steppable.rb +23 -25
- data/lib/grumlin/steps.rb +52 -54
- data/lib/grumlin/steps_serializers/bytecode.rb +53 -56
- data/lib/grumlin/steps_serializers/human_readable_bytecode.rb +17 -21
- data/lib/grumlin/steps_serializers/serializer.rb +7 -11
- data/lib/grumlin/steps_serializers/string.rb +26 -30
- data/lib/grumlin/test/rspec/db_cleaner_context.rb +8 -12
- data/lib/grumlin/test/rspec/gremlin_context.rb +18 -16
- data/lib/grumlin/test/rspec.rb +1 -5
- data/lib/grumlin/transaction.rb +34 -36
- data/lib/grumlin/transport.rb +71 -73
- data/lib/grumlin/traversal_start.rb +31 -33
- data/lib/grumlin/traversal_strategies/options_strategy.rb +3 -7
- data/lib/grumlin/traverser.rb +5 -7
- data/lib/grumlin/typed_value.rb +11 -13
- data/lib/grumlin/typing.rb +70 -72
- data/lib/grumlin/version.rb +1 -1
- data/lib/grumlin/vertex.rb +14 -16
- data/lib/grumlin/vertex_property.rb +14 -16
- data/lib/grumlin/with_extension.rb +17 -19
- data/lib/grumlin.rb +13 -0
- metadata +9 -6
- data/lib/grumlin/middlewares/frozen_builder.rb +0 -18
- data/lib/grumlin/sugar.rb +0 -15
data/lib/grumlin/typing.rb
CHANGED
@@ -1,89 +1,87 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Grumlin
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
3
|
+
module Grumlin::Typing
|
4
|
+
TYPES = {
|
5
|
+
"g:List" => ->(value) { cast_list(value) },
|
6
|
+
"g:Set" => ->(value) { cast_list(value).to_set },
|
7
|
+
"g:Map" => ->(value) { cast_map(value) },
|
8
|
+
"g:Vertex" => ->(value) { cast_entity(Grumlin::Vertex, value) },
|
9
|
+
"g:Edge" => ->(value) { cast_entity(Grumlin::Edge, value) },
|
10
|
+
"g:Path" => ->(value) { cast_entity(Grumlin::Path, value) },
|
11
|
+
"g:Traverser" => ->(value) { cast_entity(Grumlin::Traverser, value) },
|
12
|
+
"g:Property" => ->(value) { cast_entity(Grumlin::Property, value) },
|
13
|
+
"g:Int64" => ->(value) { cast_int(value) },
|
14
|
+
"g:Int32" => ->(value) { cast_int(value) },
|
15
|
+
"g:Double" => ->(value) { cast_double(value) },
|
16
|
+
"g:Direction" => ->(value) { value },
|
17
|
+
"g:VertexProperty" => ->(value) { cast_entity(Grumlin::VertexProperty, value) },
|
18
|
+
"g:TraversalMetrics" => ->(value) { cast_map(value[:@value]) },
|
19
|
+
"g:Metrics" => ->(value) { cast_map(value[:@value]) },
|
20
|
+
"g:T" => ->(value) { Grumlin::Expressions::T.public_send(value) }
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
CASTABLE_TYPES = [Hash, String, Integer, TrueClass, FalseClass, NilClass].freeze
|
24
|
+
|
25
|
+
class << self
|
26
|
+
def cast(value)
|
27
|
+
verify_type!(value)
|
28
|
+
|
29
|
+
return value unless value.is_a?(Hash)
|
30
|
+
|
31
|
+
type = TYPES[value[:@type]]
|
32
|
+
|
33
|
+
verify_castable_hash!(value, type)
|
34
|
+
|
35
|
+
type.call(value[:@value])
|
36
|
+
end
|
38
37
|
|
39
|
-
|
38
|
+
private
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
def verify_type!(value)
|
41
|
+
raise TypeError, "#{value.inspect} cannot be casted" unless CASTABLE_TYPES.include?(value.class)
|
42
|
+
end
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
def verify_castable_hash!(value, type)
|
45
|
+
raise TypeError, "#{value} cannot be casted, @type is missing" if value[:@type].nil?
|
46
|
+
raise(UnknownTypeError, value[:@type]) if type.nil?
|
47
|
+
raise TypeError, "#{value} cannot be casted, @value is missing" if value[:@value].nil?
|
48
|
+
end
|
50
49
|
|
51
|
-
|
52
|
-
|
50
|
+
def cast_int(value)
|
51
|
+
raise TypeError, "#{value} is not an Integer" unless value.is_a?(Integer)
|
53
52
|
|
54
|
-
|
55
|
-
|
53
|
+
value
|
54
|
+
end
|
56
55
|
|
57
|
-
|
58
|
-
|
56
|
+
def cast_double(value)
|
57
|
+
raise TypeError, "#{value} is not a Double" unless value.is_a?(Float)
|
59
58
|
|
60
|
-
|
61
|
-
|
59
|
+
value
|
60
|
+
end
|
62
61
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
def cast_entity(entity, value)
|
63
|
+
entity.new(**value)
|
64
|
+
rescue ArgumentError, TypeError
|
65
|
+
raise TypeError, "#{value} cannot be casted to #{entity.name}"
|
66
|
+
end
|
68
67
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
def cast_map(value)
|
69
|
+
Hash[*value].transform_keys do |key|
|
70
|
+
next key.to_sym if key.respond_to?(:to_sym)
|
71
|
+
next cast(key) if key[:@type] # TODO: g.V.group.by(:none_existing_property).next
|
73
72
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
73
|
+
raise UnknownMapKey, key, value
|
74
|
+
end.transform_values { |v| cast(v) }
|
75
|
+
rescue ArgumentError
|
76
|
+
raise TypeError, "#{value} cannot be casted to Hash"
|
77
|
+
end
|
79
78
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
def cast_list(value)
|
80
|
+
value.each_with_object([]) do |item, result|
|
81
|
+
casted_value = cast(item)
|
82
|
+
next (result << casted_value) unless casted_value.instance_of?(Grumlin::Traverser)
|
84
83
|
|
85
|
-
|
86
|
-
end
|
84
|
+
casted_value.bulk.times { result << casted_value.value }
|
87
85
|
end
|
88
86
|
end
|
89
87
|
end
|
data/lib/grumlin/version.rb
CHANGED
data/lib/grumlin/vertex.rb
CHANGED
@@ -1,24 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
attr_reader :label, :id
|
3
|
+
class Grumlin::Vertex
|
4
|
+
attr_reader :label, :id
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
def initialize(label:, id:)
|
7
|
+
@label = label
|
8
|
+
@id = Grumlin::Typing.cast(id)
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def ==(other)
|
12
|
+
self.class == other.class && @label == other.label && @id == other.id
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def inspect
|
16
|
+
"v[#{@id}]"
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
end
|
19
|
+
def to_s
|
20
|
+
inspect
|
23
21
|
end
|
24
22
|
end
|
@@ -1,24 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
attr_reader :label, :value
|
3
|
+
class Grumlin::VertexProperty
|
4
|
+
attr_reader :label, :value
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
def initialize(value)
|
7
|
+
@label = value[:label]
|
8
|
+
@value = Grumlin::Typing.cast(value[:value])
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def inspect
|
12
|
+
"vp[#{label}->#{value}]"
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def to_s
|
16
|
+
inspect
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
end
|
19
|
+
def ==(other)
|
20
|
+
self.class == other.class && @label == other.label && @value == other.value
|
23
21
|
end
|
24
22
|
end
|
@@ -1,27 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Grumlin
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
3
|
+
module Grumlin::WithExtension
|
4
|
+
def with(name, value)
|
5
|
+
prev = self
|
6
|
+
strategy = if is_a?(with_step_class)
|
7
|
+
prev = previous_step
|
8
|
+
Grumlin::TraversalStrategies::OptionsStrategy.new(args.first.value.merge(name => value))
|
9
|
+
else
|
10
|
+
Grumlin::TraversalStrategies::OptionsStrategy.new({ name => value })
|
11
|
+
end
|
12
|
+
with_step_class.new(:withStrategies, args: [strategy], previous_step: prev)
|
13
|
+
end
|
15
14
|
|
16
|
-
|
15
|
+
private
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def with_step_class
|
18
|
+
@with_step_class ||= Class.new(shortcuts.step_class) do
|
19
|
+
include Grumlin::WithExtension
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
end
|
21
|
+
def with_step_class
|
22
|
+
self.class
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
data/lib/grumlin.rb
CHANGED
@@ -184,6 +184,19 @@ module Grumlin
|
|
184
184
|
def definitions
|
185
185
|
@definitions ||= YAML.safe_load(File.read(File.join(__dir__, "definitions.yml")), symbolize_names: true)
|
186
186
|
end
|
187
|
+
|
188
|
+
def fake_uuid(*parts, separator: "->")
|
189
|
+
uuid = Digest::MD5.hexdigest(parts.join(separator))
|
190
|
+
|
191
|
+
segments = [8, 4, 4, 4, 12]
|
192
|
+
parts = segments.map do |n|
|
193
|
+
uuid[0...n].tap do
|
194
|
+
uuid = uuid[n..]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
parts.join("-")
|
199
|
+
end
|
187
200
|
end
|
188
201
|
end
|
189
202
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grumlin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gleb Sinyavskiy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-09-
|
11
|
+
date: 2022-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-pool
|
@@ -156,14 +156,18 @@ files:
|
|
156
156
|
- lib/grumlin/features/tinkergraph_features.rb
|
157
157
|
- lib/grumlin/middlewares/apply_shortcuts.rb
|
158
158
|
- lib/grumlin/middlewares/build_query.rb
|
159
|
+
- lib/grumlin/middlewares/builder.rb
|
159
160
|
- lib/grumlin/middlewares/cast_results.rb
|
160
|
-
- lib/grumlin/middlewares/
|
161
|
+
- lib/grumlin/middlewares/find_blocklisted_steps.rb
|
162
|
+
- lib/grumlin/middlewares/find_mutating_steps.rb
|
161
163
|
- lib/grumlin/middlewares/middleware.rb
|
162
164
|
- lib/grumlin/middlewares/run_query.rb
|
163
165
|
- lib/grumlin/middlewares/serialize_to_bytecode.rb
|
164
166
|
- lib/grumlin/middlewares/serialize_to_steps.rb
|
165
167
|
- lib/grumlin/path.rb
|
166
168
|
- lib/grumlin/property.rb
|
169
|
+
- lib/grumlin/query_validators/blocklisted_steps_validator.rb
|
170
|
+
- lib/grumlin/query_validators/validator.rb
|
167
171
|
- lib/grumlin/repository.rb
|
168
172
|
- lib/grumlin/repository/error_handling_strategy.rb
|
169
173
|
- lib/grumlin/repository/instance_methods.rb
|
@@ -183,7 +187,6 @@ files:
|
|
183
187
|
- lib/grumlin/steps_serializers/human_readable_bytecode.rb
|
184
188
|
- lib/grumlin/steps_serializers/serializer.rb
|
185
189
|
- lib/grumlin/steps_serializers/string.rb
|
186
|
-
- lib/grumlin/sugar.rb
|
187
190
|
- lib/grumlin/test/rspec.rb
|
188
191
|
- lib/grumlin/test/rspec/db_cleaner_context.rb
|
189
192
|
- lib/grumlin/test/rspec/gremlin_context.rb
|
@@ -218,9 +221,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
218
221
|
version: 2.7.0
|
219
222
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
220
223
|
requirements:
|
221
|
-
- - "
|
224
|
+
- - ">"
|
222
225
|
- !ruby/object:Gem::Version
|
223
|
-
version:
|
226
|
+
version: 1.3.1
|
224
227
|
requirements: []
|
225
228
|
rubygems_version: 3.2.33
|
226
229
|
signing_key:
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
module Middlewares
|
5
|
-
class FrozenBuilder < ::Middleware::Builder
|
6
|
-
def initialize(opts = nil, &block)
|
7
|
-
super(opts, &block)
|
8
|
-
freeze
|
9
|
-
end
|
10
|
-
|
11
|
-
def freeze
|
12
|
-
super
|
13
|
-
|
14
|
-
stack.freeze
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/grumlin/sugar.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
module Sugar
|
5
|
-
def self.included(base)
|
6
|
-
base.include(Grumlin::Expressions)
|
7
|
-
end
|
8
|
-
|
9
|
-
%i[__ g].each do |name|
|
10
|
-
define_method name do |cuts = Shortcuts::Storage.empty|
|
11
|
-
cuts.send(name)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|