alf 0.9.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.
Files changed (94) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +42 -0
  4. data/LICENCE.md +22 -0
  5. data/Manifest.txt +15 -0
  6. data/README.md +769 -0
  7. data/Rakefile +23 -0
  8. data/TODO.md +26 -0
  9. data/alf.gemspec +191 -0
  10. data/alf.noespec +30 -0
  11. data/bin/alf +31 -0
  12. data/examples/autonum.alf +6 -0
  13. data/examples/cities.rash +4 -0
  14. data/examples/clip.alf +3 -0
  15. data/examples/compact.alf +2 -0
  16. data/examples/database.alf +6 -0
  17. data/examples/defaults.alf +3 -0
  18. data/examples/extend.alf +3 -0
  19. data/examples/group.alf +3 -0
  20. data/examples/intersect.alf +4 -0
  21. data/examples/join.alf +2 -0
  22. data/examples/minus.alf +8 -0
  23. data/examples/nest.alf +2 -0
  24. data/examples/nulls.rash +3 -0
  25. data/examples/parts.rash +6 -0
  26. data/examples/project.alf +2 -0
  27. data/examples/quota.alf +4 -0
  28. data/examples/rename.alf +3 -0
  29. data/examples/restrict.alf +2 -0
  30. data/examples/runall.sh +26 -0
  31. data/examples/schema.yaml +28 -0
  32. data/examples/sort.alf +4 -0
  33. data/examples/summarize.alf +16 -0
  34. data/examples/suppliers.rash +5 -0
  35. data/examples/supplies.rash +12 -0
  36. data/examples/ungroup.alf +4 -0
  37. data/examples/union.alf +3 -0
  38. data/examples/unnest.alf +4 -0
  39. data/examples/with.alf +23 -0
  40. data/lib/alf.rb +2984 -0
  41. data/lib/alf/loader.rb +1 -0
  42. data/lib/alf/renderer/text.rb +153 -0
  43. data/lib/alf/renderer/yaml.rb +22 -0
  44. data/lib/alf/version.rb +14 -0
  45. data/spec/aggregator_spec.rb +62 -0
  46. data/spec/alf_spec.rb +47 -0
  47. data/spec/assumptions_spec.rb +15 -0
  48. data/spec/environment/explicit_spec.rb +15 -0
  49. data/spec/environment/folder_spec.rb +30 -0
  50. data/spec/examples_spec.rb +26 -0
  51. data/spec/lispy_spec.rb +23 -0
  52. data/spec/operator/command_methods_spec.rb +38 -0
  53. data/spec/operator/non_relational/autonum_spec.rb +61 -0
  54. data/spec/operator/non_relational/clip_spec.rb +49 -0
  55. data/spec/operator/non_relational/compact/buffer_based.rb +30 -0
  56. data/spec/operator/non_relational/compact/sort_based_spec.rb +30 -0
  57. data/spec/operator/non_relational/compact_spec.rb +38 -0
  58. data/spec/operator/non_relational/defaults_spec.rb +55 -0
  59. data/spec/operator/non_relational/sort_spec.rb +66 -0
  60. data/spec/operator/relational/extend_spec.rb +34 -0
  61. data/spec/operator/relational/group_spec.rb +54 -0
  62. data/spec/operator/relational/intersect_spec.rb +58 -0
  63. data/spec/operator/relational/join/hash_based_spec.rb +63 -0
  64. data/spec/operator/relational/minus_spec.rb +56 -0
  65. data/spec/operator/relational/nest_spec.rb +32 -0
  66. data/spec/operator/relational/project_spec.rb +65 -0
  67. data/spec/operator/relational/quota_spec.rb +44 -0
  68. data/spec/operator/relational/rename_spec.rb +32 -0
  69. data/spec/operator/relational/restrict_spec.rb +56 -0
  70. data/spec/operator/relational/summarize/sort_based_spec.rb +31 -0
  71. data/spec/operator/relational/summarize_spec.rb +41 -0
  72. data/spec/operator/relational/ungroup_spec.rb +35 -0
  73. data/spec/operator/relational/union_spec.rb +35 -0
  74. data/spec/operator/relational/unnest_spec.rb +32 -0
  75. data/spec/reader/alf_file_spec.rb +15 -0
  76. data/spec/reader/input.rb +2 -0
  77. data/spec/reader/rash_spec.rb +31 -0
  78. data/spec/reader_spec.rb +27 -0
  79. data/spec/renderer/text/cell_spec.rb +34 -0
  80. data/spec/renderer/text/row_spec.rb +30 -0
  81. data/spec/renderer/text/table_spec.rb +39 -0
  82. data/spec/renderer_spec.rb +42 -0
  83. data/spec/spec_helper.rb +26 -0
  84. data/spec/tools/ordering_key_spec.rb +81 -0
  85. data/spec/tools/projection_key_spec.rb +83 -0
  86. data/spec/tools/tools_spec.rb +25 -0
  87. data/spec/tools/tuple_handle_spec.rb +78 -0
  88. data/tasks/debug_mail.rake +78 -0
  89. data/tasks/debug_mail.txt +13 -0
  90. data/tasks/gem.rake +68 -0
  91. data/tasks/spec_test.rake +79 -0
  92. data/tasks/unit_test.rake +77 -0
  93. data/tasks/yard.rake +51 -0
  94. metadata +282 -0
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::NonRelational
4
+ describe Autonum do
5
+
6
+ let(:operator_class){ Autonum }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:input) {[
10
+ {:a => "a"},
11
+ {:a => "b"},
12
+ {:a => "a"},
13
+ ]}
14
+
15
+ subject{ operator.to_a }
16
+
17
+ describe "without providing an attribute name" do
18
+
19
+ let(:expected){[
20
+ {:a => "a", :autonum => 0},
21
+ {:a => "b", :autonum => 1},
22
+ {:a => "a", :autonum => 2},
23
+ ]}
24
+
25
+ describe "When factored with Lispy" do
26
+ let(:operator){ Lispy.autonum(input) }
27
+ it{ should == expected }
28
+ end
29
+
30
+ describe "When factored from commandline args" do
31
+ let(:operator){ Autonum.run([]) }
32
+ before{ operator.pipe(input) }
33
+ it{ should == expected }
34
+ end
35
+
36
+ end
37
+
38
+ describe "when providing an attribute name" do
39
+
40
+ let(:expected){[
41
+ {:a => "a", :unique => 0},
42
+ {:a => "b", :unique => 1},
43
+ {:a => "a", :unique => 2},
44
+ ]}
45
+
46
+ describe "When factored with Lispy" do
47
+ let(:operator){ Lispy.autonum(input, :unique) }
48
+ it{ should == expected }
49
+ end
50
+
51
+ describe "When factored from commandline args" do
52
+ let(:operator){ Autonum.run(["--", "unique"]) }
53
+ before{ operator.pipe(input) }
54
+ it{ should == expected }
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::NonRelational
4
+ describe Clip do
5
+
6
+ let(:operator_class){ Clip }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:input) {[
10
+ {:a => "a", :b => "b"},
11
+ ]}
12
+
13
+ subject{ operator.to_a }
14
+
15
+ describe "When used without --allbut" do
16
+ let(:expected){[{:a => "a"}]}
17
+
18
+ describe "when factored from commandline" do
19
+ let(:operator){ Clip.run(%w{-- a}) }
20
+ before{ operator.pipe(input) }
21
+ it { should == expected }
22
+ end
23
+
24
+ describe "when factored with Lispy" do
25
+ let(:operator){ Lispy.clip(input, [:a]) }
26
+ it { should == expected }
27
+ end
28
+
29
+ end
30
+
31
+ describe "When used with --allbut" do
32
+ let(:expected){[{:b => "b"}]}
33
+
34
+ describe "when factored with commandline args" do
35
+ let(:operator){ Clip.run(%w{--allbut -- a}) }
36
+ before{ operator.pipe(input) }
37
+ it { should == expected }
38
+ end
39
+
40
+ describe "when factored with Lispy" do
41
+ let(:operator){ Lispy.clip(input, [:a], true) }
42
+ it { should == expected }
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::NonRelational
4
+ describe Compact::BufferBased do
5
+
6
+ let(:input) {[
7
+ {:a => "via_method", :time => 1, :b => "b"},
8
+ {:a => "via_method", :time => 1, :b => "b"},
9
+ {:a => "via_method", :time => 2, :b => "b"},
10
+ {:a => "via_reader", :time => 3, :b => "b"},
11
+ {:a => "via_reader", :time => 3, :b => "b"},
12
+ ]}
13
+
14
+ let(:expected) {[
15
+ {:a => "via_method", :time => 1, :b => "b"},
16
+ {:a => "via_method", :time => 2, :b => "b"},
17
+ {:a => "via_reader", :time => 3, :b => "b"},
18
+ ]}
19
+
20
+ subject{ operator.to_a }
21
+
22
+ describe "when factored with commandline args" do
23
+ let(:operator){ Compact::BufferBased.new }
24
+ before{ operator.pipe(input) }
25
+ it { should == expected }
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::NonRelational
4
+ describe Compact::SortBased do
5
+
6
+ let(:input) {[
7
+ {:a => "via_method", :time => 1, :b => "b"},
8
+ {:a => "via_method", :time => 1, :b => "b"},
9
+ {:a => "via_method", :time => 2, :b => "b"},
10
+ {:a => "via_reader", :time => 3, :b => "b"},
11
+ {:a => "via_reader", :time => 3, :b => "b"},
12
+ ]}
13
+
14
+ let(:expected) {[
15
+ {:a => "via_method", :time => 1, :b => "b"},
16
+ {:a => "via_method", :time => 2, :b => "b"},
17
+ {:a => "via_reader", :time => 3, :b => "b"},
18
+ ]}
19
+
20
+ subject{ operator.to_a }
21
+
22
+ describe "when factored with commandline args" do
23
+ let(:operator){ Compact::SortBased.new }
24
+ before{ operator.pipe(input) }
25
+ it { should == expected }
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::NonRelational
4
+ describe Compact do
5
+
6
+ let(:operator_class){ Compact }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:input) {[
10
+ {:a => "via_method", :time => 1, :b => "b"},
11
+ {:a => "via_reader", :time => 3, :b => "b"},
12
+ {:a => "via_method", :time => 2, :b => "b"},
13
+ {:a => "via_reader", :time => 3, :b => "b"},
14
+ {:a => "via_method", :time => 1, :b => "b"},
15
+ ]}
16
+
17
+ let(:expected) {[
18
+ {:a => "via_method", :time => 1, :b => "b"},
19
+ {:a => "via_reader", :time => 3, :b => "b"},
20
+ {:a => "via_method", :time => 2, :b => "b"},
21
+ ]}
22
+
23
+ subject{ operator.to_a }
24
+
25
+ describe "when factored with commandline args" do
26
+ let(:operator){ Compact.run(%w{}) }
27
+ before{ operator.pipe(input) }
28
+ it { should == expected }
29
+ end
30
+
31
+ describe "when factored with Lispy" do
32
+ let(:operator){ Lispy.compact(input) }
33
+ it { should == expected }
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::NonRelational
4
+ describe Defaults do
5
+
6
+ let(:operator_class){ Defaults }
7
+ it_should_behave_like("An operator class")
8
+
9
+ subject{ operator.to_a }
10
+
11
+ describe "when used without --strict" do
12
+
13
+ let(:input) {[
14
+ {:a => nil, :b => "b"},
15
+ ]}
16
+
17
+ let(:expected) {[
18
+ {:a => 1, :b => "b", :c => "blue"},
19
+ ]}
20
+
21
+ describe "When factored with Lispy" do
22
+ let(:operator){ Lispy.defaults(input, :a => 1, :c => "blue") }
23
+ it{ should == expected }
24
+ end
25
+
26
+ describe "When factored from commandline args" do
27
+ let(:operator){ Defaults.run(%w{-- a 1 c 'blue'}) }
28
+ before{ operator.pipe(input) }
29
+ it{ should == expected }
30
+ end
31
+
32
+ end
33
+
34
+ describe "when used with --strict" do
35
+
36
+ let(:input) {[
37
+ {:a => 3, :b => "b", :c => "blue"},
38
+ {:a => nil, :b => "b", :c => "blue"},
39
+ ]}
40
+
41
+ let(:expected) {[
42
+ {:a => 3, :b => "b"},
43
+ {:a => 1, :b => "b"},
44
+ ]}
45
+
46
+ describe "When factored with Lispy" do
47
+ let(:operator){ Lispy.defaults(input, {:a => 1, :b => "b"}, true) }
48
+ it{ should == expected }
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::NonRelational
4
+ describe Sort do
5
+
6
+ let(:operator_class){ Sort }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:input) {[
10
+ {:first => "a", :second => 20, :third => true},
11
+ {:first => "b", :second => 10, :third => false},
12
+ {:first => "a", :second => 1, :third => true},
13
+ ]}
14
+
15
+ let(:expected){[
16
+ {:first => "a", :second => 1, :third => true},
17
+ {:first => "a", :second => 20, :third => true},
18
+ {:first => "b", :second => 10, :third => false},
19
+ ]}
20
+
21
+ subject{ operator.to_a }
22
+
23
+ describe "When factored with Lispy" do
24
+ let(:operator){ Lispy.sort(input, [[:first, :asc], [:second, :asc]]) }
25
+ it{ should == expected }
26
+ end
27
+
28
+ describe "When factored from commandline args" do
29
+ let(:operator){ Sort.run(["--", "first", "asc", "second", "asc"]) }
30
+ before{ operator.pipe(input) }
31
+ it{ should == expected }
32
+ end
33
+
34
+ describe "When used on two args" do
35
+ let(:operator){ Lispy.sort(input, [[:second, :asc], [:first, :asc]]) }
36
+ let(:expected){[
37
+ {:first => "a", :second => 1, :third => true},
38
+ {:first => "b", :second => 10, :third => false},
39
+ {:first => "a", :second => 20, :third => true},
40
+ ]}
41
+ it{ should == expected }
42
+ end
43
+
44
+ describe "When used on single arg" do
45
+ let(:operator){ Lispy.sort(input, [[:second, :asc]]) }
46
+ let(:expected){[
47
+ {:first => "a", :second => 1, :third => true},
48
+ {:first => "b", :second => 10, :third => false},
49
+ {:first => "a", :second => 20, :third => true},
50
+ ]}
51
+ it{ should == expected }
52
+ end
53
+
54
+ describe "When used with descending order" do
55
+ let(:operator){ Lispy.sort(input, [[:second, :desc]]) }
56
+ let(:expected){[
57
+ {:first => "a", :second => 20, :third => true},
58
+ {:first => "b", :second => 10, :third => false},
59
+ {:first => "a", :second => 1, :third => true},
60
+ ]}
61
+ it{ should == expected }
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::Relational
4
+ describe Extend do
5
+
6
+ let(:operator_class){ Extend }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:input) {[
10
+ {:tested => 1, :other => "b"},
11
+ {:tested => 30, :other => "a"},
12
+ ]}
13
+
14
+ let(:expected){[
15
+ {:tested => 1, :other => "b", :big => false},
16
+ {:tested => 30, :other => "a", :big => true},
17
+ ]}
18
+
19
+ subject{ operator.to_a }
20
+
21
+ describe "When factored with Lispy" do
22
+ let(:operator){ Lispy.extend(input, :big => lambda{ tested > 10 }) }
23
+ it{ should == expected }
24
+ end
25
+
26
+ describe "When factored from commandline args" do
27
+ let(:operator){ Extend.run(%w{-- big} + ["tested > 10"]) }
28
+ before{ operator.pipe(input) }
29
+ it{ should == expected }
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::Relational
4
+ describe Group do
5
+
6
+ let(:operator_class){ Group }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:input) {[
10
+ {:a => "via_method", :time => 1, :b => "b"},
11
+ {:a => "via_method", :time => 2, :b => "b"},
12
+ {:a => "via_reader", :time => 3, :b => "b"},
13
+ ]}
14
+
15
+ let(:expected) {[
16
+ {:a => "via_method", :as => [{:time => 1, :b => "b"}, {:time => 2, :b => "b"}]},
17
+ {:a => "via_reader", :as => [{:time => 3, :b => "b"}]},
18
+ ]}
19
+
20
+ subject{ operator.to_a.sort{|k1,k2| k1[:a] <=> k2[:a]} }
21
+
22
+ describe "without --allbut" do
23
+
24
+ describe "when factored with commandline args" do
25
+ let(:operator){ Group.run(["--", "time", "b", "as"]) }
26
+ before{ operator.pipe(input) }
27
+ it { should == expected }
28
+ end
29
+
30
+ describe "when factored with Lispy" do
31
+ let(:operator){ Lispy.group(input, [:time, :b], :as) }
32
+ it { should == expected }
33
+ end
34
+
35
+ end
36
+
37
+ describe "with --allbut" do
38
+
39
+ describe "when factored with commandline args" do
40
+ let(:operator){ Group.run(["--","a", "as"]) }
41
+ before{ operator.allbut = true; operator.pipe(input) }
42
+ it { should == expected }
43
+ end
44
+
45
+ describe "when factored with Lispy" do
46
+ let(:operator){ Lispy.group(input, [:a], :as, true) }
47
+ it { should == expected }
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::Relational
4
+ describe Intersect do
5
+
6
+ let(:operator_class){ Intersect }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:left) {[
10
+ {:sid => 'S1', :city => 'London'},
11
+ {:sid => 'S2', :city => 'Paris'},
12
+ {:sid => 'S3', :city => 'Paris'}
13
+ ]}
14
+
15
+ let(:right) {[
16
+ {:sid => 'S2', :city => 'Paris'},
17
+ {:sid => 'S1', :city => 'London'},
18
+ ]}
19
+
20
+ let(:disjoint) {[
21
+ {:sid => 'S4', :city => 'Oslo'},
22
+ {:sid => 'S5', :city => 'Bruxelles'},
23
+ ]}
24
+
25
+ let(:operator){ Intersect.run([]) }
26
+ subject{ operator.to_a }
27
+
28
+ describe "when applied on the same operand twice" do
29
+ before{ operator.datasets = [left, left] }
30
+ it { should == left }
31
+ end
32
+
33
+ describe "when applied on operands sharing tuples" do
34
+ before{ operator.datasets = [left, right] }
35
+ let(:expected) {[
36
+ {:sid => 'S1', :city => 'London'},
37
+ {:sid => 'S2', :city => 'Paris'},
38
+ ]}
39
+ it { should == expected }
40
+ end
41
+
42
+ describe "when applied on disjoint operands" do
43
+ before{ operator.datasets = [left, disjoint] }
44
+ it { should be_empty }
45
+ end
46
+
47
+ describe "when factored with Lispy" do
48
+ let(:operator){ Lispy.intersect(left, right) }
49
+ let(:expected) {[
50
+ {:sid => 'S1', :city => 'London'},
51
+ {:sid => 'S2', :city => 'Paris'},
52
+ ]}
53
+ it { should == expected }
54
+ end
55
+
56
+ end
57
+ end
58
+ end