pipetree 0.0.2 → 0.0.3

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
  SHA1:
3
- metadata.gz: 372090919caec356b0dccdfb2c3dc80ff18e565c
4
- data.tar.gz: 4c34b1b76303b7df53db05605b2037f2f559b7f9
3
+ metadata.gz: fb0c97eae32d5e5a171288529691ed79df1a66ab
4
+ data.tar.gz: eff1309c70264642f6b4a75f8e8e47baa8e7d45d
5
5
  SHA512:
6
- metadata.gz: b29ec2b9ea9f2503ebf53336ae433fdf54c57eb1d9f0ffb40750ec4d093608978fec321453e357e88fd939359921535eb76ea4fa4f9b1aedc030364cab215723
7
- data.tar.gz: 9cc798a6dd1d4d055d627e21533e4212060afb55583dd5766ce76449d1aa54714c18800610281d7de00015184aa5bb8f91d01e564cc9c5916eac018a588f1ce9
6
+ metadata.gz: 97fde978c2a3c47f32fbb3161c88331b94d9c6e2d1722de2b2c07eedb1552bb93ec2d9b79ebdda5b696df09a28f493200ed4f95529ff769bf742382bd60dd514
7
+ data.tar.gz: ded7af052db73f8428d8d2c5865e3fddfd3377037a5ec6f6ccd622b552ed72fba12af966f0406418e8ccc9b5c5ece397ca1bf6f8c7027c1c40a2874abb10bd26
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 0.0.3
2
+
3
+ * Improved insert semantics.
4
+
1
5
  # 0.0.2
2
6
 
3
7
  * Add `Pipetree::Flow`.
data/lib/pipetree.rb CHANGED
@@ -1,6 +1,4 @@
1
1
  class Pipetree < Array
2
- VERSION = "0.0.1"
3
-
4
2
  # Allows to implement a pipeline of filters where a value gets passed in and the result gets
5
3
  # passed to the next callable object.
6
4
  Stop = Class.new
data/lib/pipetree/flow.rb CHANGED
@@ -1,104 +1,109 @@
1
- class Pipetree::Flow < Array # yes, we could inherit, and so on.
2
- require "pipetree/flow/inspect"
3
- include Inspect
4
-
5
- module Operators
6
- # Optimize the most common steps with Stay/And objects that are faster than procs.
7
- def <(proc, options=nil)
8
- _insert On.new(Left, Stay.new(proc)), options, proc, "<"
9
- end
1
+ class Pipetree < Array
2
+ class Flow < Array # yes, we could inherit, and so on.
3
+ require "pipetree/flow/inspect"
4
+ include Inspect
5
+
6
+ module Operators
7
+ # Optimize the most common steps with Stay/And objects that are faster than procs.
8
+ def <(proc, options={})
9
+ _insert On.new(Left, Stay.new(proc)), options, proc, "<"
10
+ end
10
11
 
11
- # OnRight-> ? Right, input : Left, input
12
- def &(proc, options=nil)
13
- _insert On.new(Right, And.new(proc)), options, proc, "&"
14
- end
12
+ # OnRight-> ? Right, input : Left, input
13
+ def &(proc, options={})
14
+ _insert On.new(Right, And.new(proc)), options, proc, "&"
15
+ end
15
16
 
16
- # TODO: test me.
17
- def >(proc, options=nil)
18
- _insert On.new(Right, Stay.new(proc)), options, proc, ">"
19
- end
17
+ # TODO: test me.
18
+ def >(proc, options={})
19
+ _insert On.new(Right, Stay.new(proc)), options, proc, ">"
20
+ end
20
21
 
21
- def >>(proc, options=nil)
22
- _insert On.new(Right,
23
- ->(last, input, options) { [Right, proc.(input, options)] } ), options, proc, ">>"
24
- end
22
+ def >>(proc, options={})
23
+ _insert On.new(Right,
24
+ ->(last, input, options) { [Right, proc.(input, options)] } ), options, proc, ">>"
25
+ end
25
26
 
