nocode 0.0.5 → 0.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8726547b06744c6a7870a8634901b344e41a65bb1ede23c7e68e99d2218d482f
4
- data.tar.gz: 3462f703d7639662c0da4f96ec9913749698c7f7a08a58387671db909a88785f
3
+ metadata.gz: bb204abe5d0c62fce45c1c9afd052fe90e21c9f422020b7acb497dd3e226c22b
4
+ data.tar.gz: dedd69881e903e5a1778303ea5adcd114fdcba10fbadbe2605c7e72b867beb83
5
5
  SHA512:
6
- metadata.gz: f7bcfd37d152798a753801944a6a4787e3ad83a08fcfca0b40d9a0957cd7c5142a298adbb64215ed2e161c9e7f842b89ab460f6374fb8ec552a3482aa0b712eb
7
- data.tar.gz: 6e024f679e2973888d5bb67c20988c8e93b296a6b6c4dbc66f7cb1f55d8638db48842834fd00c2a6d24050d9aa61950666107ff285a469e3f63835f74e7a5e7d
6
+ metadata.gz: 1e36a07d157d207d70606a067561cbfd049fab0842c124ebb252ef7e15d2bf1e397f5e683b17cead76f92e75112596038d627189ad9e37372bf7236341d500ef
7
+ data.tar.gz: dfb6f8759f55c3234fc04bae3e1701679b59d6e2678ae12d81190d9775f22a1f87beb6de63e0e58da5e7454d47ba72e3ec3791df66ce43a4e015a6ab8892878a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ #### 0.0.6 - February 13th, 2022
2
+
3
+ * Expose registers to main YAML configuration.
4
+ * Add Each step to serve as an example of an iterator.
5
+
1
6
  #### 0.0.5 - February 13th, 2022
2
7
 
3
8
  * Added initial Dataset steps.
data/exe/nocode CHANGED
@@ -4,6 +4,8 @@
4
4
  require 'bundler/setup'
5
5
  require 'nocode'
6
6
 
7
+ require 'pry'
8
+
7
9
  path = ARGV[0]
8
10
 
9
11
  if path.to_s.empty?
@@ -4,7 +4,12 @@ module Nocode
4
4
  # Describes the environment for each running step. An instance is initialized when a job
5
5
  # kicks off and then is passed from step to step.
6
6
  class Context
7
- attr_reader :io, :parameters, :registers
7
+ PARAMETERS_KEY = 'parameters'
8
+ REGISTERS_KEY = 'registers'
9
+
10
+ attr_reader :io,
11
+ :parameters,
12
+ :registers
8
13
 
9
14
  def initialize(io: $stdout, parameters: {}, registers: {})
10
15
  @io = io || $stdout
@@ -24,8 +29,8 @@ module Nocode
24
29
 
25
30
  def to_h
26
31
  {
27
- 'registers' => registers,
28
- 'parameters' => parameters
32
+ REGISTERS_KEY => registers,
33
+ PARAMETERS_KEY => parameters
29
34
  }
30
35
  end
