nocode 0.0.6 → 0.0.10

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: bb204abe5d0c62fce45c1c9afd052fe90e21c9f422020b7acb497dd3e226c22b
4
- data.tar.gz: dedd69881e903e5a1778303ea5adcd114fdcba10fbadbe2605c7e72b867beb83
3
+ metadata.gz: e8132a6f8dd5bde1975030689aaed4f3858243075116febf95c34fa182df67f5
4
+ data.tar.gz: 950d30f0d5c5d9ff9c670119f3f03e90628a4ef54b578ca925be9c5f23a0995f
5
5
  SHA512:
6
- metadata.gz: 1e36a07d157d207d70606a067561cbfd049fab0842c124ebb252ef7e15d2bf1e397f5e683b17cead76f92e75112596038d627189ad9e37372bf7236341d500ef
7
- data.tar.gz: dfb6f8759f55c3234fc04bae3e1701679b59d6e2678ae12d81190d9775f22a1f87beb6de63e0e58da5e7454d47ba72e3ec3791df66ce43a4e015a6ab8892878a
6
+ metadata.gz: 72a179c3862851d65cf38679d2f147da64bb5f3bcceca8c2f7849c3687500f8637fb4c1f3ae78a90f670e356ef19d37ff2b3e35559d11e32467c4ac0b3c1e43b
7
+ data.tar.gz: 0dafc012dbcd75fe1ac4af1cda75e3084a8c9c85b9e21e51b69451b70b968aba7d03fdb5d485eb44b9f4ecca997a932c1dba750f5e7e8e8bbfcec074b777bde0
data/CHANGELOG.md CHANGED
@@ -1,11 +1,28 @@
1
+ #### 0.0.10 - February 18th, 2022
2
+
3
+ * Replace ObjectTemplate with Nay library.
4
+ #### 0.0.9 - February 18th, 2022
5
+
6
+ * Replace StringTemplate with Nay library.
7
+ #### 0.0.8 - February 14th, 2022
8
+
9
+ * Add `map` step to iterate and collect a dataset result.
10
+ * Add `record/map` step to iterate over a hash.
11
+ * Add `io/list` to populate a register with the contents of a directory.
12
+ * Add `io/delete` to delete a file specified in the path option.
13
+ #### 0.0.7 - February 13th, 2022
14
+
15
+ * Move shared logging logic to context (until a first class log writer emerges).
16
+ * Provide type_prefix option for class_registry
17
+
1
18
  #### 0.0.6 - February 13th, 2022
2
19
 
3
20
  * Expose registers to main YAML configuration.
4
- * Add Each step to serve as an example of an iterator.
21
+ * Add `each` step to serve as an example of an iterator.
5
22
 
6
23
  #### 0.0.5 - February 13th, 2022
7
24
 
8
- * Added initial Dataset steps.
25
+ * Added initial `dataset` steps.
9
26
 
10
27
  #### 0.0.4 - February 13th, 2022
11
28
 
@@ -33,5 +33,13 @@ module Nocode
33
33
  PARAMETERS_KEY => parameters
34
34
  }
35
35
  end
36
+
37
+ def log_line
38
+ log('-' * 50)
39
+ end
40
+
41
+ def log(msg)
42
+ io.puts(msg)
43
+ end
36
44
  end
37
45
  end
@@ -31,33 +31,25 @@ module Nocode
31
31
  registers: registers
32
32
  )
33
33
 
34
- log_title
34
+ log_title(context)
35
35
 
36
36
  StepsExecutor.new(context: context, steps: steps).execute
37
37
 
38
- log("Ended: #{DateTime.now}")
39
- log_line
38
+ context.log("Ended: #{DateTime.now}")
39
+ context.log_line
40
40
 
41
41
  context
42
42
  end
43
43
 
44
44
  private
45
45
 
46
- def log_title
47
- log_line
46
+ def log_title(context)
47
+ context.log_line
48
48
 
49
- log('Nocode Execution')
50
- log("Started: #{DateTime.now}")
49
+ context.log('Nocode Execution')
50
+ context.log("Started: #{DateTime.now}")
51
51
 