26
- def %(proc, options=nil)
27
- # no condition is needed, and we want to stay on the same track, too.
28
- _insert Stay.new(proc), options, proc, "%"
29
- end
27
+ def %(proc, options={})
28
+ # no condition is needed, and we want to stay on the same track, too.
29
+ _insert Stay.new(proc), options, proc, "%"
30
+ end
30
31
 
31
- # :private:
32
- # proc is the original step proc, e.g. Validate.
33
- def _insert(step, options, proc, operator)
34
- options ||= { append: true } # DISCUSS: needed?
32
+ # :private:
33
+ # proc is the original step proc, e.g. Validate.
34
+ def _insert(step, options, original_proc, operator)
35
+ name = options[:name]
36
+ options = { append: true } if options.empty? || options.keys == [:name]
35
37
 
36
- insert!(step, options).tap do
37
- @debug ||= {}
38
- @debug[step] = Inspect::Proc.new(proc, operator)
38
+ insert!(step, options).tap do
39
+ @step2proc ||= {}
40
+ @step2proc[step] = Inspect::Proc.new(name, original_proc, operator)
41
+ end
42
+ end
43
+
44
+ # :private:
45
+ def index(step) # @step2proc: { <On @proc> => {proc: @proc, name: "trb.validate", operator: "&"} }
46
+ method = step.is_a?(String) ? :name : :proc
47
+ @step2proc.find { |on, inspect_proc| inspect_proc.send(method) == step and return super(on) }
39
48
  end
40
49
  end
41
- end
42
- include Operators
50
+ include Operators
43
51
 
44
- # Actual implementation of Pipetree:Flow. Yes, it's that simple!
45
- def call(input, options)
46
- input = [Right, input]
52
+ # Actual implementation of Pipetree:Flow. Yes, it's that simple!
53
+ def call(input, options)
54
+ input = [Right, input]
47
55
 
48
- inject(input) do |memooo, step|
49
- last, memo = memooo
50
- step.call(last, memo, options)
56
+ inject(input) do |memooo, step|
57
+ last, memo = memooo
58
+ step.call(last, memo, options)
59
+ end
51
60
  end
52
- end
53
-
54
- def index(step) # @debug maps the original user's step proc to the On instance (or any kind of wrapper proc).
55
- @debug.find { |on, inspect_proc| inspect_proc.proc == step and return super(on) }
56
- end
57
61
 
58
- # Directions emitted by steps.
59
- Left = Class.new
60
- Right = Class.new
62
+ # Directions emitted by steps.
63
+ Left = Class.new
64
+ Right = Class.new
61
65
 
62
- # Incoming direction must be Left/Right.
63
- class On
64
- def initialize(direction, proc)
65
- @direction, @proc = direction, proc
66
- end
66
+ # Incoming direction must be Left/Right.
67
+ class On
68
+ def initialize(direction, proc)
69
+ @direction, @proc = direction, proc
70
+ end
67
71
 
68
- def call(last, input, options)
69
- return [last, input] unless last == @direction # return unless incoming direction is Right (or Left).
70
- @proc.(last, input, options)
72
+ def call(last, input, options)
73
+ return [last, input] unless last == @direction # return unless incoming direction is Right (or Left).
74
+ @proc.(last, input, options)
75
+ end
71
76
  end
72
- end
73
77
 
74
- # Call step proc and return (Right || Left).
75
- class And
76
- def initialize(proc)
77
- @proc = proc
78
- end
78
+ # Call step proc and return (Right || Left).
79
+ class And
80
+ def initialize(proc)
81
+ @proc = proc
82
+ end
79
83
 
80
- def call(last, input, options)
81
- @proc.(input, options) ? [Right, input] : [Left, input]
84
+ def call(last, input, options)
85
+ @proc.(input, options) ? [Right, input] : [Left, input]
86
+ end
82
87
  end
83
- end
84
88
 
85
- # Call step proc and return incoming last step.
86
- class Stay < And
87
- def call(last, input, options)
88
- @proc.(input, options)
89
- [last, input] # simply pass through the current direction: either [Left, input] or [Right, input].
89
+ # Call step proc and return incoming last step.
90
+ class Stay < And
91
+ def call(last, input, options)
92
+ @proc.(input, options)
93
+ [last, input] # simply pass through the current direction: either [Left, input] or [Right, input].
94
+ end
90
95
  end