31
36
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'context'
4
+ require_relative 'steps_executor'
5
+
6
+ module Nocode
7
+ # Manages the lifecycle and executes a job.
8
+ class JobExecutor
9
+ PARAMETERS_KEY = 'parameters'
10
+ REGISTERS_KEY = 'registers'
11
+ STEPS_KEY = 'steps'
12
+
13
+ attr_reader :yaml, :io
14
+
15
+ def initialize(yaml, io: $stdout)
16
+ @yaml = yaml.respond_to?(:read) ? yaml.read : yaml
17
+ @yaml = YAML.safe_load(@yaml) || {}
18
+ @io = io
19
+
20
+ freeze
21
+ end
22
+
23
+ def execute
24
+ steps = yaml[STEPS_KEY] || []
25
+ parameters = yaml[PARAMETERS_KEY] || {}
26
+ registers = yaml[REGISTERS_KEY] || {}
27
+
28
+ context = Context.new(
29
+ io: io,
30
+ parameters: parameters,
31
+ registers: registers
32
+ )
33
+
34
+ log_title
35
+
36
+ StepsExecutor.new(context: context, steps: steps).execute
37
+
38
+ log("Ended: #{DateTime.now}")
39
+ log_line
40
+
41
+ context
42
+ end
43
+
44
+ private
45
+
46
+ def log_title
47
+ log_line
48
+
49
+ log('Nocode Execution')
50
+ log("Started: #{DateTime.now}")
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)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,31 @@
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
+ class Each < Step
9
+ option :element_register_prefix,
10
+ :register,
11
+ :steps
12
+
13
+ skip_options_evaluation!
14
+
15
+ # rubocop:disable Metrics/AbcSize
16
+ def perform
17
+ entries = array(registers[register_option])
18
+
19
+ 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
24
+
25
+ StepsExecutor.new(context: context, steps: steps).execute
26
+ end
27
+ end
28
+ # rubocop:enable Metrics/AbcSize
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'step_registry'
4
+
5
+ module Nocode
6
+ # Class that knows how to execute a series of steps given a context.
7
+ class StepsExecutor
8
+ extend Forwardable
9
+
10
+ NAME_KEY = 'name'
11
+ OPTIONS_KEY = 'options'
12
+ TYPE_KEY = 'type'
13
+
14
+ attr_reader :context, :steps
15
+
16
+ def_delegators :context, :io
17
+
18
+ def initialize(context:, steps:)
19
+ @context = context
20
+ @steps = steps
21
+
22
+ freeze
23
+ end
24
+
25
+ def execute
26
+ steps.each do |step|
27
+ step_instance = make_step(step)
28
+
29
+ execute_step(step_instance)
30
+ end
31
+ end
32
+
33
+ private
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
+ def make_step(step)
39
+ evaluated_step = Util::ObjectTemplate.new(step).evaluate(context.to_h)
40
+ type = evaluated_step[TYPE_KEY].to_s
41
+ name = evaluated_step[NAME_KEY].to_s
42
+ step_class = StepRegistry.constant!(type)
43
+
44
+ options =
45
+ if step_class.skip_options_evaluation?
46
+ step[OPTIONS_KEY]
47
+ else
48
+ evaluated_step[OPTIONS_KEY]
49
+ end
50
+
51
+ step_class.new(
52
+ options: Util::Dictionary.new(options),
53
+ context: context,
54
+ name: name,
55
+ type: type
56
+ )
57
+ end
58
+
59
+ def execute_step(step)
60
+ log(step.name) unless step.name.empty?
61
+ log("Step: #{step.type}")
62
+ log("Class: #{step.class}")
63
+
64
+ time_in_seconds = Benchmark.measure { step.perform }.real
65
+
66
+ log("Completed in #{time_in_seconds.round(3)} second(s)")
67
+
68
+ log_line
69
+ end
70
+
71
+ def log_line
72
+ log('-' * 50)
73
+ end
74
+
75
+ def log(msg)
76
+ io.puts(msg)
77
+ end
78
+ end
79
+ end
@@ -23,6 +23,14 @@ module Nocode
23
23
 
24
24
  # Class-level DSL Methods
25
25
  module ClassMethods
26
+ def skip_options_evaluation?
27
+ @skip_options_evaluation || false
28
+ end
29
+
30
+ def skip_options_evaluation!
31
+ @skip_options_evaluation = true
32
+ end
33
+
26
34
  def option(*values)
27
35
  values.each { |v| options << v.to_s }
28
36
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nocode
4
- VERSION = '0.0.5'
4
+ VERSION = '0.0.6'
5
5
  end
data/lib/nocode.rb CHANGED
@@ -12,14 +12,14 @@ require 'yaml'
12
12
  require 'nocode/util'
13
13
 
14
14
  # Core
15
- require 'nocode/executor'
15
+ require 'nocode/job_executor'
16
16
 
17
17
  # Establish main top-level namespace
18
18
  module Nocode
19
19
  # Default consumer entrypoint into the library.
