pipetree 0.0.3 → 0.0.4

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: fb0c97eae32d5e5a171288529691ed79df1a66ab
4
- data.tar.gz: eff1309c70264642f6b4a75f8e8e47baa8e7d45d
3
+ metadata.gz: 13019affb084e0a3dc4470feec4f21c904a1af83
4
+ data.tar.gz: ea2b5913c8afad622ad624cd77736c9b6a601304
5
5
  SHA512:
6
- metadata.gz: 97fde978c2a3c47f32fbb3161c88331b94d9c6e2d1722de2b2c07eedb1552bb93ec2d9b79ebdda5b696df09a28f493200ed4f95529ff769bf742382bd60dd514
7
- data.tar.gz: ded7af052db73f8428d8d2c5865e3fddfd3377037a5ec6f6ccd622b552ed72fba12af966f0406418e8ccc9b5c5ece397ca1bf6f8c7027c1c40a2874abb10bd26
6
+ metadata.gz: 521d4af02d44620e9a510a8e9703d843cda87aaccc02962d9b194881c837f56d3d1b4d9d77d0e5d127c66f9f24333ccabc94af763679eea3b98709b28d4ccf98
7
+ data.tar.gz: f49f1e93b4371a6282f71bfc24ab6241a86d118810cf0ab35a44f88f43adcd12529e6ad8fbac6ac8bbc156897ede6ad1fd9eabdcc368b70adc9b0f426373ce00
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
6
+ - 2.3.1
7
+ before_install:
8
+ - gem install bundler
data/Gemfile CHANGED
@@ -3,6 +3,4 @@ source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  gem "benchmark-ips"
6
-
7
- gem "dry-monads"
8
6
  gem "minitest-line"
