grumlin 0.15.2 → 0.15.6
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 +3 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +2 -2
- data/README.md +4 -0
- data/Rakefile +21 -3
- data/lib/definitions.yml +114 -0
- data/lib/grumlin/anonymous_step.rb +4 -6
- data/lib/grumlin/expressions/operator.rb +1 -1
- data/lib/grumlin/expressions/order.rb +1 -1
- data/lib/grumlin/expressions/pop.rb +1 -1
- data/lib/grumlin/expressions/scope.rb +1 -1
- data/lib/grumlin/expressions/t.rb +1 -1
- data/lib/grumlin/expressions/u.rb +2 -5
- data/lib/grumlin/expressions/with_options.rb +1 -12
- data/lib/grumlin/shortcut.rb +27 -0
- data/lib/grumlin/shortcut_proxy.rb +1 -1
- data/lib/grumlin/shortcuts.rb +15 -6
- data/lib/grumlin/traversal.rb +2 -3
- data/lib/grumlin/version.rb +1 -1
- data/lib/grumlin.rb +6 -4
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 195f614a2cbebbe43f6dd2aedb3aeb54891c4377f50f85f21f44ee3325c87f58
|
4
|
+
data.tar.gz: 0f0a3c0b5aa8f03fb4d613c406b08497685ee9fb4cbea2e8a0b99385f749ebf3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21a7d91e9ce0a9e143f4bba9bb15d4bd31f6337f72500038bf09cd471ab05535d9d3ade4cfba6d6b6d779e09600b6352ed83b3e4bd70aeadd1417e51ba663937
|
7
|
+
data.tar.gz: 9cd14a8f18b856eca87d3b51b48c3f3c0d8d454b76fae92466bd7aee370019bbbb0b398236187acfcfed2322520aa4a3aa68a0e6bfb8b02a073e27f0db3cf525
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## [0.15.4] - 2022-01-20
|
2
|
+
|
3
|
+
- Move step and expression definitions to a yaml file for better diffs
|
4
|
+
- Add `definitions:format` rake task
|
5
|
+
|
6
|
+
## [0.15.3] - 2022-01-18
|
7
|
+
|
8
|
+
- Fix passing nils as step arguments. Even if they are not supported by the server, they should not be omitted.
|
9
|
+
|
1
10
|
## [0.15.2] - 2022-01-17
|
2
11
|
|
3
12
|
- New steps: `map` and `identity`
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
grumlin (0.15.
|
4
|
+
grumlin (0.15.6)
|
5
5
|
async-pool (~> 0.3)
|
6
6
|
async-websocket (~> 0.19)
|
7
7
|
oj (~> 3.12)
|
@@ -28,7 +28,7 @@ GEM
|
|
28
28
|
protocol-http (~> 0.22.0)
|
29
29
|
protocol-http1 (~> 0.14.0)
|
30
30
|
protocol-http2 (~> 0.14.0)
|
31
|
-
async-io (1.
|
31
|
+
async-io (1.33.0)
|
32
32
|
async
|
33
33
|
async-pool (0.3.9)
|
34
34
|
async (>= 1.25)
|
data/README.md
CHANGED
@@ -258,6 +258,10 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
258
258
|
the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version,
|
259
259
|
push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
260
260
|
|
261
|
+
### Adding new steps and expressions
|
262
|
+
To add a new step or an expression simple put it to the corresponding list in [definitions.yml](lib/definitions.yml)
|
263
|
+
and run `rake definitions:format`. You don't need to properly sort the lists manually, the rake task will do it for you.
|
264
|
+
|
261
265
|
## Contributing
|
262
266
|
|
263
267
|
Bug reports and pull requests are welcome on GitHub at https://github.com/zhulik/grumlin. This project is intended to
|
data/Rakefile
CHANGED
@@ -1,12 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "yaml"
|
4
|
+
|
3
5
|
require "bundler/gem_tasks"
|
4
6
|
require "rspec/core/rake_task"
|
7
|
+
require "rubocop/rake_task"
|
5
8
|
|
6
9
|
RSpec::Core::RakeTask.new(:spec)
|
10
|
+
RuboCop::RakeTask.new
|
7
11
|
|
8
|
-
|
12
|
+
task default: %i[rubocop spec]
|
9
13
|
|
10
|
-
|
14
|
+
namespace :definitions do
|
15
|
+
desc "Format definitions.yml"
|
16
|
+
task :format do
|
17
|
+
path = File.join(__dir__, "lib", "definitions.yml")
|
18
|
+
definitions = YAML.safe_load(File.read(path))
|
19
|
+
|
20
|
+
definitions.each_value do |kind|
|
21
|
+
kind.each do |name, list|
|
22
|
+
next if name == "with_options"
|
23
|
+
|
24
|
+
list.sort!
|
25
|
+
end
|
26
|
+
end
|
11
27
|
|
12
|
-
|
28
|
+
File.write(path, YAML.dump(definitions))
|
29
|
+
end
|
30
|
+
end
|
data/lib/definitions.yml
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
---
|
2
|
+
steps:
|
3
|
+
regular:
|
4
|
+
- E
|
5
|
+
- V
|
6
|
+
- addE
|
7
|
+
- addV
|
8
|
+
- aggregate
|
9
|
+
- and
|
10
|
+
- as
|
11
|
+
- both
|
12
|
+
- bothE
|
13
|
+
- by
|
14
|
+
- choose
|
15
|
+
- coalesce
|
16
|
+
- constant
|
17
|
+
- count
|
18
|
+
- dedup
|
19
|
+
- drop
|
20
|
+
- elementMap
|
21
|
+
- emit
|
22
|
+
- fold
|
23
|
+
- from
|
24
|
+
- group
|
25
|
+
- groupCount
|
26
|
+
- has
|
27
|
+
- hasId
|
28
|
+
- hasLabel
|
29
|
+
- hasNot
|
30
|
+
- id
|
31
|
+
- identity
|
32
|
+
- in
|
33
|
+
- inE
|
34
|
+
- inV
|
35
|
+
- inject
|
36
|
+
- is
|
37
|
+
- label
|
38
|
+
- limit
|
39
|
+
- map
|
40
|
+
- none
|
41
|
+
- not
|
42
|
+
- option
|
43
|
+
- or
|
44
|
+
- order
|
45
|
+
- out
|
46
|
+
- outE
|
47
|
+
- outV
|
48
|
+
- path
|
49
|
+
- project
|
50
|
+
- properties
|
51
|
+
- property
|
52
|
+
- range
|
53
|
+
- repeat
|
54
|
+
- sack
|
55
|
+
- select
|
56
|
+
- sideEffect
|
57
|
+
- skip
|
58
|
+
- sum
|
59
|
+
- tail
|
60
|
+
- timeLimit
|
61
|
+
- to
|
62
|
+
- unfold
|
63
|
+
- union
|
64
|
+
- until
|
65
|
+
- valueMap
|
66
|
+
- values
|
67
|
+
- where
|
68
|
+
- with
|
69
|
+
start:
|
70
|
+
- E
|
71
|
+
- V
|
72
|
+
- addE
|
73
|
+
- addV
|
74
|
+
- inject
|
75
|
+
configuration:
|
76
|
+
- withSack
|
77
|
+
- withSideEffect
|
78
|
+
expressions:
|
79
|
+
operator:
|
80
|
+
- addAll
|
81
|
+
- and
|
82
|
+
- assign
|
83
|
+
- div
|
84
|
+
- max
|
85
|
+
- min
|
86
|
+
- minus
|
87
|
+
- mult
|
88
|
+
- or
|
89
|
+
- sum
|
90
|
+
order:
|
91
|
+
- asc
|
92
|
+
- desc
|
93
|
+
- shuffle
|
94
|
+
pop:
|
95
|
+
- all
|
96
|
+
- first
|
97
|
+
- last
|
98
|
+
- mixed
|
99
|
+
scope:
|
100
|
+
- local
|
101
|
+
t:
|
102
|
+
- id
|
103
|
+
- label
|
104
|
+
with_options:
|
105
|
+
tokens: "~tinkerpop.valueMap.tokens"
|
106
|
+
none: 0
|
107
|
+
ids: 1
|
108
|
+
labels: 2
|
109
|
+
keys: 4
|
110
|
+
values: 8
|
111
|
+
all: 15
|
112
|
+
indexer: "~tinkerpop.index.indexer"
|
113
|
+
list: 0
|
114
|
+
map: 1
|
@@ -4,11 +4,7 @@ module Grumlin
|
|
4
4
|
class AnonymousStep
|
5
5
|
attr_reader :name, :previous_step, :configuration_steps
|
6
6
|
|
7
|
-
|
8
|
-
SUPPORTED_STEPS = %i[E V addE addV aggregate and as both bothE by choose coalesce count dedup drop elementMap emit
|
9
|
-
fold from group groupCount has hasId hasLabel hasNot id identity in inE inV is label limit
|
10
|
-
map not or order out outE path project properties property range repeat sack select sideEffect
|
11
|
-
skip sum tail to unfold union until valueMap values where with].freeze
|
7
|
+
SUPPORTED_STEPS = Grumlin.definitions.dig(:steps, :regular).map(&:to_sym).freeze
|
12
8
|
|
13
9
|
def initialize(name, *args, configuration_steps: [], previous_step: nil, **params)
|
14
10
|
@name = name
|
@@ -41,7 +37,9 @@ module Grumlin
|
|
41
37
|
end
|
42
38
|
|
43
39
|
def args
|
44
|
-
[*@args
|
40
|
+
[*@args].tap do |args|
|
41
|
+
args << @params if @params.any?
|
42
|
+
end
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
@@ -2,13 +2,10 @@
|
|
2
2
|
|
3
3
|
module Grumlin
|
4
4
|
module Expressions
|
5
|
+
# The module is called U because Underscore and implements __
|
5
6
|
module U
|
6
|
-
# TODO: add other start steps
|
7
|
-
SUPPORTED_STEPS = %i[V addV coalesce constant count drop fold has hasLabel hasNot id identity in inE inV is label
|
8
|
-
out outE outV project repeat select timeLimit unfold valueMap values].freeze
|
9
|
-
|
10
7
|
class << self
|
11
|
-
SUPPORTED_STEPS.each do |step|
|
8
|
+
Grumlin::AnonymousStep::SUPPORTED_STEPS.each do |step|
|
12
9
|
define_method step do |*args, **params|
|
13
10
|
AnonymousStep.new(step, *args, **params)
|
14
11
|
end
|
@@ -3,18 +3,7 @@
|
|
3
3
|
module Grumlin
|
4
4
|
module Expressions
|
5
5
|
module WithOptions
|
6
|
-
WITH_OPTIONS =
|
7
|
-
tokens: "~tinkerpop.valueMap.tokens",
|
8
|
-
none: 0,
|
9
|
-
ids: 1,
|
10
|
-
labels: 2,
|
11
|
-
keys: 4,
|
12
|
-
values: 8,
|
13
|
-
all: 15,
|
14
|
-
indexer: "~tinkerpop.index.indexer",
|
15
|
-
list: 0,
|
16
|
-
map: 1
|
17
|
-
}.freeze
|
6
|
+
WITH_OPTIONS = Grumlin.definitions.dig(:expressions, :with_options).freeze
|
18
7
|
|
19
8
|
class << self
|
20
9
|
WITH_OPTIONS.each do |k, v|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
class Shortcut
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_reader :name, :block
|
8
|
+
|
9
|
+
def_delegator :@block, :arity
|
10
|
+
def_delegator :@block, :source_location
|
11
|
+
|
12
|
+
def initialize(name, &block)
|
13
|
+
@name = name
|
14
|
+
@block = block
|
15
|
+
end
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
@name == other.name && @block == other.block
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO: to_s, inspect, preview
|
22
|
+
|
23
|
+
def apply(object, *args, **params)
|
24
|
+
object.instance_exec(*args, **params, &@block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -18,7 +18,7 @@ module Grumlin
|
|
18
18
|
|
19
19
|
return wrap_result(@object.public_send(name, *args, **params)) if @object.respond_to?(name)
|
20
20
|
|
21
|
-
return wrap_result(
|
21
|
+
return wrap_result(@shortcuts[name].apply(self, *args, **params)) if @shortcuts.key?(name)
|
22
22
|
|
23
23
|
super
|
24
24
|
end
|
data/lib/grumlin/shortcuts.rb
CHANGED
@@ -18,19 +18,28 @@ module Grumlin
|
|
18
18
|
subclass.shortcuts_from(self)
|
19
19
|
end
|
20
20
|
|
21
|
-
def shortcut(name, &block)
|
21
|
+
def shortcut(name, shortcut = nil, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
22
22
|
name = name.to_sym
|
23
23
|
# TODO: blocklist of names to avoid conflicts with standard methods?
|
24
|
-
|
24
|
+
if Grumlin::AnonymousStep::SUPPORTED_STEPS.include?(name)
|
25
|
+
raise ArgumentError,
|
26
|
+
"cannot use names of standard gremlin steps"
|
27
|
+
end
|
28
|
+
|
29
|
+
if (shortcut.nil? && block.nil?) || (shortcut && block)
|
30
|
+
raise ArgumentError, "either shortcut or block must be passed"
|
31
|
+
end
|
32
|
+
|
33
|
+
shortcut ||= Shortcut.new(name, &block)
|
25
34
|
|
26
|
-
raise ArgumentError, "shortcut '#{name}' already exists" if shortcuts.key?(name) && shortcuts[name] !=
|
35
|
+
raise ArgumentError, "shortcut '#{name}' already exists" if shortcuts.key?(name) && shortcuts[name] != shortcut
|
27
36
|
|
28
|
-
shortcuts[name] =
|
37
|
+
shortcuts[name] = shortcut
|
29
38
|
end
|
30
39
|
|
31
40
|
def shortcuts_from(other_shortcuts)
|
32
|
-
other_shortcuts.shortcuts.each do |name,
|
33
|
-
shortcut(name,
|
41
|
+
other_shortcuts.shortcuts.each do |name, shortcut|
|
42
|
+
shortcut(name, shortcut)
|
34
43
|
end
|
35
44
|
end
|
36
45
|
|
data/lib/grumlin/traversal.rb
CHANGED
@@ -2,10 +2,9 @@
|
|
2
2
|
|
3
3
|
module Grumlin
|
4
4
|
class Traversal
|
5
|
-
|
6
|
-
SUPPORTED_STEPS = %i[E V addE addV].freeze
|
5
|
+
SUPPORTED_STEPS = Grumlin.definitions.dig(:steps, :start).map(&:to_sym).freeze
|
7
6
|
|
8
|
-
CONFIGURATION_STEPS =
|
7
|
+
CONFIGURATION_STEPS = Grumlin.definitions.dig(:steps, :configuration).map(&:to_sym).freeze
|
9
8
|
|
10
9
|
attr_reader :configuration_steps
|
11
10
|
|
data/lib/grumlin/version.rb
CHANGED
data/lib/grumlin.rb
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
require "securerandom"
|
4
4
|
require "oj"
|
5
|
+
require "yaml"
|
5
6
|
|
7
|
+
# TODO: use Oj directly
|
6
8
|
Oj.mimic_JSON
|
7
9
|
Oj.add_to_json
|
8
10
|
|
@@ -108,10 +110,6 @@ module Grumlin
|
|
108
110
|
end
|
109
111
|
end
|
110
112
|
|
111
|
-
def self.supported_steps
|
112
|
-
@supported_steps ||= (Grumlin::AnonymousStep::SUPPORTED_STEPS + Grumlin::Expressions::U::SUPPORTED_STEPS).sort.uniq
|
113
|
-
end
|
114
|
-
|
115
113
|
@pool_mutex = Mutex.new
|
116
114
|
|
117
115
|
class << self
|
@@ -145,6 +143,10 @@ module Grumlin
|
|
145
143
|
Thread.current.thread_variable_set(:grumlin_default_pool, nil)
|
146
144
|
end
|
147
145
|
end
|
146
|
+
|
147
|
+
def definitions
|
148
|
+
@definitions ||= YAML.safe_load(File.read(File.join(__dir__, "definitions.yml")), symbolize_names: true)
|
149
|
+
end
|
148
150
|
end
|
149
151
|
end
|
150
152
|
|
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.15.
|
4
|
+
version: 0.15.6
|
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-
|
11
|
+
date: 2022-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-pool
|
@@ -96,6 +96,7 @@ files:
|
|
96
96
|
- gremlin_server/tinkergraph-empty.properties
|
97
97
|
- grumlin.gemspec
|
98
98
|
- lib/async/channel.rb
|
99
|
+
- lib/definitions.yml
|
99
100
|
- lib/grumlin.rb
|
100
101
|
- lib/grumlin/anonymous_step.rb
|
101
102
|
- lib/grumlin/bytecode.rb
|
@@ -114,6 +115,7 @@ files:
|
|
114
115
|
- lib/grumlin/property.rb
|
115
116
|
- lib/grumlin/repository.rb
|
116
117
|
- lib/grumlin/request_dispatcher.rb
|
118
|
+
- lib/grumlin/shortcut.rb
|
117
119
|
- lib/grumlin/shortcut_proxy.rb
|
118
120
|
- lib/grumlin/shortcuts.rb
|
119
121
|
- lib/grumlin/shortcuts/properties.rb
|