ducktrap 0.0.1

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.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.circle.yml +6 -0
  3. data/.gitignore +5 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.devtools +59 -0
  8. data/Guardfile +18 -0
  9. data/LICENSE +20 -0
  10. data/README.md +47 -0
  11. data/Rakefile +2 -0
  12. data/TODO +4 -0
  13. data/config/devtools.yml +2 -0
  14. data/config/flay.yml +3 -0
  15. data/config/flog.yml +2 -0
  16. data/config/heckle.yml +3 -0
  17. data/config/mutant.yml +2 -0
  18. data/config/reek.yml +98 -0
  19. data/config/yardstick.yml +2 -0
  20. data/ducktrap.gemspec +23 -0
  21. data/lib/ducktrap.rb +73 -0
  22. data/lib/ducktrap/builder.rb +36 -0
  23. data/lib/ducktrap/error.rb +48 -0
  24. data/lib/ducktrap/evaluator.rb +127 -0
  25. data/lib/ducktrap/evaluator/invalid.rb +30 -0
  26. data/lib/ducktrap/evaluator/static.rb +25 -0
  27. data/lib/ducktrap/formatter.rb +138 -0
  28. data/lib/ducktrap/mapper.rb +59 -0
  29. data/lib/ducktrap/nary.rb +148 -0
  30. data/lib/ducktrap/node.rb +94 -0
  31. data/lib/ducktrap/node/anima.rb +40 -0
  32. data/lib/ducktrap/node/anima/dump.rb +39 -0
  33. data/lib/ducktrap/node/anima/load.rb +39 -0
  34. data/lib/ducktrap/node/block.rb +44 -0
  35. data/lib/ducktrap/node/coercion.rb +7 -0
  36. data/lib/ducktrap/node/custom.rb +121 -0
  37. data/lib/ducktrap/node/disjunction.rb +8 -0
  38. data/lib/ducktrap/node/forward.rb +55 -0
  39. data/lib/ducktrap/node/guard_nil.rb +42 -0
  40. data/lib/ducktrap/node/hash.rb +7 -0
  41. data/lib/ducktrap/node/hash/transform.rb +53 -0
  42. data/lib/ducktrap/node/invalid.rb +29 -0
  43. data/lib/ducktrap/node/inverse.rb +46 -0
  44. data/lib/ducktrap/node/key.rb +61 -0
  45. data/lib/ducktrap/node/key/add.rb +42 -0
  46. data/lib/ducktrap/node/key/delete.rb +44 -0
  47. data/lib/ducktrap/node/key/dump.rb +38 -0
  48. data/lib/ducktrap/node/key/fetch.rb +49 -0
  49. data/lib/ducktrap/node/map.rb +42 -0
  50. data/lib/ducktrap/node/noop.rb +30 -0
  51. data/lib/ducktrap/node/primitive.rb +61 -0
  52. data/lib/ducktrap/node/static.rb +33 -0
  53. data/lib/ducktrap/nullary.rb +41 -0
  54. data/lib/ducktrap/pretty_dump.rb +31 -0
  55. data/lib/ducktrap/registry.rb +60 -0
  56. data/lib/ducktrap/singleton.rb +55 -0
  57. data/lib/ducktrap/unary.rb +153 -0
  58. data/spec/rcov.opts +7 -0
  59. data/spec/shared/inverse_behavior.rb +7 -0
  60. data/spec/spec_helper.rb +20 -0
  61. data/spec/support/ice_nine_config.rb +8 -0
  62. data/spec/support/let_mock_helper.rb +13 -0
  63. data/spec/unit/ducktrap/builder/class_methods/new_spec.rb +41 -0
  64. data/spec/unit/ducktrap/builder/new_spec.rb +41 -0
  65. data/spec/unit/ducktrap/class_methods/build_spec.rb +11 -0
  66. data/spec/unit/ducktrap/error/exception/pretty_inspect_spec.rb +22 -0
  67. data/spec/unit/ducktrap/error/pretty_inspect_spec.rb +19 -0
  68. data/spec/unit/ducktrap/evaluator/assert_successful_spec.rb +38 -0
  69. data/spec/unit/ducktrap/evaluator/invalid/output_spec.rb +14 -0
  70. data/spec/unit/ducktrap/evaluator/noop/output_spec.rb +14 -0
  71. data/spec/unit/ducktrap/evaluator/output_spec.rb +52 -0
  72. data/spec/unit/ducktrap/evaluator/pretty_inspect_spec.rb +63 -0
  73. data/spec/unit/ducktrap/evaluator/successful_predicate_spec.rb +36 -0
  74. data/spec/unit/ducktrap/failed_transformation_error/message_spec.rb +10 -0
  75. data/spec/unit/ducktrap/formatter/attribute_spec.rb +24 -0
  76. data/spec/unit/ducktrap/formatter/body_spec.rb +19 -0
  77. data/spec/unit/ducktrap/formatter/class_methods/new_spec.rb +14 -0
  78. data/spec/unit/ducktrap/formatter/initialize_spec.rb +14 -0
  79. data/spec/unit/ducktrap/formatter/name_spec.rb +25 -0
  80. data/spec/unit/ducktrap/formatter/nest_spec.rb +48 -0
  81. data/spec/unit/ducktrap/formatter/puts_spec.rb +36 -0
  82. data/spec/unit/ducktrap/mapper/builder/dumper_spec.rb +20 -0
  83. data/spec/unit/ducktrap/mapper/builder/loader_spec.rb +20 -0
  84. data/spec/unit/ducktrap/mapper/builder/object_spec.rb +90 -0
  85. data/spec/unit/ducktrap/mapper/class_methods/build_spec.rb +20 -0
  86. data/spec/unit/ducktrap/nary/builder/add_spec.rb +16 -0
  87. data/spec/unit/ducktrap/nary/builder/method_missing_spec.rb +44 -0
  88. data/spec/unit/ducktrap/nary/builder/output_spec.rb +16 -0
  89. data/spec/unit/ducktrap/nary/class_methods/build_spec.rb +22 -0
  90. data/spec/unit/ducktrap/nary/class_methods/included_spec.rb +13 -0
  91. data/spec/unit/ducktrap/nary/evaluator/output_spec.rb +79 -0
  92. data/spec/unit/ducktrap/nary/instance_methods/inverse_spec.rb +24 -0
  93. data/spec/unit/ducktrap/nary/instance_methods/pretty_inspect_spec.rb +31 -0
  94. data/spec/unit/ducktrap/node/anima/dump/evaluator/output_spec.rb +18 -0
  95. data/spec/unit/ducktrap/node/anima/dump/inverse_spec.rb +10 -0
  96. data/spec/unit/ducktrap/node/anima/dump/pretty_inspect_spec.rb +15 -0
  97. data/spec/unit/ducktrap/node/anima/evaluator/output_spec.rb +18 -0
  98. data/spec/unit/ducktrap/node/anima/load/evaluator/output_spec.rb +35 -0
  99. data/spec/unit/ducktrap/node/anima/load/inverse_spec.rb +10 -0
  100. data/spec/unit/ducktrap/node/anima/load/pretty_inspect_spec.rb +15 -0
  101. data/spec/unit/ducktrap/node/anima/pretty_inspect_spec.rb +15 -0
  102. data/spec/unit/ducktrap/node/block/evaluator/output_spec.rb +79 -0
  103. data/spec/unit/ducktrap/node/block/inverse_spec.rb +24 -0
  104. data/spec/unit/ducktrap/node/call_spec.rb +21 -0
  105. data/spec/unit/ducktrap/node/class_methods/build_spec.rb +11 -0
  106. data/spec/unit/ducktrap/node/class_methods/register_spec.rb +16 -0
  107. data/spec/unit/ducktrap/node/custom/builder/forward_spec.rb +54 -0
  108. data/spec/unit/ducktrap/node/custom/builder/inverse_spec.rb +54 -0
  109. data/spec/unit/ducktrap/node/custom/builder/object_spec.rb +54 -0
  110. data/spec/unit/ducktrap/node/custom/call_spec.rb +21 -0
  111. data/spec/unit/ducktrap/node/custom/class_methods/build_spec.rb +20 -0
  112. data/spec/unit/ducktrap/node/custom/inverse_spec.rb +12 -0
  113. data/spec/unit/ducktrap/node/custom/pretty_inspect_spec.rb +15 -0
  114. data/spec/unit/ducktrap/node/forward/evaluator/output_spec.rb +13 -0
  115. data/spec/unit/ducktrap/node/forward/inverse_spec.rb +14 -0
  116. data/spec/unit/ducktrap/node/forward/pretty_inspect_spec.rb +19 -0
  117. data/spec/unit/ducktrap/node/guard_nil/call_spec.rb +21 -0
  118. data/spec/unit/ducktrap/node/guard_nil/evaluator/output_spec.rb +27 -0
  119. data/spec/unit/ducktrap/node/guard_nil/inverse_spec.rb +12 -0
  120. data/spec/unit/ducktrap/node/hash/transform/evaluator/output_spec.rb +51 -0
  121. data/spec/unit/ducktrap/node/hash/transform/inverse_spec.rb +27 -0
  122. data/spec/unit/ducktrap/node/invalid/call_spec.rb +13 -0
  123. data/spec/unit/ducktrap/node/invalid/inverse_spec.rb +11 -0
  124. data/spec/unit/ducktrap/node/inverse/call_spec.rb +11 -0
  125. data/spec/unit/ducktrap/node/inverse/inverse_spec.rb +14 -0
  126. data/spec/unit/ducktrap/node/inverse/pretty_inspect_spec.rb +19 -0
  127. data/spec/unit/ducktrap/node/key/add/call_spec.rb +15 -0
  128. data/spec/unit/ducktrap/node/key/add/evaluator/call_spec.rb +15 -0
  129. data/spec/unit/ducktrap/node/key/add/inverse_spec.rb +14 -0
  130. data/spec/unit/ducktrap/node/key/delete/call_spec.rb +13 -0
  131. data/spec/unit/ducktrap/node/key/delete/evaluator/call_spec.rb +13 -0
  132. data/spec/unit/ducktrap/node/key/delete/inverse_spec.rb +13 -0
  133. data/spec/unit/ducktrap/node/key/dump/evaluator/output_spec.rb +37 -0
  134. data/spec/unit/ducktrap/node/key/dump/inverse_spec.rb +14 -0
  135. data/spec/unit/ducktrap/node/key/evaluator/key_spec.rb +26 -0
  136. data/spec/unit/ducktrap/node/key/fetch/evaluator/output_spec.rb +48 -0
  137. data/spec/unit/ducktrap/node/key/fetch/inverse_spec.rb +14 -0
  138. data/spec/unit/ducktrap/node/key/pretty_inspect_spec.rb +20 -0
  139. data/spec/unit/ducktrap/node/map/evaluator/output_spec.rb +22 -0
  140. data/spec/unit/ducktrap/node/map/inverse_spec.rb +15 -0
  141. data/spec/unit/ducktrap/node/noop/call_spec.rb +11 -0
  142. data/spec/unit/ducktrap/node/noop/inverse_spec.rb +9 -0
  143. data/spec/unit/ducktrap/node/pretty_inspect_spec.rb +17 -0
  144. data/spec/unit/ducktrap/node/primitive/call_spec.rb +19 -0
  145. data/spec/unit/ducktrap/node/primitive/inverse_spec.rb +13 -0
  146. data/spec/unit/ducktrap/node/primitive/pretty_inspect_spec.rb +15 -0
  147. data/spec/unit/ducktrap/node/run_spec.rb +46 -0
  148. data/spec/unit/ducktrap/node/static/call_spec.rb +13 -0
  149. data/spec/unit/ducktrap/node/static/inverse_spec.rb +14 -0
  150. data/spec/unit/ducktrap/nullary/class_methods/build_spec.rb +37 -0
  151. data/spec/unit/ducktrap/nullary/class_methods/included_spec.rb +7 -0
  152. data/spec/unit/ducktrap/pretty_dump/pretty_dump_spec.rb +47 -0
  153. data/spec/unit/ducktrap/pretty_dump/pretty_inspect_spec.rb +22 -0
  154. data/spec/unit/ducktrap/registry/lookup_spec.rb +27 -0
  155. data/spec/unit/ducktrap/registry/register_spec.rb +21 -0
  156. data/spec/unit/ducktrap/singleton/class_methods/included_spec.rb +13 -0
  157. data/spec/unit/ducktrap/singleton/class_methods/instance_spec.rb +19 -0
  158. data/spec/unit/ducktrap/singleton/instance_methods/inspect_spec.rb +19 -0
  159. data/spec/unit/ducktrap/singleton/instance_methods/pretty_inspect_spec.rb +17 -0
  160. data/spec/unit/ducktrap/unary/class_methods/build_spec.rb +18 -0
  161. data/spec/unit/ducktrap/unary/class_methods/included_spec.rb +14 -0
  162. data/spec/unit/ducktrap/unary/evaluator/output2_spec.rb +48 -0
  163. data/spec/unit/ducktrap/unary/evaluator/output_spec.rb +37 -0
  164. data/spec/unit/ducktrap/unary/instance_methods/pretty_inspect_spec.rb +15 -0
  165. metadata +399 -0
