ruflow 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|