52
- log_line
53
- end
54
-
55
- def log_line
56
- log('-' * 50)
57
- end
58
-
59
- def log(msg)
60
- io.puts(msg)
52
+ context.log_line
61
53
  end
62
54
  end
63
55
  end
@@ -10,8 +10,8 @@ module Nocode
10
10
  class StepRegistry < Util::ClassRegistry
11
11
  include Singleton
12
12
 
13
- PREFIX = 'Nocode::Steps::'
14
- DIR = File.join(__dir__, 'steps')
13
+ CLASS_PREFIX = 'Nocode::Steps::'
14
+ DIR = File.join(__dir__, 'steps')
15
15
 
16
16
  class << self
17
17
  extend Forwardable
@@ -27,7 +27,7 @@ module Nocode
27
27
  files_loaded = Util::ClassLoader.new(DIR).load!
28
28
 
29
29
  # Class the parent to load up the registry with the files we found.
30
- load(files_loaded, PREFIX)
30
+ load(files_loaded, class_prefix: CLASS_PREFIX)
31
31
  end
32
32
  end
33
33
 
@@ -12,20 +12,36 @@ module Nocode
12
12
 
13
13
  skip_options_evaluation!
14
14
 
15
- # rubocop:disable Metrics/AbcSize
16
15
  def perform
17
- entries = array(registers[register_option])
18
-
19
16
  entries.each_with_index do |entry, index|
20
- steps = array(steps_option)
21
-
22
- registers["#{element_register_prefix_option}_element"] = entry
23
- registers["#{element_register_prefix_option}_index"] = index
17
+ registers[element_key] = entry
18
+ registers[index_key] = index
24
19
 
25
- StepsExecutor.new(context: context, steps: steps).execute
20
+ execute_steps
26
21
  end
27
22
  end
28
- # rubocop:enable Metrics/AbcSize
23
+
24
+ private
25
+
26
+ def execute_steps
27
+ StepsExecutor.new(context: context, steps: steps).execute
28
+ end
29
+
30
+ def entries
31
+ array(registers[register_option])
32
+ end
33
+
34
+ def steps
35
+ array(steps_option)
36
+ end
37
+
38
+ def element_key
39
+ "#{element_register_prefix_option}_element"
40
+ end
41
+
42
+ def index_key
43
+ "#{element_register_prefix_option}_index"
44
+ end
29
45
  end
30
46
  end
31
47
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nocode
4
+ module Steps
5
+ module Io
6
+ # Delete the specified path. Does nothing if the file does not exist.
7
+ class Delete < Step
8
+ option :path
9
+
10
+ def perform
11
+ return if path.to_s.empty?
12
+
13
+ FileUtils.rm_f(path) if File.exist?(path)
14
+ end
15
+
16
+ private
17
+
18
+ def path
19
+ File.join(*array(path_option))
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nocode
4
+ module Steps
5
+ module Io
6
+ # List all files in the path option. Wildcards can be used.
7
+ #
8
+ # Mechanic: https://ruby-doc.org/core-2.5.0/Dir.html#method-c-glob
9
+ class List < Step
10
+ option :path,
11
+ :register
12
+
13
+ def perform
14
+ registers[register_option] = Dir[path].reject { |p| File.directory?(p) }
15
+ end
16
+
17
+ private
18
+
19
+ def path
20
+ File.join(*array(path_option))
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nocode
4
+ module Steps
5
+ # Iterate over a register. Each iteration will store the current element and index in
6
+ # special registers called: _element and _index. You can prefix these registers by setting
7
+ # the element_register_prefix option.
8
+ #
9
+ # The main difference between this and 'each' is that this will collect the iterator
10
+ # element register and set the register to this new collection.
11
+ class Map < Step
12
+ option :element_register_prefix,
13
+ :register,
14
+ :steps
15
+
16
+ skip_options_evaluation!
17
+
18
+ def perform
19
+ registers[register_option] = entries.map.with_index do |entry, index|
20
+ registers[element_key] = entry
21
+ registers[index_key] = index
22
+
23
+ execute_steps
24
+
25
+ registers[element_key]
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def execute_steps
32
+ StepsExecutor.new(context: context, steps: steps).execute
33
+ end
34
+
35
+ def entries
36
+ array(registers[register_option])
37
+ end
38
+
39
+ def steps
40
+ array(steps_option)
41
+ end
42
+
43
+ def element_key
44
+ "#{element_register_prefix_option}_element"
45
+ end
46
+
47
+ def index_key
48
+ "#{element_register_prefix_option}_index"
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nocode
4
+ module Steps
5
+ module Record
6
+ # Create a new hash from an existing hash mapping each key as configured by the
7
+ # key_mappings option. The key_mappings option should be in the form of:
8
+ # new_key => old_key
9
+ class Map < Step
10
+ option :key_mappings, :register
11
+
12
+ def perform
13
+ input = registers[register_option] || {}
14
+ output = {}
15
+
16
+ (key_mappings_option || {}).each do |to, from|
17
+ output[to.to_s] = input[from.to_s]
18
+ end
19
+
20
+ registers[register_option] = output
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -13,7 +13,7 @@ module Nocode
13
13
 