91
- end
92
96
 
93
97
 
94
98
 
95
99
 
96
100
 
97
- require "pipetree/insert"
98
- module Macros
99
- def insert!(new_function, options)
100
- Pipetree::Insert.(self, new_function, options)
101
+ require "pipetree/insert"
102
+ module Macros
103
+ def insert!(new_function, options)
104
+ Pipetree::Insert.(self, new_function, options)
105
+ end
101
106
  end
107
+ include Macros # FIXME: we shouldn't expose #insert!
102
108
  end
103
- include Macros # FIXME: we shouldn't expose #insert!
104
109
  end
@@ -3,11 +3,11 @@ require "pipetree/inspect"
3
3
  module Pipetree::Flow::Inspect
4
4
  include ::Pipetree::Inspect
5
5
 
6
- Proc = Struct.new(:proc, :operator)
6
+ Proc = Struct.new(:name, :proc, :operator)
7
7
 
8
8
  def inspect_for(step)
9
- debug = @debug[step]
10
- [super(debug.proc), debug.operator]
9
+ cfg = @step2proc[step]
10
+ [cfg.name || super(cfg.proc), cfg.operator]
11
11
  end
12
12
 
13
13
  def inspect_line(names)
@@ -18,4 +18,26 @@ module Pipetree::Flow::Inspect
18
18
  def inspect_row(index, name)
19
19
  "#{index} #{name.last}#{name.first}"
20
20
  end
21
+
22
+ def inspect_rows(names)
23
+ string = names.collect do |i, (name, operator)|
24
+
25
+ op = "#{operator}#{name}"
26
+ padding = 38
27
+
28
+ proc = if operator == "<"
29
+ sprintf("%- #{padding}s", op)
30
+ elsif [">", ">>", "&"].include?(operator.to_s)
31
+ sprintf("% #{padding}s", op)
32
+ else
33
+ pad = " " * ((padding - op.length) / 2)
34
+ "#{pad}#{op}#{pad}"
35
+ end
36
+
37
+ proc = proc.gsub(" ", "=")
38
+
39
+ sprintf("%2d %s", i, proc)
40
+ end.join("\n")
41
+ "\n#{string}"
42
+ end
21
43
  end
@@ -15,24 +15,30 @@ module Pipetree::Function
15
15
 
16
16
  private
17
17
  def replace!(arr, old_func, new_func)
18
- arr.each_with_index { |func, index|
19
- if func.is_a?(Collect)
20
- arr[index] = Collect[*Pipeline::Insert.(func, new_func, replace: old_func)]
21
- end
18
+ arr[arr.index(old_func)] = new_func
22
19
 
23
- arr[index] = new_func if func==old_func
24
- }
20
+ # arr.each_with_index { |func, index|
21
+ # if func.is_a?(::Pipetree::Collect)
22
+ # arr[index] = Collect[*Pipeline::Insert.(func, new_func, replace: old_func)]
23
+ # end
24
+
25
+ # arr[index] = new_func if func==old_func
26
+ # }
27
+ arr
25
28
  end
26
29
 
27
30
  def delete!(arr, removed_func)
28
- arr.delete(removed_func)
31
+ index = arr.index(removed_func)
32
+ arr.delete_at(index)
29
33
 
30
34
  # TODO: make nice.
31
- arr.each_with_index { |func, index|
32
- if func.is_a?(Collect)
33
- arr[index] = Collect[*Pipeline::Insert.(func, removed_func, delete: true)]
34
- end
35
- }
35
+ # arr.each_with_index { |func, index|
36
+ # if func.is_a?(Collect)
37
+ # arr[index] = Collect[*Pipeline::Insert.(func, removed_func, delete: true)]
38
+ # end
39
+ # }
40
+
41
+ arr
36
42
  end
37
43
 
38
44
  # TODO: not nested.
@@ -7,14 +7,7 @@ module Pipetree::Inspect
7
7
  end
