grumlin 0.15.2 → 0.15.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7027bddd19689f2886286b1bcd099c7c8dbf764502f77b5469434cd243387e5
4
- data.tar.gz: b5a3e1e1db75e2a7378f77246c9b3bbbc066d5b32c575d15c88d38917d4658be
3
+ metadata.gz: 195f614a2cbebbe43f6dd2aedb3aeb54891c4377f50f85f21f44ee3325c87f58
4
+ data.tar.gz: 0f0a3c0b5aa8f03fb4d613c406b08497685ee9fb4cbea2e8a0b99385f749ebf3
5
5
  SHA512:
6
- metadata.gz: b116b30db9eeaf3255793843caa191b6942de7c16a5765b00aa0b803c5e7ae7a1e35d4da4372fd9e2ebe485555f9b895b0fb527cbb37ff89636824197e3a9821
7
- data.tar.gz: 11647d93fe2b33814a5356607bca81f2d30edf3992cbae4c52a2191cc34db8632e65bd672ac61030ed27a3c7a7387316d0522188b53e83cef63af2171d5a8494
6
+ metadata.gz: 21a7d91e9ce0a9e143f4bba9bb15d4bd31f6337f72500038bf09cd471ab05535d9d3ade4cfba6d6b6d779e09600b6352ed83b3e4bd70aeadd1417e51ba663937
7
+ data.tar.gz: 9cd14a8f18b856eca87d3b51b48c3f3c0d8d454b76fae92466bd7aee370019bbbb0b398236187acfcfed2322520aa4a3aa68a0e6bfb8b02a073e27f0db3cf525
data/.rubocop.yml CHANGED
@@ -60,6 +60,9 @@ RSpec/MultipleExpectations:
60
60
  RSpec/DescribeClass:
61
61
  Enabled: false
62
62
 
63
+ RSpec/MultipleMemoizedHelpers:
64
+ Max: 7
65
+
63
66
  Style/WordArray:
64
67
  Exclude:
65
68
  - spec/**/*_spec.rb
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.2)
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.32.2)
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
- require "rubocop/rake_task"
12
+ task default: %i[rubocop spec]
9
13
 
10
- RuboCop::RakeTask.new
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
- task default: %i[spec rubocop]
28
+ File.write(path, YAML.dump(definitions))
29
+ end
30
+ end
@@ -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
- # TODO: add other steps
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, @params.any? ? @params : nil].compact
40
+ [*@args].tap do |args|
41
+ args << @params if @params.any?
42
+ end
45
43
  end
46
44
  end
47
45
  end
@@ -3,7 +3,7 @@
3
3
  module Grumlin
4
4
  module Expressions
5
5
  module Operator
6
- SUPPORTED_STEPS = %i[addAll and assign div max min minus mult or sum].freeze
6
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :operator).map(&:to_sym).freeze
7
7
 
8
8
  class << self
9
9
  extend Expression
@@ -3,7 +3,7 @@
3
3
  module Grumlin
4
4
  module Expressions
5
5
  module Order
6
- SUPPORTED_STEPS = %i[asc desc shuffle].freeze
6
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :order).map(&:to_sym).freeze
7
7
 
8
8
  class << self
9
9
  extend Expression
@@ -3,7 +3,7 @@
3
3
  module Grumlin
4
4
  module Expressions
5
5
  module Pop
6
- SUPPORTED_STEPS = %i[all first last mixed].freeze
6
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :pop).map(&:to_sym).freeze
7
7
 
8
8
  class << self
9
9
  extend Expression
@@ -3,7 +3,7 @@
3
3
  module Grumlin
4
4
  module Expressions
5
5
  module Scope
6
- SUPPORTED_STEPS = %i[local].freeze
6
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :scope).map(&:to_sym).freeze
7
7
 
8
8
  class << self
9
9
  extend Expression
@@ -3,7 +3,7 @@
3
3
  module Grumlin
4
4
  module Expressions
5
5
  module T
6
- SUPPORTED_STEPS = %i[id label].freeze
6
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :t).map(&:to_sym).freeze
7
7
 
8
8
  class << self
9
9
  extend Expression
@@ -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(instance_exec(*args, **params, &@shortcuts[name])) if @shortcuts.key?(name)
21
+ return wrap_result(@shortcuts[name].apply(self, *args, **params)) if @shortcuts.key?(name)
22
22
 
23
23
  super
24
24
  end
@@ -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
- raise ArgumentError, "cannot use names of standard gremlin steps" if Grumlin.supported_steps.include?(name)
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] != block
35
+ raise ArgumentError, "shortcut '#{name}' already exists" if shortcuts.key?(name) && shortcuts[name] != shortcut
27
36
 
28
- shortcuts[name] = block
37
+ shortcuts[name] = shortcut
29
38
  end
30
39
 
31
40
  def shortcuts_from(other_shortcuts)
32
- other_shortcuts.shortcuts.each do |name, block|
33
- shortcut(name, &block)
41
+ other_shortcuts.shortcuts.each do |name, shortcut|
42
+ shortcut(name, shortcut)
34
43
  end
35
44
  end
36
45
 
@@ -2,10 +2,9 @@
2
2
 
3
3
  module Grumlin
4
4
  class Traversal
5
- # TODO: add other start steps
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 = %i[withSack withSideEffect].freeze
7
+ CONFIGURATION_STEPS = Grumlin.definitions.dig(:steps, :configuration).map(&:to_sym).freeze
9
8
 
10
9
  attr_reader :configuration_steps
11
10
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Grumlin
4
- VERSION = "0.15.2"
4
+ VERSION = "0.15.6"
5
5
  end
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.2
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-01-17 00:00:00.000000000 Z
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