stages 0.0.1 → 0.1.0

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.
data/.autotest CHANGED
@@ -3,7 +3,7 @@ Autotest.add_hook(:initialize) do |at|
3
3
  at.add_exception(exception)
4
4
  end
5
5
 
6
- at.add_mapping(%r%^dataprocessing/pipeline(/stages)?/(.*).rb$%, true) do |filename, _|
6
+ at.add_mapping(%r%^lib(/stages)?/(.*).rb$%, true) do |filename, _|
7
7
  ['test/test_pipeline.rb', 'test/test_stages.rb']
8
8
  end
9
9
 
@@ -19,7 +19,7 @@ We have included some general purpose stages, map and select, which can accompli
19
19
 
20
20
  ```ruby
21
21
  pipeline = Evens.new | Map.new{ |x| x * 3} | Select.new{ |x| x % 7 == 0}
22
- (0..2).map{ |x| pipeline.run } #[0, 42, 84]}
22
+ 3.times{ pipeline.run } #[0, 42, 84]}
23
23
  ```
24
24
 
25
25
  Writing New Stages
data/Rakefile CHANGED
@@ -25,7 +25,7 @@ Jeweler::Tasks.new do |gem|
25
25
  gem.summary = "pipeline builder"
26
26
  gem.description = "pipeline builder"
27
27
  gem.email = "support@igodigital.com"
28
- gem.authors = ["Nathan Acuff", "Justin Hill", "Matt Brown", "Kyle Prifogle"]
28
+ gem.authors = ["The Justice Eight"]
29
29
  # dependencies defined in Gemfile
30
30
  end
31
31
  Jeweler::RubygemsDotOrgTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.1.0
data/examples/sing.rb ADDED
@@ -0,0 +1,48 @@
1
+ require "#{File.dirname(__FILE__)}/../lib/stages"
2
+
3
+ include Stages
4
+
5
+ #count the occurance of each letter in these song lyrics
6
+ def sing
7
+ { :do => 'doe a deer a female deer',
8
+ :re => 'ray a drop of golden sun',
9
+ :mi => 'me a name I call myself',
10
+ :fa => 'far a long long way to run',
11
+ :so => 'a needle pulling thread',
12
+ :la => 'a note to follow so',
13
+ :ti => 'a drink with jam and bread'}
14
+ end
15
+
16
+ def setup_pipeline
17
+ generator = EachElement.new sing.keys
18
+ loop = Restrict.new
19
+ get_lyric = HashLookup.new sing
20
+ each_character = EachInput.new{ |x| x.chars }
21
+ whitespace = Select.new{ |x| x != ' '}
22
+ pool = ResumeCount.new
23
+ subtotals = Map.new { |x| x.values.first }
24
+ iterator = EachInput.new
25
+ aggregator = SuperAggregator.new
26
+
27
+ generator | loop | get_lyric | each_character | whitespace | pool | subtotals | iterator | aggregator
28
+ end
29
+
30
+ class SuperAggregator < Stage
31
+ def initialize
32
+ @accumulator = Hash.new{ |h,k| h[k] = 0}
33
+ super()
34
+ end
35
+
36
+ def handle_value(value)
37
+ @accumulator[value[0]] += value[1]
38
+ while v = input
39
+ @accumulator[v[0]] += v[1]
40
+ end
41
+ output @accumulator
42
+ end
43
+ end
44
+
45
+ puts setup_pipeline.run.inspect
46
+
47
+
48
+
@@ -0,0 +1,34 @@
1
+ require "#{File.dirname(__FILE__)}/../lib/stages"
2
+
3
+ include Stages
4
+
5
+ #count the occurance of each letter in these song lyrics
6
+ def sing
7
+ { :do => 'doe a deer a female deer',
8
+ :re => 'ray a drop of golden sun',
9
+ :mi => 'me a name I call myself',
10
+ :fa => 'far a long long way to run',
11
+ :so => 'a needle pulling thread',
12
+ :la => 'a note to follow so',
13
+ :ti => 'a drink with jam and bread'}
14
+ end
15
+
16
+ def setup_pipeline
17
+ get_lyric = HashLookup.new sing
18
+ each_character = EachInput.new{ |x| x.chars }
19
+ whitespace = Select.new{ |x| x != ' '}
20
+ sub_pipeline = get_lyric | each_character | whitespace
21
+ process_elements = SubStage.new(sub_pipeline)
22
+
23
+ generator = EachElement.new sing.keys
24
+ subtotals = Map.new { |x| x.values.first }
25
+ iterator = EachInput.new
26
+ count = Count.new
27
+
28
+ generator | process_elements | subtotals | iterator | count
29
+ end
30
+
31
+ puts setup_pipeline.run.inspect
32
+
33
+
34
+
data/lib/stage_base.rb CHANGED
@@ -4,14 +4,23 @@ module Stages
4
4
 