20
20
  class << self
21
21
  def execute(yaml, io: $stdout)
22
- Executor.new(yaml, io: io).execute
22
+ JobExecutor.new(yaml, io: io).execute
23
23
  end
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nocode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
@@ -175,7 +175,7 @@ files:
175
175
  - exe/nocode
176
176
  - lib/nocode.rb
177
177
  - lib/nocode/context.rb
178
- - lib/nocode/executor.rb
178
+ - lib/nocode/job_executor.rb
179
179
  - lib/nocode/step.rb
180
180
  - lib/nocode/step_registry.rb
181
181
  - lib/nocode/steps/copy.rb
@@ -188,6 +188,7 @@ files:
188
188
  - lib/nocode/steps/deserialize/csv.rb
189
189
  - lib/nocode/steps/deserialize/json.rb
190
190
  - lib/nocode/steps/deserialize/yaml.rb
191
+ - lib/nocode/steps/each.rb
191
192
  - lib/nocode/steps/io/read.rb
192
193
  - lib/nocode/steps/io/write.rb
193
194
  - lib/nocode/steps/log.rb
@@ -196,6 +197,7 @@ files:
196
197
  - lib/nocode/steps/serialize/yaml.rb
197
198
  - lib/nocode/steps/set.rb
198
199
  - lib/nocode/steps/sleep.rb
200
+ - lib/nocode/steps_executor.rb
199
201
  - lib/nocode/util.rb
200
202
  - lib/nocode/util/arrayable.rb
201
203
  - lib/nocode/util/class_loader.rb
@@ -1,90 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'context'
4
- require_relative 'step_registry'
5
-
6
- module Nocode
7
- # Manages the lifecycle and executes a job.
8
- class Executor
9
- NAME_KEY = 'name'
10
- OPTIONS_KEY = 'options'
11
- PARAMETERS_KEY = 'parameters'
12
- STEPS_KEY = 'steps'
13
- TYPE_KEY = 'type'
14
-
15
- attr_reader :yaml, :io
16
-
17
- def initialize(yaml, io: $stdout)
18
- @yaml = yaml.respond_to?(:read) ? yaml.read : yaml
19
- @yaml = YAML.safe_load(@yaml) || {}
20
- @io = io
21
-
22
- freeze
23
- end
24
-
25
- def execute
26
- steps = yaml[STEPS_KEY] || []
27
- parameters = yaml[PARAMETERS_KEY] || {}
28
- context = Context.new(io: io, parameters: parameters)
29
-
30
- log_title
31
-
32
- steps.each do |step|
33
- step_instance = make_step(step, context)
34
-
35
- execute_step(step_instance)
36
- end
37
-
38
- log("Ended: #{DateTime.now}")
39
- log_line
40
-
41
- context
42
- end
43
-
44
- private
45
-
46
- def make_step(step, context)
47
- step = Util::ObjectTemplate.new(step).evaluate(context.to_h)
48
- type = step[TYPE_KEY].to_s
49
- name = step[NAME_KEY].to_s
50
- options = step[OPTIONS_KEY] || {}
51
- step_class = StepRegistry.constant!(type)
52
-
53
- step_class.new(
54
- options: Util::Dictionary.new(options),
55
- context: context,
56
- name: name,
57
- type: type
58
- )
59
- end
60
-
61
- def execute_step(step)
62
- log(step.name) unless step.name.empty?
63
- log("Step: #{step.type}")
64
- log("Class: #{step.class}")
65
-
66
- time_in_seconds = Benchmark.measure { step.perform }.real
67
-
68
- log("Completed in #{time_in_seconds.round(3)} second(s)")
69
-
70
- log_line
71
- end
72
-
73
- def log_title
74
- log_line
75
-
76
- log('Nocode Execution')
77
- log("Started: #{DateTime.now}")
78
-
79
- log_line
80
- end
81
-
82
- def log_line
83
- log('-' * 50)
84
- end
85
-
86
- def log(msg)
87
- io.puts(msg)
88
- end
89
- end
90
- end