14
14
  attr_reader :context, :steps
15
15
 
16
- def_delegators :context, :io
16
+ def_delegators :context, :log_line, :log
17
17
 
18
18
  def initialize(context:, steps:)
19
19
  @context = context
@@ -32,11 +32,8 @@ module Nocode
32
32
 
33
33
  private
34
34
 
35
- # TODO: It could be better encapsulated to move the evaluation logic into the step itself
36
- # and let it deal with compilation. This may call for re-working the lifecycle of the Step
37
- # class so I will temporarily defer this refactoring.
38
35
  def make_step(step)
39
- evaluated_step = Util::ObjectTemplate.new(step).evaluate(context.to_h)
36
+ evaluated_step = Nay.evaluate(step, context.to_h)
40
37
  type = evaluated_step[TYPE_KEY].to_s
41
38
  name = evaluated_step[NAME_KEY].to_s
42
39
  step_class = StepRegistry.constant!(type)
@@ -67,13 +64,5 @@ module Nocode
67
64
 
68
65
  log_line
69
66
  end
70
-
71
- def log_line
72
- log('-' * 50)
73
- end
74
-
75
- def log(msg)
76
- io.puts(msg)
77
- end
78
67
  end
79
68
  end
@@ -20,13 +20,13 @@ module Nocode
20
20
  freeze
21
21
  end
22
22
 
23
- def load(types, prefix = '')
23
+ def load(types, class_prefix: '', type_prefix: '')
24
24
  types.each do |type|
25
25
  pascal_cased = type.split(File::SEPARATOR).map do |part|
26
26
  part.split('_').collect(&:capitalize).join
27
27
  end.join('::')
28
28
 
29
- register(type, "#{prefix}#{pascal_cased}")
29
+ register("#{type_prefix}#{type}", "#{class_prefix}#{pascal_cased}")
30
30
  end
31
31
 
32
32
  self
data/lib/nocode/util.rb CHANGED
@@ -4,5 +4,4 @@ require_relative 'util/arrayable'
4
4
  require_relative 'util/class_loader'
5
5
  require_relative 'util/class_registry'
6
6
  require_relative 'util/dictionary'
7
- require_relative 'util/object_template'
8
7
  require_relative 'util/optionable'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nocode
4
- VERSION = '0.0.6'
4
+ VERSION = '0.0.10'
5
5
  end
data/lib/nocode.rb CHANGED
@@ -4,6 +4,7 @@ require 'benchmark'
4
4
  require 'csv'
5
5
  require 'fileutils'
6
6
  require 'json'
7
+ require 'nay'
7
8
  require 'singleton'
8
9
  require 'time'
9
10
  require 'yaml'
data/nocode.gemspec CHANGED
@@ -29,6 +29,8 @@ Gem::Specification.new do |s|
29
29
 
30
30
  s.required_ruby_version = '>= 2.6'
31
31
 
32
+ s.add_dependency('nay', '~>0.0', '>=0.0.3')
33
+
32
34
  s.add_development_dependency('bundler-audit')
33
35
  s.add_development_dependency('guard-rspec')
34
36
  s.add_development_dependency('pry')
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nocode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-14 00:00:00.000000000 Z
11
+ date: 2022-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nay
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.3
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.3
13
33
  - !ruby/object:Gem::Dependency