5
5
  def initialize(&block)
6
6
  @block = block
7
- @fiber_delegate = Fiber.new do
7
+ initialize_loop
8
+ end
9
+
10
+ def initialize_loop
11
+ @fiber_delegate = Fiber.new do
8
12
  process
9
13
  die
10
14
  end
11
15
  end
12
16
 
13
17
  def run
14
- @fiber_delegate.resume
18
+ @fiber_delegate.resume
19
+ end
20
+
21
+ def continue
22
+ initialize_loop
23
+ @source.continue if @source
15
24
  end
16
25
 
17
26
  def die
@@ -38,10 +47,34 @@ module Stages
38
47
  Fiber.yield value
39
48
  end
40
49
 
41
- def |(other=nil)
42
- other.source = self
50
+ def |(other)
51
+ other.root_source.source = self
43
52
  other
44
53
  end
54
+
55
+ def root_source
56
+ source.nil? ? self : source.root_source
57
+ end
58
+
59
+ def drop_leftmost!
60
+ if @source.end?
61
+ @source = nil
62
+ else
63
+ @source.drop_leftmost!
64
+ end
65
+ end
66
+
67
+ def end?
68
+ @source.nil?
69
+ end
70
+
71
+ def length
72
+ if source
73
+ source.length + 1
74
+ else
75
+ 1
76
+ end
77
+ end
45
78
  end
46
79
  end
47
80
 
data/lib/stages.rb CHANGED
@@ -1,3 +1,3 @@
1
- require 'stage_base'
1
+ require "#{File.dirname(__FILE__)}/stage_base"
2
2
  Dir["#{File.dirname(__FILE__)}/stages/*.rb"].each { |file| require file.gsub(".rb", "")}
3
3
 
@@ -0,0 +1,11 @@
1
+ module Stages
2
+ class Count < Stage
3
+ def input
4
+ result = Hash.new{ |h, k| h[k] = 0 }
5
+ while v = source.run
6
+ result[v] += 1
7
+ end
8
+ result.empty? ? nil : result
9
+ end
10
+ end
11
+ end
@@ -4,7 +4,7 @@ module Stages
4
4
  @things = things
5
5
  super()
6
6
  end
7
-
7
+
8
8
  def process
9
9
  @things.each do |thing|
10
10
  output thing
@@ -0,0 +1,10 @@
1
+ module Stages
2
+ class EachInput < Stage
3
+ def handle_value(value)
4
+ value = @block.call(value) if @block
5
+ value.each do |i|
6
+ output i
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,28 @@
1
+ module Stages
2
+ class Restrict < Stage
3
+ alias :super_continue :continue
4
+
5
+ def initialize
6
+ @open = true
7
+ super()
8
+ end
9
+
10
+ def continue
11
+ @open = true
12
+ r = @last_value
13
+ @last_value = nil
14
+ r
15
+ end
16
+
17
+ def process
18
+ while value = input
19
+ while !@open
20
+ handle_value nil
21
+ end
22
+ @open = false
23
+ @last_value = value
24
+ handle_value value
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ module Stages
2
+ class Resume < Stage
3
+ def input
4
+ result = []
5
+ while v = source.run
6
+ result << v
7
+ end
8
+ continued = @source.continue
9
+ if continued.nil?
10
+ nil
11
+ else
12
+ { continued => result}
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Stages
2
+ class ResumeCount < Stage
3
+ def input
4
+ result = Hash.new{ |h, k| h[k] = 0 }
5
+ while v = source.run
6
+ result[v] += 1
7
+ end
8
+ continued = @source.continue
9
+ if continued.nil?
10
+ nil
11
+ else
12
+ { continued => result}
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ module Stages
2
+ class SubStage < Stage
3
+ def initialize(pipeline)
4
+ @pipeline = pipeline
5
+ super()
6
+ end
7
+
8
+ def handle_value(value)
9
+ results = []
10
+ subpipe = (EachElement.new([value]) | @pipeline)
11
+ while v = subpipe.run
12
+ results << v
13
+ end
14
+ @pipeline.drop_leftmost!
15
+ @pipeline.continue
16
+ results = results.first if results.length == 1
17
+ output ({ value => results })
18
+ end
19
+ end
20
+ end
data/stages.gemspec CHANGED
@@ -5,31 +5,39 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "stages"
8
- s.version = "0.0.1"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Nathan Acuff", "Justin Hill", "Matt Brown", "Kyle Prifogle"]
12
- s.date = "2012-01-13"
11
+ s.authors = ["The Justice Eight"]
12
+ s.date = "2012-01-14"
13
13
  s.description = "pipeline builder"
