nocode 0.0.5 → 0.0.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: 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