pipetree 0.0.2 → 0.0.3

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
  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