@@ -0,0 +1,94 @@
1
+ module Ducktrap
2
+ # Abstract base class for transformation nodes
3
+ class Node
4
+ include AbstractType, PrettyDump, Adamantium::Flat
5
+
6
+ # Return inversed ducktrap
7
+ #
8
+ # @param [Object] input
9
+ #
10
+ # @return [Evaluator]
11
+ #
12
+ # @api private
13
+ #
14
+ abstract_method :inverse
15
+
16
+ # Run ducktrap on input
17
+ #
18
+ # @param [Object] input
19
+ #
20
+ # @return [Evaluator]
21
+ #
22
+ # @api private
23
+ #
24
+ def call(input)
25
+ evaluator_klass.new(self, input)
26
+ end
27
+
28
+ # Process input and raise exception on error
29
+ #
30
+ # @param [Object] input
31
+ #
32
+ # @return [Object]
33
+ # if successful
34
+ #
35
+ # @raise [RuntimeError]
36
+ # otherwise
37
+ #
38
+ # @api private
39
+ #
40
+ def run(input)
41
+ evaluator = call(input)
42
+ evaluator.assert_successful
43
+ evaluator.output
44
+ end
45
+
46
+ # Register dsl name
47
+ #
48
+ # @param [Symbol] name
49
+ #
50
+ # @return [self]
51
+ #
52
+ # @api private
53
+ #
54
+ def self.register(name)
55
+ DSL.register(name, self)
56
+ end
57
+ private_class_method :register
58
+
59
+ # Build ducktrap
60
+ #
61
+ # @return [Ducktrap]
62
+ #
63
+ # @api private
64
+ #
65
+ def self.build(&block)
66
+ self::Block.build(&block)
67
+ end
68
+
69
+ private
70
+
71
+ # Dump object
72
+ #
73
+ # @param [Formatter] output
74
+ #
75
+ # @return [undefined]
76
+ #
77
+ # @api private
78
+ #
79
+ def dump(output)
80
+ output.name(self)
81
+ end
82
+
83
+ # Return evaluator class
84
+ #
85
+ # @return [Class:Evaluator]
86
+ #
87
+ # @api private
88
+ #
89
+ def evaluator_klass
90
+ self.class::Evaluator
91
+ end
92
+
93
+ end # Node
94
+ end # Ducktrap
@@ -0,0 +1,40 @@
1
+ module Ducktrap
2
+ class Node
3
+ # Base class for anima nodes
4
+ class Anima < self
5
+ include Nullary, Concord::Public.new(:model)
6
+
7
+ private
8
+
9
+ # Perform pretty dump
10
+ #
11
+ # @param [Formatter] output
12
+ #
13
+ # @return [undefined]
14
+ #
15
+ # @api private
16
+ #
17
+ def dump(output)
18
+ output.name(self)
19
+ output.attribute(:model, model)
20
+ end
21
+
22
+ # Evaluator base class for anima nodes
23
+ class Evaluator < Nullary::Evaluator
24
+
25
+ private
26
+
27
+ # Return model
28
+ #
29
+ # @return [Class:Anima]
30
+ #
31
+ # @api private
32
+ #
33
+ def model
34
+ context.model
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,39 @@
1
+ module Ducktrap
2
+ class Node
3
+ class Anima
4
+
5
+ # Dumper for anima
6
+ class Dump < self
7
+ register :anima_dump
8
+
9
+ # Return inverse ducktrap
10
+ #
11
+ # @return [Ducktrap]
12
+ #
13
+ # @api private
14
+ #
15
+ def inverse
16
+ Load.new(model)
17
+ end
18
+
19
+ # Evaluator for anima dump nodes
20
+ class Evaluator < Anima::Evaluator
21
+
22
+ private
23
+
24
+ # Process input
25
+ #
26
+ # @return [Hash]
27
+ # if successful
28
+ #
29
+ # @api private
30
+ #
31
+ def process
32
+ model.attributes_hash(input)
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ module Ducktrap
2
+ class Node
3
+ class Anima
4
+ # Load attributes hash
5
+ class Load < self
6
+ register :anima_load
7
+
8
+ # Return inverse ducktrap
9
+ #
10
+ # @return [Ducktrap]
11
+ #
12
+ # @api private
13
+ #
14
+ def inverse
15
+ Dump.new(model)
16
+ end
17
+
18
+ # Evaluator of anima load ducktrap
19
+ class Evaluator < Anima::Evaluator
20
+
21
+ private
22
+
23
+ # Process input
24
+ #
25
+ # @return [Object]
26
+ #
27
+ # @api private
28
+ #
29
+ def process
30
+ model.new(input)
31
+ rescue ::Anima::Error => exception
32
+ exception(exception)
33
+ end
34
+
35
+ end # Evaluator
36
+ end # Load
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,44 @@
1
+ module Ducktrap
2
+ class Node
3
+ # Ducktrap that returns last evaluator output of a chain and stops on first failure.
4
+ # Acts like AND with multiple inputs.
5
+ class Block < self
6
+ include Nary
7
+
8
+ # Return inverse ducktrap
9
+ #
10
+ # @return [Node]
11
+ #
12
+ # @api private
13
+ #
14
+ def inverse
15
+ self.class.new(inverse_body)
16
+ end
17
+
18
+ # Evaluator of chained ducktraps
19
+ class Evaluator < Nary::Evaluator
20
+
21
+ private
22
+
23
+ # Calculate evaluator
24
+ #
25
+ # @return [Object]
26
+ # if successful
27
+ #
28
+ # @return [Error]
29
+ # otherwise
30
+ #
31
+ # @api private
32
+ #
33
+ def process
34
+ body.inject(input) do |input, ducktrap|
35
+ evaluator = ducktrap.call(input)
36
+ return nested_error(evaluator) unless evaluator.successful?
37
+ evaluator.output
38
+ end
39
+ end
40
+
41
+ end # Evaluator
42
+ end # Block
43
+ end # Node
44
+ end # Ducktrap
@@ -0,0 +1,7 @@
1
+ module Ducktrap
2
+ class Node
3
+ # Transformatio node for primitive coercion
4
+ class Coercion
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,121 @@
1
+ module Ducktrap
2
+ class Node
3
+ # Custom, user defined node
4
+ class Custom < self
5
+ include Concord::Public.new(:forward_block, :inverse_block)
6
+
7
+ register :custom
8
+
9
+ # FIXME: Remove this after a while
10
+ register :extern
11
+
12
+ # Return inverse
13
+ #
14
+ # @return [Ducktrap]
15
+ #
16
+ # @api private
17
+ #
18
+ def inverse
19
+ self.class.new(inverse_block, forward_block)
20
+ end
21
+
22
+ # Run with input
23
+ #
24
+ # @param [Object] input
25
+ #
26
+ # @return [Evaluator]
27
+ #
28
+ # @api private
29
+ #
30
+ def call(input)
31
+ Evaluator::Static.new(self, input, forward_block.call(input))
32
+ end
33
+
34
+ private
35
+
36
+ # Dump object
37
+ #
38
+ # @param [Formatter] output
39
+ #
40
+ # @return [undefined]
41
+ #
42
+ # @api private
43
+ #
44
+ def dump(output)
45
+ output.name(self)
46
+ output.attribute(:forward, forward_block)
47
+ output.attribute(:inverse, inverse_block)
48
+ end
49
+
50
+ # Build external ducktrap
51
+ #
52
+ # @return [External]
53
+ #
54
+ # @api private
55
+ #
56
+ def self.build(&block)
57
+ Builder.new(self, &block).object
58
+ end
59
+
60
+ # Builder for external ducktrap
61
+ class Builder < Ducktrap::Builder
62
+
63
+ # Capture forward block
64
+ #
65
+ # @return [self]
66
+ #
67
+ # @api private
68
+ #
69
+ def forward(&block)
70
+ @forward_block = block
71
+ self
72
+ end
73
+
74
+ # Capture inverse block
75
+ #
76
+ # @return [self]
77
+ #
78
+ # @api private
79
+ #
80
+ def inverse(&block)
81
+ @inverse_block = block
82
+ self
83
+ end
84
+
85
+ # Return ducktrap
86
+ #
87
+ # @return [Ducktrap]
88
+ #
89
+ # @api private
90
+ #
91
+ def object
92
+ klass.new(forward_block, inverse_block)
93
+ end
94
+
95
+ private
96
+
97
+ # Return block
98
+ #
99
+ # @return [Proc]
100
+ #
101
+ # @api private
102
+ #
103
+ def forward_block
104
+ @forward_block || raise('No forward block specified!')
105
+ end
106
+
107
+ # Return inverse block
108
+ #
109
+ # @return [Proc]
110
+ #
111
+ # @api private
112
+ #
113
+ def inverse_block
114
+ @inverse_block || raise('No inverse block specified!')
115
+ end
116
+
117
+ end # Builder
118
+
119
+ end # Custom
120
+ end # Node
121
+ end # Ducktrap
@@ -0,0 +1,8 @@
1
+ module Ducktrap
2
+ class Node
3
+ # Node for disjunct input processing
4
+ class Disjunction < self
5
+ include Nary
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,55 @@
1
+ module Ducktrap
2
+ class Node
3
+ # Ducktrap with noop inverse
4
+ class Forward < self
5
+ include Unary, Concord::Public.new(:operand)
6
+
7
+ register :forward
8
+
9
+ # Return inverse node
10
+ #
11
+ # @return [Inverse]
12
+ #
13
+ # @api private
14
+ #
15
+ def inverse
16
+ Inverse.new(operand)
17
+ end
18
+
19
+ private
20
+
21
+ # Perform pretty dump
22
+ #
23
+ # @return [undefined]
24
+ #
25
+ # @api private
26
+ #
27
+ def dump(output)
28
+ output.name(self)
29
+ output.nest(:operand, operand)
30
+ end
31
+
32
+ # Evaluator for forward nodes
33
+ class Evaluator < Unary::Evaluator
34
+
35
+ private
36
+
37
+ # Return output
38
+ #
39
+ # @return [Object]
40
+ # if successful
41
+ #
42
+ # @return [Error]
43
+ # otherwise
44
+ #
45
+ # @api private
46
+ #
47
+ def process
48
+ operand_output
49
+ end
50
+
51
+ end # Evaluator
52
+
53
+ end # Forward
54
+ end # Node
55
+ end # Ducktrap