14
34
  name: bundler-audit
15
35
  requirement: !ruby/object:Gem::Requirement
@@ -189,9 +209,13 @@ files:
189
209
  - lib/nocode/steps/deserialize/json.rb
190
210
  - lib/nocode/steps/deserialize/yaml.rb
191
211
  - lib/nocode/steps/each.rb
212
+ - lib/nocode/steps/io/delete.rb
213
+ - lib/nocode/steps/io/list.rb
192
214
  - lib/nocode/steps/io/read.rb
193
215
  - lib/nocode/steps/io/write.rb
194
216
  - lib/nocode/steps/log.rb
217
+ - lib/nocode/steps/map.rb
218
+ - lib/nocode/steps/record/map.rb
195
219
  - lib/nocode/steps/serialize/csv.rb
196
220
  - lib/nocode/steps/serialize/json.rb
197
221
  - lib/nocode/steps/serialize/yaml.rb
@@ -203,9 +227,7 @@ files:
203
227
  - lib/nocode/util/class_loader.rb
204
228
  - lib/nocode/util/class_registry.rb
205
229
  - lib/nocode/util/dictionary.rb
206
- - lib/nocode/util/object_template.rb
207
230
  - lib/nocode/util/optionable.rb
208
- - lib/nocode/util/string_template.rb
209
231
  - lib/nocode/version.rb
210
232
  - nocode.gemspec
211
233
  homepage: https://github.com/mattruggio/nocode
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'string_template'
4
-
5
- module Nocode
6
- module Util
7
- # Built on top of StringTemplate but instead of only working for a string, this will
8
- # recursively evaluate all strings within an object. Heuristics:
9
- # - Strings evaluate using StringTemplate
10
- # - Hashes will have their keys and values traversed
11
- # - Arrays will have their entries traversed
12
- # - All other types will simply return themselves
13
- class ObjectTemplate
14
- attr_reader :object
15
-
16
- def initialize(object)
17
- @object = object
18
-
19
- freeze
20
- end
21
-
22
- def evaluate(values = {})
23
- recursive_evaluate(object, values)
24
- end
25
-
26
- private
27
-
28
- def recursive_evaluate(expression, values)
29
- case expression
30
- when Array
31
- expression.map { |o| recursive_evaluate(o, values) }
32
- when Hash
33
- expression.to_h do |k, v|
34
- [recursive_evaluate(k, values), recursive_evaluate(v, values)]
35
- end
36
- when String
37
- Util::StringTemplate.new(expression).evaluate(values)
38
- else
39
- expression
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nocode
4
- module Util
5
- # Takes in an expression and interpolates in any parameters using << >> notation.
6
- # For example:
7
- # input = { 'person' => 'hops' }
8
- # Nocode::Util::StringTemplate.new("Hello, << person.name >>!").evaluate(input)
9
- # Should produce: "Hello, hops!"
10
- class StringTemplate
11
- LEFT_TOKEN = '<<'
12
- RIGHT_TOKEN = '>>'
13
- SEPARATOR = '.'
14
- REG_EXPR = /#{Regexp.quote(LEFT_TOKEN)}(.*?)#{Regexp.quote(RIGHT_TOKEN)}/.freeze
15
-
16
- attr_reader :expression
17
-
18
- def initialize(expression)
19
- @expression = expression.to_s
20
-
21
- freeze
22
- end
23
-
24
- def evaluate(values = {})
25
- resolved = tokens_to_values(tokens, values)
26
-
27
- tokens.inject(expression) do |memo, token|
28
- memo.gsub("#{LEFT_TOKEN}#{token}#{RIGHT_TOKEN}", resolved[token].to_s)
29
- end
30
- end
31
-
32
- private
33
-
34
- def tokens
35
- expression.to_s.scan(REG_EXPR).flatten
36
- end
37
-
38
- def tokens_to_values(tokens, values)
39
- tokens.each_with_object({}) do |token, memo|
40
- cleansed = token.strip
41
- parts = cleansed.split(SEPARATOR)
42
- value = values.dig(*parts)
43
-
44
- memo[token] = value
45
- end
46
- end
47
- end
48
- end
49
- end