data/README.md CHANGED
@@ -16,6 +16,15 @@ Instead of implementing the perfect API where users can override methods, call `
16
16
 
17
17
  This is way less tedious than climbing through `super` calls and callstacks.
18
18
 
19
+ ## Installation
20
+
21
+ In your `Gemfile`.
22
+
23
+ ```ruby
24
+ gem "pipetree"
25
+ ```
26
+
27
+ Pipetree runs with Ruby >= 1.9.3.
19
28
 
20
29
  ## TODO
21
30
 
@@ -5,7 +5,7 @@ module Pipetree::Flow::Inspect
5
5
 
6
6
  Proc = Struct.new(:name, :proc, :operator)
7
7
 
8
- def inspect_for(step)
8
+ def inspect_func(step)
9
9
  cfg = @step2proc[step]
10
10
  [cfg.name || super(cfg.proc), cfg.operator]
11
11
  end
@@ -0,0 +1,24 @@
1
+ # Map original proc or its name to the wrapped On.
2
+ # This class is solely dedicated for inspect and insert operations, and not
3
+ # involved at run-time at all.
4
+ class Pipetree::Flow::StepMap
5
+ def initialize
6
+ @hash = {}
7
+ end
8
+
9
+ def []=(step, (name, original_proc, operator))
10
+ @hash[step] = Pipetree::Flow::Inspect::Proc.new(name, original_proc, operator)
11
+ end
12
+
13
+ def [](key)
14
+ @hash[key]
15
+ end
16
+
17
+ def find_proc(original_proc)
18
+ method = original_proc.is_a?(String) ? :name : :proc
19
+
20
+ @hash.find do |step, inspect_proc|
21
+ inspect_proc.send(method) == original_proc and return step
22
+ end
23
+ end
24
+ end
data/lib/pipetree/flow.rb CHANGED
@@ -2,6 +2,8 @@ class Pipetree < Array
2
2
  class Flow < Array # yes, we could inherit, and so on.
3
3
  require "pipetree/flow/inspect"
4
4
  include Inspect
5
+ require "pipetree/flow/step_map"
6
+ require "pipetree/insert"
5
7
 
6
8
  module Operators
7
9
  # Optimize the most common steps with Stay/And objects that are faster than procs.
@@ -32,19 +34,17 @@ class Pipetree < Array
32
34
  # :private:
33
35
  # proc is the original step proc, e.g. Validate.
34
36
  def _insert(step, options, original_proc, operator)
35
- name = options[:name]
36
- options = { append: true } if options.empty? || options.keys == [:name]
37
+ options = { append: true }.merge(options)
37
38
 
38
39
  insert!(step, options).tap do
39
- @step2proc ||= {}
40
- @step2proc[step] = Inspect::Proc.new(name, original_proc, operator)
40
+ @step2proc ||= StepMap.new
41
+ @step2proc[step] = options[:name], original_proc, operator
41
42
  end
42
43
  end
43
44
 
44
45
  # :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) }
46
+ def index(proc) # @step2proc: { <On @proc> => {proc: @proc, name: "trb.validate", operator: "&"} }
47
+ on = @step2proc.find_proc(proc) and return super(on)
48
48
  end
49
49
  end
50
50
  include Operators
@@ -94,16 +94,6 @@ class Pipetree < Array
94
94
  end
95
95
  end
96
96
 
97
-
98
-
99
-
100
-
101
- require "pipetree/insert"
102
- module Macros
103
- def insert!(new_function, options)
104
- Pipetree::Insert.(self, new_function, options)
105
- end
106
- end
107
- include Macros # FIXME: we shouldn't expose #insert!
97
+ include Function::Insert::Macros # #insert!
108
98
  end
109
99
  end
@@ -2,12 +2,10 @@ module Pipetree::Function
2
2
  class Insert
3
3
  def call(arr, func, options)
4
4
  # arr = arr.dup
5
- return delete!(arr, func) if options[:delete]
6
- return replace!(arr, options[:replace], func) if options[:replace]
7
- return before!(arr, options[:before], func) if options[:before]
8
- return after!(arr, options[:after], func) if options[:after]
9
- return append!(arr, options[:append], func) if options[:append]
10
- return prepend!(arr, options[:prepend], func) if options[:prepend]
5
+ operations = [:delete, :replace, :before, :after, :append, :prepend]
6
+
7
+ # replace!(arr, options[:replace], func)
8
+ options.keys.reverse.each { |k| operations.include?(k) and return send("#{k}!", arr, options[k], func) }
11
9
 
12
10
  raise "[Pipetree] Unknown command #{options.inspect}" # TODO: test.
13
11
  # arr
@@ -27,7 +25,7 @@ module Pipetree::Function
27
25
  arr
28
26
  end
29
27
 
30
- def delete!(arr, removed_func)
28
+ def delete!(arr, _, removed_func)
31
29
  index = arr.index(removed_func)
32
30
  arr.delete_at(index)
33
31
 
@@ -59,6 +57,12 @@ module Pipetree::Function
59
57
  def prepend!(arr, old_func, new_func)
60
58
  arr.unshift(new_func)
61
59
  end
60
+
61
+ module Macros
62
+ def insert!(new_function, options)
63
+ Pipetree::Insert.(self, new_function, options)
64
+ end
65
+ end
62
66
  end
63
67
  end
64
68
 
@@ -3,7 +3,7 @@ module Pipetree::Inspect
3
3
  # TODO: remove in Representable::Debug.
4
4
  def inspect(options={ style: :line })
5
5
  names = each_with_index.collect do |func, i|
6
- [i, inspect_for(func)]
6
+ [i, inspect_func(func)]
7
7
  end
8
8
 
9
9
  return inspect_line(names) if options[:style] == :line
@@ -11,8 +11,17 @@ module Pipetree::Inspect
11
11
  end
12
12
 
13
13
  # open source file to retrieve the constant name.
14
- def inspect_for(func)
15
- File.readlines(func.source_location[0])[func.source_location[1]-1].match(/^\s+([\w\:]+)/)[1]
14
+ def inspect_func(func)
15
+ return inspect_object(func) unless func.is_a?(Proc)
16
+ inspect_proc(func)
17
+ end
18
+
19
+ def inspect_object(obj)
20
+ obj.inspect.sub(/0x\w+/, "")
21
+ end
22
+
23
+ def inspect_proc(proc)
24
+ File.readlines(proc.source_location[0])[proc.source_location[1]-1].match(/^\s+([\w\:]+)/)[1]
16
25
  end
17
26
 
18
27
  def inspect_line(names)
@@ -1,3 +1,3 @@
1
1
  class Pipetree < Array
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -1,9 +1,9 @@
1
1
  require "test_helper"
2
2
 
3
3
  class AlteringTest < Minitest::Spec
4
- A = ->(*) { }
4
+ A = ->(*) { "bla ruby 1.9 needs that" }
5
5
  B = ->(*) { }
6
- C = ->(*) { }
6
+ C = ->(*) { "otherwise it'll confuse empty procs" }
7
7
 
8
8
  # constructor.
9
9
  it do
@@ -26,6 +26,9 @@ class AlteringTest < Minitest::Spec
26
26
 
27
27
  it { Pipetree[A,B].insert!(C, prepend: true).inspect.must_equal %{[C|>A|>B]} }
28
28
  it { Pipetree[].insert!(C, prepend: true).inspect.must_equal %{[C]} }
29
+
30
+ # last option wins
31
+ it { Pipetree[A,B].insert!(C, after: B, prepend: true).inspect.must_equal %{[C|>A|>B]} }
29
32
  end
30
33
 
31
34
  require "pipetree/flow"
@@ -41,6 +44,5 @@ class FlowInsertTest < Minitest::Spec
41
44
  it { pipe = Pipetree::Flow[].>(A).>(C, prepend: true).inspect.must_equal %{[>C,>A]} }
42
45
  it { pipe = Pipetree::Flow[].>(A).>(C, replace: A).inspect.must_equal %{[>C]} }
43
46
  it { pipe = Pipetree::Flow[].>(A)._insert(A, {delete: true}, nil, nil).inspect.must_equal %{[]} }
44
-
45
47
  # FIXME: add :delete and :replace.
46
48
  end
data/test/flow_test.rb CHANGED
@@ -35,7 +35,7 @@ class FlowTest < Minitest::Spec
35
35
  # end
36
36
  # end
37
37
 
38
- Aaa = ->(*) { }
38
+ Aaa = ->(*) { "yo" }
39
39
  B = ->(*) { }
40
40
 
41
41
  let (:pipe) { pipe = Pipetree::Flow.new
@@ -105,11 +105,12 @@ class FlowTest < Minitest::Spec
105
105
  # #inspect
106
106
  Seventeen = ->(*) { snippet }
107
107
  Long = ->(*) { snippet }
108
+ Callable = Object.new # random callable object.
108
109
 
109
110
  describe "#inspect" do
110
- let (:pipe) { Pipetree::Flow.new.&(Aaa).>>(Long).<(B).%(Aaa).<(Seventeen).>(Long) }
111
+ let (:pipe) { Pipetree::Flow.new.&(Aaa).>>(Long).<(B).%(Aaa).<(Seventeen).>(Long).>(Callable) }
111
112
 
112
- it { pipe.inspect.must_equal %{[&Aaa,>>Long,<B,%Aaa,<Seventeen,>Long]} }
113
+ it { pipe.inspect.must_equal %{[&Aaa,>>Long,<B,%Aaa,<Seventeen,>Long,>#<Object:>]} }
113
114
 
114
115
  it { pipe.inspect(style: :rows).must_equal %{
115
116
  0 ==================================&Aaa
@@ -117,7 +118,8 @@ class FlowTest < Minitest::Spec
117
118
  2 <B====================================
118
119
  3 =================%Aaa=================
119
120
  4 <Seventeen============================
120
- 5 =================================>Long} }
121
+ 5 =================================>Long
122
+ 6 ===========================>#<Object:>} }
121
123
  end
122
124
 
123
125
  describe "#index" do
@@ -145,6 +147,39 @@ class FlowTest < Minitest::Spec
145
147
 
146
148
  pipe.>(Long, after: "pipe.b").inspect.must_equal %{[>pipe.aaa,>pipe.b,>Long,>pipe.aaa.aaa]}
147
149
  end
150
+
151
+ #---
152
+ # test decompose array
153
+ it do
154
+ pipe = Pipetree::Flow.new.
155
+ >>( ->(input, options) { [options[:key], input] } ). # passes [bla, input] as input.
156
+ &( ->((value, input), options) { input["x"] = value } ) # decomposes input.
157
+
158
+ pipe.(input={}, options={key: 1}).must_equal [Pipetree::Flow::Right, [1, {"x"=>1}]]
159
+ input.inspect.must_equal %{{"x"=>1}}
160
+ options.inspect.must_equal %{{:key=>1}}
161
+ end
162
+ end
163
+
164
+ #- StepMap
165
+ class StepMapTest < Minitest::Spec
166
+ it do
167
+ map = Pipetree::Flow::StepMap.new
168
+
169
+ original_proc = ->(*) { snippet }
170
+ step = ->(*) { original_proc }
171
+
172
+ original_proc2 = ->(*) { snippet }
173
+ step2 = ->(*) { original_proc2 }
174
+
175
+ map[step] = "my.step", original_proc, ">"
176
+ map[step2] = "my.step2", original_proc2, ">"
177
+
178
+ map.find_proc(original_proc).must_equal step
179
+ map.find_proc("my.step").must_equal step
180
+ map.find_proc(original_proc2).must_equal step2
181
+ map.find_proc("my.step2").must_equal step2
182
+ end
148
183
  end
149
184
 
150
185
  # TODO: instead of testing #index, test all options like :before, etc.
data/test/inspect_test.rb CHANGED
@@ -6,8 +6,9 @@ class InspectTest < Minitest::Spec
6
6
 
7
7
  M::AlphaConstant = ->(*) { }
8
8
  M::Beta = ->(*) { }
9
+ Callable = Object.new
9
10
 
10
- let (:pipe) { ::Pipetree[M::Beta, M::AlphaConstant, M::Beta, M::AlphaConstant, M::Beta, M::AlphaConstant, M::Beta, M::AlphaConstant, M::Beta, M::AlphaConstant, M::Beta] }
11
+ let (:pipe) { ::Pipetree[M::Beta, M::AlphaConstant, M::Beta, M::AlphaConstant, M::Beta, M::AlphaConstant, M::Beta, M::AlphaConstant, M::Beta, M::AlphaConstant, M::Beta, Callable] }
11
12
 
12
13
  it do
13
14
  puts pipe.inspect
@@ -25,9 +26,10 @@ class InspectTest < Minitest::Spec
25
26
  7|>M::AlphaConstant
26
27
  8|>M::Beta
27
28
  9|>M::AlphaConstant
28
- 10|>M::Beta}
29
+ 10|>M::Beta
30
+ 11|>#<Object:>}
29
31
  end
30
32
 
31
33
  # different separator
32
- it { ::Pipetree[M::AlphaConstant,M::Beta].inspect.must_equal %{[M::AlphaConstant|>M::Beta]} }
34
+ it { ::Pipetree[M::AlphaConstant,M::Beta,Callable].inspect.must_equal %{[M::AlphaConstant|>M::Beta|>#<Object:>]} }
33
35
  end
@@ -71,6 +71,17 @@ class PipelineTest < MiniTest::Spec
71
71
  Pipetree[First, Second].("", options={}, memory={})
72
72
  end
73
73
 
74
+ #---
75
+ #- #index
76
+ it do
77
+ A = ->(*) { snippet }
78
+ B = ->(*) { snippet }
79
+
80
+ pipe = Pipetree[A, B]
81
+ pipe.index(A).must_equal 0
82
+ pipe.index(B).must_equal 1
83
+ end
84
+
74
85
  # ######### collection :ratings
75
86
 
76
87
  # let (:ratings) {
@@ -147,6 +158,8 @@ class PipelineTest < MiniTest::Spec
147
158
 
148
159
  # it "replaces if exists" do
149
160
  # # pipeline.insert!(R::Default, replace: R::StopOnSkipable)
161
+
162
+
150
163
  # P::Insert.(pipeline, R::Default, replace: R::StopOnSkipable).must_equal P[R::GetValue, R::Default, R::StopOnNil]
151
164
  # pipeline.must_equal P[R::GetValue, R::StopOnSkipable, R::StopOnNil]
152
165
  # end
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.3
4
+ version: 0.0.4
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-05 00:00:00.000000000 Z
11
+ date: 2016-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -59,6 +59,7 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - ".travis.yml"
62
63
  - CHANGES.md
63
64
  - Gemfile
64
65
  - README.md
@@ -66,6 +67,7 @@ files:
66
67
  - lib/pipetree.rb
67
68
  - lib/pipetree/flow.rb
68
69
  - lib/pipetree/flow/inspect.rb
70
+ - lib/pipetree/flow/step_map.rb
69
71
  - lib/pipetree/insert.rb
70
72
  - lib/pipetree/inspect.rb
71
73
  - lib/pipetree/version.rb