8
8
 
9
9
  return inspect_line(names) if options[:style] == :line
10
-
11
- string = names.collect do |i, name|
12
- index = sprintf("%2d", i)
13
- inspect_row(index, name)
14
- end.join("\n")
15
- # name = sprintf("%-60.300s", name) # no idea what i'm doing here.
16
- # "#{index}) #{name} #{func.source_location.join(":")}"
17
- "\n#{string}"
10
+ inspect_rows(names)
18
11
  end
19
12
 
20
13
  # open source file to retrieve the constant name.
@@ -27,6 +20,16 @@ module Pipetree::Inspect
27
20
  "[#{string}]"
28
21
  end
29
22
 
23
+ def inspect_rows(names)
24
+ string = names.collect do |i, name|
25
+ index = sprintf("%2d", i)
26
+ inspect_row(index, name)
27
+ end.join("\n")
28
+ # name = sprintf("%-60.300s", name) # no idea what i'm doing here.
29
+ # "#{index}) #{name} #{func.source_location.join(":")}"
30
+ "\n#{string}"
31
+ end
32
+
30
33
  def inspect_row(index, name)
31
34
  "#{index}|>#{name}"
32
35
  end
@@ -1,3 +1,3 @@
1
- module Pipetree
2
- VERSION = "0.0.2"
1
+ class Pipetree < Array
2
+ VERSION = "0.0.3"
3
3
  end
@@ -28,6 +28,7 @@ class AlteringTest < Minitest::Spec
28
28
  it { Pipetree[].insert!(C, prepend: true).inspect.must_equal %{[C]} }
29
29
  end
30
30
 
31
+ require "pipetree/flow"
31
32
  class FlowInsertTest < Minitest::Spec
32
33
  A = ->{ }
33
34
  B = ->{ }
@@ -38,7 +39,8 @@ class FlowInsertTest < Minitest::Spec
38
39
  it { pipe = Pipetree::Flow[].>(A).>(B).>(C, after: A).inspect.must_equal %{[>A,>C,>B]} }
39
40
  it { pipe = Pipetree::Flow[].>(A).>(C, append: true).inspect.must_equal %{[>A,>C]} }
40
41
  it { pipe = Pipetree::Flow[].>(A).>(C, prepend: true).inspect.must_equal %{[>C,>A]} }
41
- # it { pipe = Pipetree::Flow[].>(A).>(C, replace: A).inspect.must_equal %{[>C]} }
42
+ it { pipe = Pipetree::Flow[].>(A).>(C, replace: A).inspect.must_equal %{[>C]} }
43
+ it { pipe = Pipetree::Flow[].>(A)._insert(A, {delete: true}, nil, nil).inspect.must_equal %{[]} }
42
44
 
43
45
  # FIXME: add :delete and :replace.
44
46
  end
data/test/flow_test.rb CHANGED
@@ -28,17 +28,17 @@ require "json"
28
28
  class FlowTest < Minitest::Spec
29
29
  # TODO: test each function from & to > is only called once!
30
30
  # describe "#call" do
31
- # let (:pipe) { Pipetree::Flow[] }
31
+ # let (:pipe) { Pipetree::Flow.new }
32
32
  # it do
33
33
  # pipe.>> ->(*) { puts "snippet" }
34
34
  # pipe.({},{})
35
35
  # end
36
36
  # end
37
37
 
38
- A = ->(*) { }
39
- B = ->(*) { }
38
+ Aaa = ->(*) { }
39
+ B = ->(*) { }
40
40
 
