ruflow 0.0.1 → 0.1.0
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/.gitignore +2 -1
- data/lib/ruflow.rb +15 -1
- data/lib/ruflow/action.rb +92 -0
- data/lib/ruflow/error/bad_return.rb +9 -0
- data/lib/ruflow/error/mismatch_input_type.rb +9 -0
- data/lib/ruflow/error/mismatch_output_input_type.rb +19 -0
- data/lib/ruflow/error/mismatch_output_type.rb +9 -0
- data/lib/ruflow/error/output_port_not_defined.rb +9 -0
- data/lib/ruflow/flow.rb +75 -0
- data/lib/ruflow/tasks/base.rb +15 -2
- data/lib/ruflow/type_checker.rb +33 -0
- data/lib/ruflow/version.rb +1 -1
- data/ruflow.gemspec +3 -1
- data/setup_files/components/actions/printer.rb +21 -0
- data/setup_files/components/flows/hello_world.rb +12 -0
- metadata +40 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdeec6d4a796f5db914c0eee7f5665936416c281574b6a6f3a53dbe0ac15d8c3
|
4
|
+
data.tar.gz: c7598cdfb3279daa47abcc32b7f88e6e95f2295f506512727de8f3393eb4686b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 802e1ff8608bf668d8a8ee6a6d6ad7dd4a612c5a85a91dcbcea03f1ac2b7e773390d1b38799cd0b70f84dc754699969aac843f4730b54186159ffa5a3bff09e8
|
7
|
+
data.tar.gz: cc8ff7550c3f232cb1d33519f98fd4a673a5c97fb01aa6963be2caea6238c0d3cf43939cd1adc0d379ef580c2a77e36877627a6fdcf1f70fdeec211e3f14d8d2
|
data/.gitignore
CHANGED
data/lib/ruflow.rb
CHANGED
@@ -1,5 +1,16 @@
|
|
1
|
-
require "ruflow/version"
|
2
1
|
require "configurations"
|
2
|
+
require 'require_all'
|
3
|
+
|
4
|
+
require "ruflow/version"
|
5
|
+
require "ruflow/type_checker"
|
6
|
+
require "ruflow/action"
|
7
|
+
require "ruflow/flow"
|
8
|
+
|
9
|
+
require "ruflow/error/bad_return"
|
10
|
+
require "ruflow/error/mismatch_input_type"
|
11
|
+
require "ruflow/error/mismatch_output_type"
|
12
|
+
require "ruflow/error/mismatch_output_input_type"
|
13
|
+
require "ruflow/error/output_port_not_defined"
|
3
14
|
|
4
15
|
module Ruflow
|
5
16
|
include Configurations
|
@@ -13,6 +24,9 @@ module Ruflow
|
|
13
24
|
|
14
25
|
def setup(&block)
|
15
26
|
Ruflow.configure(&block)
|
27
|
+
|
28
|
+
autoload_all "#{Dir.pwd}/#{config.components_folder}/actions"
|
29
|
+
autoload_all "#{Dir.pwd}/#{config.components_folder}/flows"
|
16
30
|
end
|
17
31
|
end
|
18
32
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Ruflow
|
2
|
+
class Action
|
3
|
+
class << self
|
4
|
+
attr_accessor :options
|
5
|
+
|
6
|
+
alias_method :set_options, :options=
|
7
|
+
|
8
|
+
def change_options(_options = {})
|
9
|
+
self.options = options.merge(_options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_custom_options(_options = {})
|
13
|
+
klass = self.clone
|
14
|
+
klass.change_options(_options)
|
15
|
+
klass
|
16
|
+
end
|
17
|
+
|
18
|
+
def start(param = nil)
|
19
|
+
_param = param.nil? ? options[:default_input] : param
|
20
|
+
|
21
|
+
type_check_input!(_param, input_type)
|
22
|
+
output_port_and_value = self.new.start(_param)
|
23
|
+
|
24
|
+
check_return!(output_port_and_value)
|
25
|
+
|
26
|
+
output_port, value = output_port_and_value
|
27
|
+
|
28
|
+
check_output_port_is_defined!(output_port)
|
29
|
+
|
30
|
+
output_type = options[:output][output_port]
|
31
|
+
|
32
|
+
type_check_output!(value, output_type)
|
33
|
+
|
34
|
+
[output_port, value]
|
35
|
+
end
|
36
|
+
|
37
|
+
def input_type
|
38
|
+
options[:input]
|
39
|
+
end
|
40
|
+
|
41
|
+
def options
|
42
|
+
@options || ::Ruflow::Action.options
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def type_check_input!(value, input_type)
|
48
|
+
if TypeChecker.is_invalid?(value, type: input_type)
|
49
|
+
raise Error::MismatchInputType.new(value, input_type)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def check_return!(return_value)
|
54
|
+
if return_value.class != Array || return_value.first.class != Symbol
|
55
|
+
raise Error::BadReturn.new(return_value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def check_output_port_is_defined!(output_port)
|
60
|
+
_output_port = options[:output][output_port]
|
61
|
+
|
62
|
+
if _output_port.nil? || _output_port.empty?
|
63
|
+
raise Error::OutputPortNotDefined.new(_output_port)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def type_check_output!(value, output_type)
|
68
|
+
if TypeChecker.is_invalid?(value, type: output_type)
|
69
|
+
raise Error::MismatchOutputType.new(value, output_type)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
set_options(
|
75
|
+
default_input: nil,
|
76
|
+
input: '*',
|
77
|
+
output: {
|
78
|
+
ok: '*'
|
79
|
+
}
|
80
|
+
)
|
81
|
+
|
82
|
+
def start(value = nil)
|
83
|
+
raise NotImplementedError, 'Overwrite instance method start'
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def options
|
89
|
+
self.class.options
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Ruflow
|
2
|
+
module Error
|
3
|
+
class MismatchOutputInputType < StandardError
|
4
|
+
attr_reader :errors
|
5
|
+
|
6
|
+
def initialize(errors, msg="Mismatches found in: ")
|
7
|
+
@errors = Array(errors)
|
8
|
+
super(msg + format_errors)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def format_errors
|
14
|
+
@errors.map { |e| "ACTION_ID=#{e[:from_action_id]} to ACTION_ID=#{e[:to_action_id]} mismatch type on port #{e[:port]} (#{e[:from]} to #{e[:to]})" }
|
15
|
+
.join(', ')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/ruflow/flow.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
module Ruflow
|
2
|
+
class Flow < Action
|
3
|
+
|
4
|
+
def start(param)
|
5
|
+
action = self.class.start_action
|
6
|
+
value = param
|
7
|
+
|
8
|
+
while action[:output_to]
|
9
|
+
output_port, value = action[:klass].start(value)
|
10
|
+
|
11
|
+
action = self.class.actions[action[:output_to][output_port]]
|
12
|
+
end
|
13
|
+
|
14
|
+
action[:klass].start(value)
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
attr_accessor :actions, :start_action_id
|
19
|
+
|
20
|
+
alias_method :set_actions, :actions=
|
21
|
+
alias_method :set_start_action_id, :start_action_id=
|
22
|
+
|
23
|
+
def check_actions!
|
24
|
+
raise NotImplementedError, 'actions must be defined using set_actions({})' if actions.nil?
|
25
|
+
|
26
|
+
raise NotImplementedError, 'start_action_id must be defined using set_start_action_id(Integer)' if start_action_id.nil?
|
27
|
+
|
28
|
+
raise NotImplementedError, 'actions must be a Hash' if not(actions.is_a?(Hash))
|
29
|
+
|
30
|
+
raise NotImplementedError, 'start_action not found, change the start_action_id' if start_action.nil?
|
31
|
+
|
32
|
+
if (actions_with_error = actions_without_klass).any?
|
33
|
+
raise NotImplementedError, "actions id=#{actions_with_error.keys.join(', ')} must have value as a Hash and define a 'klass:' key"
|
34
|
+
end
|
35
|
+
|
36
|
+
if (actions_with_error = actions_mismatch_output_input_type).any?
|
37
|
+
raise Error::MismatchOutputInputType.new(actions_with_error)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def start
|
42
|
+
check_actions!
|
43
|
+
super(nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
def start_action
|
47
|
+
actions[start_action_id]
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def actions_without_klass
|
53
|
+
actions.select { |_, a| not(a.is_a?(Hash)) || a[:klass].nil? }
|
54
|
+
end
|
55
|
+
|
56
|
+
def actions_with_output_to
|
57
|
+
actions.select { |_, a| a[:output_to] }
|
58
|
+
end
|
59
|
+
|
60
|
+
def actions_mismatch_output_input_type
|
61
|
+
actions_with_output_to.map do |action_id, action|
|
62
|
+
|
63
|
+
action[:output_to].map do |port, next_action_id|
|
64
|
+
action_input_type = actions[next_action_id][:klass].options[:input]
|
65
|
+
action_output_type = action[:klass].options[:output][port]
|
66
|
+
|
67
|
+
if TypeChecker.incompatible_types?(action_input_type, action_output_type)
|
68
|
+
{from_action_id: action_id, to_action_id: next_action_id, from: action_output_type, to: action_input_type, port: port}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end.flatten.compact
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/ruflow/tasks/base.rb
CHANGED
@@ -1,14 +1,27 @@
|
|
1
1
|
require_relative 'setup'
|
2
|
+
require_relative '../../ruflow'
|
2
3
|
|
3
4
|
module Ruflow
|
4
5
|
module Tasks
|
5
6
|
class Base < Thor
|
6
|
-
desc "new [PROJECT_NAME]", "
|
7
|
+
desc "new [PROJECT_NAME]", "Generate a new project"
|
7
8
|
def new(project_name)
|
8
9
|
Ruflow::Tasks::Setup.start([project_name])
|
9
10
|
end
|
10
11
|
|
11
|
-
desc "
|
12
|
+
desc "start [FLOW_CLASS_NAME]", "Start a flow"
|
13
|
+
def start(flow_klass_name)
|
14
|
+
_file_path = "#{Dir.pwd}/ruflow_config"
|
15
|
+
|
16
|
+
if File.exist?("#{_file_path}.rb")
|
17
|
+
require _file_path
|
18
|
+
Kernel.const_get(flow_klass_name).start
|
19
|
+
else
|
20
|
+
puts "ruflow_config.rb not found on #{Dir.pwd}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "setup", "Generate all files and folder required"
|
12
25
|
def setup
|
13
26
|
Ruflow::Tasks::Setup.start(['.'])
|
14
27
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Ruflow
|
2
|
+
module TypeChecker
|
3
|
+
def self.incompatible_types?(type, compare_type)
|
4
|
+
!compatible_types?(type, compare_type)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.compatible_types?(type, compare_type)
|
8
|
+
return true if compare_type.include? '*'
|
9
|
+
|
10
|
+
compare_types = compare_type.split('|')
|
11
|
+
|
12
|
+
type.split('|').any? { |t| compare_types.include?(t) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.is_invalid?(value, type:)
|
16
|
+
!is_valid?(value, type: type)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.is_valid?(value, type:)
|
20
|
+
return true if type.include? '*'
|
21
|
+
|
22
|
+
types = type.split('|').map { |t| get_constant(t) }.flatten
|
23
|
+
|
24
|
+
types.any? { |t| value.is_a?(t) }
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def self.get_constant(type)
|
30
|
+
type == 'Boolean' ? [TrueClass, FalseClass] : [Kernel.const_get(type)]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/ruflow/version.rb
CHANGED
data/ruflow.gemspec
CHANGED
@@ -21,9 +21,11 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
23
|
spec.add_dependency "configurations", "~> 2.2.0"
|
24
|
-
spec.add_dependency "thor",
|
24
|
+
spec.add_dependency "thor", "~> 0.20.0"
|
25
|
+
spec.add_dependency "require_all", "~> 1.5.0"
|
25
26
|
|
26
27
|
spec.add_development_dependency "bundler", "~> 1.16"
|
27
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
28
29
|
spec.add_development_dependency "rspec", "~> 3.0"
|
30
|
+
spec.add_development_dependency "byebug"
|
29
31
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Actions
|
2
|
+
class Printer < ::Ruflow::Action
|
3
|
+
set_options(
|
4
|
+
default_input: '',
|
5
|
+
input: 'String',
|
6
|
+
output: {
|
7
|
+
ok: 'String'
|
8
|
+
}
|
9
|
+
)
|
10
|
+
|
11
|
+
def self.with_custom_options(can_print:, text:)
|
12
|
+
super(can_print: can_print, text: text)
|
13
|
+
end
|
14
|
+
|
15
|
+
def start(text)
|
16
|
+
puts text if options[:can_print]
|
17
|
+
|
18
|
+
[:ok, text + options[:text]]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Flows
|
2
|
+
class HelloWorld < ::Ruflow::Flow
|
3
|
+
set_actions({
|
4
|
+
1 => { klass: ::Actions::Printer.with_custom_options(can_print: false, text: 'Hello'), output_to: { ok: 2 } },
|
5
|
+
2 => { klass: ::Actions::Printer.with_custom_options(can_print: false, text: 'Hello'), output_to: { ok: 3 } },
|
6
|
+
3 => { klass: ::Actions::Printer.with_custom_options(can_print: false, text: 'Again'), output_to: { ok: 4 } },
|
7
|
+
4 => { klass: ::Actions::Printer.with_custom_options(can_print: true, text: 'World') }
|
8
|
+
})
|
9
|
+
|
10
|
+
set_start_action_id(1)
|
11
|
+
end
|
12
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- victor95pc
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: configurations
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.20.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: require_all
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.5.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.5.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,20 @@ dependencies:
|
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: byebug
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
83
111
|
description: Framework to create flow-based programs using Ruby.
|
84
112
|
email:
|
85
113
|
- victorpalomocastro@gmail.com
|
@@ -108,12 +136,22 @@ files:
|
|
108
136
|
- bin/thor
|
109
137
|
- exe/ruflow
|
110
138
|
- lib/ruflow.rb
|
139
|
+
- lib/ruflow/action.rb
|
140
|
+
- lib/ruflow/error/bad_return.rb
|
141
|
+
- lib/ruflow/error/mismatch_input_type.rb
|
142
|
+
- lib/ruflow/error/mismatch_output_input_type.rb
|
143
|
+
- lib/ruflow/error/mismatch_output_type.rb
|
144
|
+
- lib/ruflow/error/output_port_not_defined.rb
|
145
|
+
- lib/ruflow/flow.rb
|
111
146
|
- lib/ruflow/tasks/base.rb
|
112
147
|
- lib/ruflow/tasks/setup.rb
|
148
|
+
- lib/ruflow/type_checker.rb
|
113
149
|
- lib/ruflow/version.rb
|
114
150
|
- ruflow.gemspec
|
115
151
|
- setup_files/Gemfile
|
116
152
|
- setup_files/components/.gitkeep
|
153
|
+
- setup_files/components/actions/printer.rb
|
154
|
+
- setup_files/components/flows/hello_world.rb
|
117
155
|
- setup_files/ruflow_config.rb
|
118
156
|
homepage: https://github.com/victor95pc/ruflow
|
119
157
|
licenses: []
|