14
14
  s.email = "support@igodigital.com"
15
15
  s.extra_rdoc_files = [
16
- "README"
16
+ "README.md"
17
17
  ]
18
18
  s.files = [
19
19
  ".autotest",
20
20
  "Gemfile",
21
21
  "Gemfile.lock",
22
- "README",
22
+ "README.md",
23
23
  "Rakefile",
24
24
  "VERSION",
25
+ "examples/sing.rb",
26
+ "examples/sing_subpipes.rb",
25
27
  "lib/stage_base.rb",
26
28
  "lib/stages.rb",
29
+ "lib/stages/count.rb",
27
30
  "lib/stages/each_element.rb",
31
+ "lib/stages/each_input.rb",
28
32
  "lib/stages/evens.rb",
29
33
  "lib/stages/hash_lookup.rb",
30
34
  "lib/stages/map.rb",
31
35
  "lib/stages/multiples_of.rb",
36
+ "lib/stages/restrict.rb",
37
+ "lib/stages/resume.rb",
38
+ "lib/stages/resume_count.rb",
32
39
  "lib/stages/select.rb",
40
+ "lib/stages/sub_stage.rb",
33
41
  "stages.gemspec",
34
42
  "test/helper.rb",
35
43
  "test/test_pipeline.rb",
@@ -10,19 +10,19 @@ class TestPipeline < MiniTest::Unit::TestCase
10
10
  mx3.source = evens
11
11
  mx7.source = mx3
12
12
 
13
- result = (0..2).map{ |x| mx7.run }
13
+ result = (0..2).map{ mx7.run }
14
14
  assert_equal([0, 42, 84], result)
15
15
  end
16
16
 
17
17
  test 'pipeline pipe syntax works' do
18
18
  pipeline = Evens.new | MultiplesOf.new(3) | MultiplesOf.new(7)
19
- result = (0..2).map{ |x| pipeline.run }
19
+ result = (0..2).map{ pipeline.run }
20
20
  assert_equal([0, 42, 84], result)
21
21
  end
22
22
 
23
23
  test 'block stages work' do
24
24
  pipeline = Evens.new | Map.new{ |x| x * 3} | Select.new{ |x| x % 7 == 0}
25
- result = (0..2).map{ |x| pipeline.run }
25
+ result = (0..2).map{ pipeline.run }
26
26
  assert_equal([0, 42, 84], result)
27
27
  end
28
28
 
@@ -43,14 +43,5 @@ class TestPipeline < MiniTest::Unit::TestCase
43
43
  end
44
44
  assert_equal([1, 2], result)
45
45
  end
46
-
47
- def sing
48
- { :do => 'doe a deer a female deer',
49
- :re => 'ray a drop of golden sun',
50
- :mi => 'me a name I call myself',
51
- :fa => 'far a long long way to run',
52
- :so => 'A needle pulling thread',
53
- :la => 'a note to follow so',
54
- :ti => 'a drink with jam and bread'}
55
- end
46
+
56
47
  end
data/test/test_stages.rb CHANGED
@@ -11,34 +11,82 @@ class TestStages < MiniTest::Unit::TestCase
11
11
 
12
12
  test 'select' do
13
13
  pipeline = Evens.new | Select.new{ |val| val > 6}
14
- result = (0..2).map{ |x| pipeline.run }
14
+ result = (0..2).map{ pipeline.run }
15
15
  assert_equal([8, 10, 12], result)
16
16
  end
17
17
 
18
18
  test 'map' do
19
19
  pipeline = Evens.new | Map.new{ |val| val * 3}
20
- result = (0..2).map{ |x| pipeline.run }
20
+ result = (0..2).map{ pipeline.run }
21
21
  assert_equal([0, 6, 12], result)
22
22
  end
23
23
 
24
24
  test 'multiples_of' do
25
25
  pipeline = Evens.new | MultiplesOf.new(3)
26
- result = (0..3).map{ |x| pipeline.run }
26
+ result = (0..3).map{ pipeline.run }
27
27
  assert_equal([0, 6, 12, 18], result)
28
28
  end
29
29
 
30
30
  test 'each_element' do
31
31
  pipeline = EachElement.new([1, 2, 3])
32
- result = (0..2).map{ |x| pipeline.run }
32
+ result = (0..2).map{ pipeline.run }
33
33
  assert_equal([1, 2, 3], result)
34
34
  end
35
35
 
36
36
  test 'hash_lookup' do
37
37
  pipeline = EachElement.new([:do, :re, :mi]) | HashLookup.new(sing)
38
- result = (0..2).map{ |x| pipeline.run }
38
+ result = (0..2).map { pipeline.run }
39
39
  assert_equal(['doe a deer a female deer', 'ray a drop of golden sun', 'me a name I call myself'], result)
40
40
  end
41
41
 
42
+ test 'restrict' do
43
+ pipeline = Evens.new | Restrict.new | Map.new{ |x| x * 2}
44
+ result = []
45
+ while v = pipeline.run
46
+ result << v
47
+ end
48
+ assert_equal([0], result)
49
+ pipeline.continue
50
+ while v = pipeline.run
51
+ result << v
52
+ end
53
+ assert_equal([0, 4], result)
54
+ end
55
+
56
+ test 'each_input' do
57
+ pipeline = EachElement.new([[1, 2], [3, 4]]) | EachInput.new
58
+ result = []
59
+ while v = pipeline.run
60
+ result << v
61
+ end
62
+ assert_equal([1, 2, 3, 4], result)
63
+ end
64
+
65
+ test 'resume' do
66
+ pipeline = EachElement.new(%w(foo bar)) | Restrict.new | EachInput.new{ |x| x.chars} | Resume.new
67
+ result = []
68
+ while v = pipeline.run
69
+ result << v
70
+ end
71
+ assert_equal([{ 'foo' => %w(f o o)}, {'bar' => %w(b a r)}], result)
72
+ end
73
+
74
+ test 'resume with count' do
75
+ resume = ResumeCount.new
76
+ pipeline = EachElement.new(%w(foo bar)) | Restrict.new | EachInput.new{ |x| x.chars} | Map.new{ |x| x.to_sym } | resume
77
+ result = pipeline.run
78
+ assert_equal({ 'foo' => { :f => 1, :o => 2}}, result)
79
+ end
80
+
81
+ test 'substage instead of resume' do
82
+ sub = EachInput.new{ |x| x.chars } | Map.new{ |x| x.to_sym} | Count.new
83
+ pipeline = EachElement.new(%w(foo bar)) | SubStage.new(sub)
84
+ result = pipeline.run
85
+ assert_equal({ 'foo' => { :f => 1, :o => 2}}, result)
86
+ result = pipeline.run
87
+ assert_equal({ 'bar' => { :b => 1, :a => 1, :r => 1}}, result)
88
+ end
89
+
42
90
  def sing
43
91
  { :do => 'doe a deer a female deer',
44
92
  :re => 'ray a drop of golden sun',
metadata CHANGED
@@ -2,18 +2,15 @@
2
2
  name: stages
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
- - Nathan Acuff
9
- - Justin Hill
10
- - Matt Brown
11
- - Kyle Prifogle
8
+ - The Justice Eight
12
9
  autorequire:
13
10
  bindir: bin
14
11
  cert_chain: []
15
12
 
16
- date: 2012-01-13 00:00:00 Z
13
+ date: 2012-01-14 00:00:00 Z
17
14
  dependencies:
18
15
  - !ruby/object:Gem::Dependency
19
16
  name: rake
@@ -33,22 +30,30 @@ executables: []
33
30
  extensions: []
34
31
 
35
32
  extra_rdoc_files:
36
- - README
33
+ - README.md
37
34
  files:
38
35
  - .autotest
39
36
  - Gemfile
40
37
  - Gemfile.lock
41
- - README
38
+ - README.md
42
39
  - Rakefile
43
40
  - VERSION
41
+ - examples/sing.rb
42
+ - examples/sing_subpipes.rb
44
43
  - lib/stage_base.rb
45
44
  - lib/stages.rb
45
+ - lib/stages/count.rb
46
46
  - lib/stages/each_element.rb
47
+ - lib/stages/each_input.rb
47
48
  - lib/stages/evens.rb
48
49
  - lib/stages/hash_lookup.rb
49
50
  - lib/stages/map.rb
50
51
  - lib/stages/multiples_of.rb
52
+ - lib/stages/restrict.rb
53
+ - lib/stages/resume.rb
54
+ - lib/stages/resume_count.rb
51
55
  - lib/stages/select.rb
56
+ - lib/stages/sub_stage.rb
52
57
  - stages.gemspec
53
58
  - test/helper.rb
54
59
  - test/test_pipeline.rb
@@ -66,7 +71,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
66
71
  requirements:
67
72
  - - ">="
68
73
  - !ruby/object:Gem::Version
69
- hash: 4101338441187827743
74
+ hash: 1745323606775845054
70
75
  segments:
71
76
  - 0
72
77
  version: "0"