41
- let (:pipe) { pipe = Pipetree::Flow[]
41
+ let (:pipe) { pipe = Pipetree::Flow.new
42
42
  pipe.& ->(value, options) { value && options["deserializer.result"] = JSON.parse(value) }
43
43
  pipe.& ->(value, options) { options["deserializer.result"]["key"] == 1 ? true : (options["contract.errors"]=false) }
44
44
  pipe.& ->(value, options) { options["deserializer.result"]["key2"] == 2 ? true : (options["contract.errors.2"]="screwd";false) }
@@ -64,7 +64,7 @@ class FlowTest < Minitest::Spec
64
64
  options.must_equal({"deserializer.result"=>{"key"=>2}, "contract.errors"=>false, "after_deserialize.fail"=>true, "meantime"=>true, "after_meantime.left?"=>true})
65
65
  end
66
66
 
67
- it "what" do
67
+ it do
68
68
  options = {}
69
69
  pipe.(%{{"key": 1,"key2":null}}, options)#.must_equal ""
70
70
 
@@ -83,7 +83,7 @@ class FlowTest < Minitest::Spec
83
83
  #---
84
84
  # #>
85
85
  describe "#>" do
86
- let (:pipe) { Pipetree::Flow[] }
86
+ let (:pipe) { Pipetree::Flow.new }
87
87
  it {
88
88
  pipe.> ->(input, options) { input.reverse }
89
89
  # pipe.| B
@@ -94,7 +94,7 @@ class FlowTest < Minitest::Spec
94
94
 
95
95
  # #>>
96
96
  describe "#>>" do
97
- let (:pipe) { Pipetree::Flow[] }
97
+ let (:pipe) { Pipetree::Flow.new }
98
98
  it {
99
99
  pipe.>> ->(input, options) { input.reverse }
100
100
  pipe.("Hallo", {}).must_equal [Pipetree::Flow::Right, "ollaH"]
@@ -103,22 +103,47 @@ class FlowTest < Minitest::Spec
103
103
 
104
104
  #---
105
105
  # #inspect
106
+ Seventeen = ->(*) { snippet }
107
+ Long = ->(*) { snippet }
108
+
106
109
  describe "#inspect" do
107
- let (:pipe) { Pipetree::Flow[].&(A).<(B).%(A) }
110
+ let (:pipe) { Pipetree::Flow.new.&(Aaa).>>(Long).<(B).%(Aaa).<(Seventeen).>(Long) }
108
111
 
109
- it { pipe.inspect.must_equal %{[&A,<B,%A]} }
112
+ it { pipe.inspect.must_equal %{[&Aaa,>>Long,<B,%Aaa,<Seventeen,>Long]} }
110
113
 
111
114
  it { pipe.inspect(style: :rows).must_equal %{
112
- 0 &A
113
- 1 <B
114
- 2 %A} }
115
+ 0 ==================================&Aaa
116
+ 1 ================================>>Long
117
+ 2 <B====================================
118
+ 3 =================%Aaa=================
119
+ 4 <Seventeen============================
120
+ 5 =================================>Long} }
115
121
  end
116
122
 
117
123
  describe "#index" do
118
- let (:pipe) { Pipetree::Flow[].&(A).<(B).%(A) }
124
+ let (:pipe) { Pipetree::Flow.new.&(Aaa).<(B).%(Aaa, name: "a.triple") }
119
125
 
120
126
  it { pipe.index(B).must_equal 1 }
121
- it { pipe.index(A).must_equal 0 }
127
+ it { pipe.index(Aaa).must_equal 0 }
128
+ # with alias
129
+ it { pipe.index("a.triple").must_equal 2 }
130
+ end
131
+
132
+ #---
133
+ # with aliases
134
+ it do
135
+ pipe = Pipetree::Flow.new.
136
+ >(Aaa, name: "pipe.aaa").
137
+ >(B, name: "pipe.b").
138
+ >(Aaa, name: "pipe.aaa.aaa")
139
+
140
+ pipe.inspect.must_equal %{[>pipe.aaa,>pipe.b,>pipe.aaa.aaa]}
141
+ pipe.inspect(style: :rows).must_equal %{
142
+ 0 =============================>pipe.aaa
143
+ 1 ===============================>pipe.b
144
+ 2 =========================>pipe.aaa.aaa}
145
+
146
+ pipe.>(Long, after: "pipe.b").inspect.must_equal %{[>pipe.aaa,>pipe.b,>Long,>pipe.aaa.aaa]}
122
147
  end
123
148
  end
124
149
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pipetree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-01 00:00:00.000000000 Z
11
+ date: 2016-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler