pipetree 0.0.3 → 0.0.4

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