alf 0.9.3 → 0.10.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 (270) hide show
  1. data/CHANGELOG.md +255 -129
  2. data/Gemfile +31 -1
  3. data/Gemfile.lock +17 -20
  4. data/LICENCE.md +1 -1
  5. data/Manifest.txt +2 -0
  6. data/README.md +37 -43
  7. data/TODO.md +1 -1
  8. data/alf.gemspec +10 -7
  9. data/alf.noespec +24 -13
  10. data/bin/alf +2 -2
  11. data/doc/commands/exec.md +16 -0
  12. data/doc/commands/help.md +11 -0
  13. data/doc/commands/main.md +33 -0
  14. data/doc/commands/show.md +19 -0
  15. data/doc/operators/non_relational/autonum.md +23 -0
  16. data/doc/operators/non_relational/clip.md +31 -0
  17. data/doc/operators/non_relational/coerce.md +15 -0
  18. data/doc/operators/non_relational/compact.md +20 -0
  19. data/doc/operators/non_relational/defaults.md +32 -0
  20. data/doc/operators/non_relational/generator.md +20 -0
  21. data/doc/operators/non_relational/sort.md +24 -0
  22. data/doc/operators/relational/extend.md +18 -0
  23. data/doc/operators/relational/group.md +27 -0
  24. data/doc/operators/relational/intersect.md +13 -0
  25. data/doc/operators/relational/join.md +27 -0
  26. data/doc/operators/relational/matching.md +20 -0
  27. data/doc/operators/relational/minus.md +12 -0
  28. data/doc/operators/relational/not-matching.md +20 -0
  29. data/doc/operators/relational/project.md +28 -0
  30. data/doc/operators/relational/quota.md +21 -0
  31. data/doc/operators/relational/rank.md +27 -0
  32. data/doc/operators/relational/rename.md +17 -0
  33. data/doc/operators/relational/restrict.md +25 -0
  34. data/doc/operators/relational/summarize.md +25 -0
  35. data/doc/operators/relational/ungroup.md +20 -0
  36. data/doc/operators/relational/union.md +14 -0
  37. data/doc/operators/relational/unwrap.md +20 -0
  38. data/doc/operators/relational/wrap.md +24 -0
  39. data/examples/csv/suppliers.csv +6 -0
  40. data/examples/logs/access.log +1000 -0
  41. data/examples/logs/combined.alf +2 -0
  42. data/examples/logs/hits.alf +14 -0
  43. data/examples/logs/not_found.alf +7 -0
  44. data/examples/logs/robots-cheating.alf +11 -0
  45. data/examples/logs/robots.alf +8 -0
  46. data/examples/northwind/customers.csv +92 -0
  47. data/examples/northwind/northwind.db +0 -0
  48. data/examples/northwind/orders.csv +831 -0
  49. data/examples/operators/clip.alf +1 -1
  50. data/examples/operators/database.alf +5 -6
  51. data/examples/operators/defaults.alf +1 -1
  52. data/examples/operators/group.alf +1 -1
  53. data/examples/operators/project.alf +2 -1
  54. data/examples/operators/pseudo-with.alf +2 -2
  55. data/examples/operators/quota.alf +2 -2
  56. data/examples/operators/summarize.alf +2 -2
  57. data/lib/alf/aggregator/aggregators.rb +77 -0
  58. data/lib/alf/aggregator/base.rb +95 -0
  59. data/lib/alf/aggregator/class_methods.rb +57 -0
  60. data/lib/alf/buffer/sorted.rb +48 -0
  61. data/lib/alf/command/class_methods.rb +27 -0
  62. data/lib/alf/command/doc_manager.rb +72 -0
  63. data/lib/alf/command/exec.rb +12 -0
  64. data/lib/alf/command/help.rb +31 -0
  65. data/lib/alf/command/main.rb +146 -0
  66. data/lib/alf/command/show.rb +33 -0
  67. data/lib/alf/environment/base.rb +37 -0
  68. data/lib/alf/environment/class_methods.rb +93 -0
  69. data/lib/alf/environment/explicit.rb +38 -0
  70. data/lib/alf/environment/folder.rb +62 -0
  71. data/lib/alf/extra/csv.rb +104 -0
  72. data/lib/alf/extra/logs.rb +100 -0
  73. data/lib/alf/extra/sequel.rb +77 -0
  74. data/lib/alf/{yaml.rb → extra/yaml.rb} +0 -0
  75. data/lib/alf/extra.rb +5 -0
  76. data/lib/alf/iterator/base.rb +38 -0
  77. data/lib/alf/iterator/class_methods.rb +22 -0
  78. data/lib/alf/iterator/proxy.rb +33 -0
  79. data/lib/alf/lispy/instance_methods.rb +157 -0
  80. data/lib/alf/operator/base.rb +74 -0
  81. data/lib/alf/operator/binary.rb +32 -0
  82. data/lib/alf/operator/cesure.rb +45 -0
  83. data/lib/alf/operator/class_methods.rb +132 -0
  84. data/lib/alf/operator/experimental.rb +9 -0
  85. data/lib/alf/operator/non_relational/autonum.rb +24 -0
  86. data/lib/alf/operator/non_relational/clip.rb +20 -0
  87. data/lib/alf/operator/non_relational/coerce.rb +21 -0
  88. data/lib/alf/operator/non_relational/compact.rb +62 -0
  89. data/lib/alf/operator/non_relational/defaults.rb +25 -0
  90. data/lib/alf/operator/non_relational/generator.rb +38 -0
  91. data/lib/alf/operator/non_relational/sort.rb +23 -0
  92. data/lib/alf/operator/nullary.rb +20 -0
  93. data/lib/alf/operator/relational/extend.rb +24 -0
  94. data/lib/alf/operator/relational/group.rb +32 -0
  95. data/lib/alf/operator/relational/intersect.rb +37 -0
  96. data/lib/alf/operator/relational/join.rb +106 -0
  97. data/lib/alf/operator/relational/matching.rb +45 -0
  98. data/lib/alf/operator/relational/minus.rb +37 -0
  99. data/lib/alf/operator/relational/not_matching.rb +45 -0
  100. data/lib/alf/operator/relational/project.rb +22 -0
  101. data/lib/alf/operator/relational/quota.rb +51 -0
  102. data/lib/alf/operator/relational/rank.rb +55 -0
  103. data/lib/alf/operator/relational/rename.rb +19 -0
  104. data/lib/alf/operator/relational/restrict.rb +20 -0
  105. data/lib/alf/operator/relational/summarize.rb +83 -0
  106. data/lib/alf/operator/relational/ungroup.rb +25 -0
  107. data/lib/alf/operator/relational/union.rb +32 -0
  108. data/lib/alf/operator/relational/unwrap.rb +21 -0
  109. data/lib/alf/operator/relational/wrap.rb +22 -0
  110. data/lib/alf/operator/shortcut.rb +53 -0
  111. data/lib/alf/operator/signature.rb +262 -0
  112. data/lib/alf/operator/transform.rb +27 -0
  113. data/lib/alf/operator/unary.rb +38 -0
  114. data/lib/alf/reader/alf_file.rb +24 -0
  115. data/lib/alf/reader/base.rb +119 -0
  116. data/lib/alf/reader/class_methods.rb +82 -0
  117. data/lib/alf/reader/rash.rb +28 -0
  118. data/lib/alf/relation/class_methods.rb +37 -0
  119. data/lib/alf/relation/instance_methods.rb +127 -0
  120. data/lib/alf/renderer/base.rb +72 -0
  121. data/lib/alf/renderer/class_methods.rb +58 -0
  122. data/lib/alf/renderer/rash.rb +19 -0
  123. data/lib/alf/{text.rb → renderer/text.rb} +1 -1
  124. data/lib/alf/tools/coerce.rb +14 -0
  125. data/lib/alf/tools/miscellaneous.rb +77 -0
  126. data/lib/alf/tools/to_lispy.rb +99 -0
  127. data/lib/alf/tools/to_ruby_literal.rb +14 -0
  128. data/lib/alf/tools/tuple_handle.rb +50 -0
  129. data/lib/alf/types/attr_list.rb +56 -0
  130. data/lib/alf/types/attr_name.rb +28 -0
  131. data/lib/alf/types/boolean.rb +12 -0
  132. data/lib/alf/types/heading.rb +96 -0
  133. data/lib/alf/types/ordering.rb +93 -0
  134. data/lib/alf/types/renaming.rb +57 -0
  135. data/lib/alf/types/summarization.rb +76 -0
  136. data/lib/alf/types/tuple_computation.rb +61 -0
  137. data/lib/alf/types/tuple_expression.rb +61 -0
  138. data/lib/alf/types/tuple_predicate.rb +49 -0
  139. data/lib/alf/version.rb +2 -2
  140. data/lib/alf.rb +193 -3714
  141. data/spec/integration/__database__/group.alf +1 -1
  142. data/spec/integration/__database__/suppliers_csv.csv +6 -0
  143. data/spec/integration/command/alf/alf.db +0 -0
  144. data/spec/integration/command/alf/alf_env_sqlite.cmd +1 -0
  145. data/spec/integration/command/alf/alf_env_sqlite.stdout +9 -0
  146. data/spec/integration/command/alf/alf_help.cmd +1 -0
  147. data/spec/integration/command/alf/alf_help.stdout +67 -0
  148. data/spec/integration/command/autonum/autonum_0.cmd +1 -1
  149. data/spec/integration/command/coerce/coerce_1.cmd +1 -0
  150. data/spec/integration/command/coerce/coerce_1.stdout +5 -0
  151. data/spec/integration/command/defaults/defaults_0.cmd +1 -1
  152. data/spec/integration/command/defaults/defaults_0.stdout +9 -9
  153. data/spec/integration/command/defaults/defaults_2.cmd +1 -0
  154. data/spec/integration/command/defaults/defaults_2.stdout +9 -0
  155. data/spec/integration/command/generator/generator_1.cmd +1 -0
  156. data/spec/integration/command/generator/generator_1.stdout +10 -0
  157. data/spec/integration/command/generator/generator_2.cmd +1 -0
  158. data/spec/integration/command/generator/generator_2.stdout +5 -0
  159. data/spec/integration/command/generator/generator_3.cmd +1 -0
  160. data/spec/integration/command/generator/generator_3.stdout +5 -0
  161. data/spec/integration/command/group/group_0.cmd +1 -1
  162. data/spec/integration/command/group/group_1.cmd +1 -1
  163. data/spec/integration/command/help/help_1.cmd +1 -0
  164. data/spec/integration/command/help/help_1.stdout +22 -0
  165. data/spec/integration/command/quota/quota_0.cmd +1 -1
  166. data/spec/integration/command/rank/rank_1.cmd +1 -1
  167. data/spec/integration/command/rank/rank_1.stdout +10 -10
  168. data/spec/integration/command/rank/rank_2.cmd +1 -1
  169. data/spec/integration/command/rank/rank_2.stdout +10 -10
  170. data/spec/integration/command/rank/rank_3.cmd +1 -1
  171. data/spec/integration/command/rank/rank_3.stdout +10 -10
  172. data/spec/integration/command/rank/rank_4.cmd +1 -1
  173. data/spec/integration/command/rank/rank_5.cmd +1 -1
  174. data/spec/integration/command/show/show_csv.cmd +1 -0
  175. data/spec/integration/command/show/show_csv.stdout +6 -0
  176. data/spec/integration/command/show/show_rash_2.cmd +1 -1
  177. data/spec/integration/command/show/show_rash_2.stdout +5 -5
  178. data/spec/integration/command/sort/sort_0.cmd +1 -1
  179. data/spec/integration/command/sort/sort_1.cmd +1 -1
  180. data/spec/integration/command/sort/sort_1.stdout +2 -2
  181. data/spec/integration/command/sort/sort_2.cmd +1 -0
  182. data/spec/integration/command/sort/sort_2.stdout +9 -0
  183. data/spec/integration/command/sort/sort_3.cmd +1 -0
  184. data/spec/integration/command/sort/sort_3.stdout +9 -0
  185. data/spec/integration/command/summarize/summarize_0.cmd +1 -1
  186. data/spec/integration/command/ungroup/ungroup_0.cmd +1 -1
  187. data/spec/integration/command/wrap/wrap_0.cmd +1 -1
  188. data/spec/integration/semantics/test_project.alf +5 -6
  189. data/spec/integration/semantics/test_rank.alf +16 -16
  190. data/spec/integration/test_command.rb +17 -6
  191. data/spec/integration/test_examples.rb +1 -1
  192. data/spec/regression/logs/apache_combined.log +5 -0
  193. data/spec/regression/logs/test_path_attribute.rb +25 -0
  194. data/spec/regression/relation/test_relation_allbut_all.rb +14 -0
  195. data/spec/shared/an_operator_class.rb +10 -5
  196. data/spec/spec_helper.rb +1 -7
  197. data/spec/unit/assumptions/test_set.rb +64 -0
  198. data/spec/unit/command/doc_manager/dynamic.md +1 -0
  199. data/spec/unit/command/doc_manager/example.md +1 -0
  200. data/spec/unit/command/doc_manager/example_1.txt +11 -0
  201. data/spec/unit/command/doc_manager/static.md +1 -0
  202. data/spec/unit/command/doc_manager/test_call.rb +49 -0
  203. data/spec/unit/csv/input.csv +3 -0
  204. data/spec/unit/csv/test_reader.rb +66 -0
  205. data/spec/unit/csv/test_renderer.rb +73 -0
  206. data/spec/unit/lispy/test_relation.rb +37 -0
  207. data/spec/unit/lispy/test_run.rb +40 -0
  208. data/spec/unit/lispy/test_tuple.rb +36 -0
  209. data/spec/unit/logs/apache_combined.log +5 -0
  210. data/spec/unit/logs/postgresql.log +29 -0
  211. data/spec/unit/logs/test_reader.rb +56 -0
  212. data/spec/unit/operator/non_relational/compact/{buffer_based.rb → test_buffer_based.rb} +0 -0
  213. data/spec/unit/operator/non_relational/test_clip.rb +1 -1
  214. data/spec/unit/operator/non_relational/test_coerce.rb +35 -0
  215. data/spec/unit/operator/non_relational/test_defaults.rb +15 -2
  216. data/spec/unit/operator/non_relational/test_generator.rb +78 -0
  217. data/spec/unit/operator/relational/join/test_hash_based.rb +4 -4
  218. data/spec/unit/operator/relational/matching/test_hash_based.rb +6 -6
  219. data/spec/unit/operator/relational/not_matching/test_hash_based.rb +4 -4
  220. data/spec/unit/operator/relational/summarize/test_hash_based.rb +10 -6
  221. data/spec/unit/operator/relational/summarize/test_sort_based.rb +18 -7
  222. data/spec/unit/operator/relational/test_group.rb +8 -8
  223. data/spec/unit/operator/relational/test_intersect.rb +3 -3
  224. data/spec/unit/operator/relational/test_minus.rb +3 -3
  225. data/spec/unit/operator/relational/test_project.rb +12 -2
  226. data/spec/unit/operator/relational/test_quota.rb +5 -6
  227. data/spec/unit/operator/relational/test_summarize.rb +9 -11
  228. data/spec/unit/operator/relational/test_union.rb +1 -1
  229. data/spec/unit/operator/relational/test_wrap.rb +1 -1
  230. data/spec/unit/operator/signature/test_collect_on.rb +45 -0
  231. data/spec/unit/operator/signature/test_initialize.rb +17 -0
  232. data/spec/unit/operator/signature/test_install.rb +56 -0
  233. data/spec/unit/operator/signature/test_option_parser.rb +36 -0
  234. data/spec/unit/operator/signature/test_parse_args.rb +60 -0
  235. data/spec/unit/operator/signature/test_parse_argv.rb +87 -0
  236. data/spec/unit/operator/signature/test_to_lispy.rb +102 -0
  237. data/spec/unit/operator/signature/test_to_shell.rb +103 -0
  238. data/spec/unit/operator/test_non_relational.rb +3 -1
  239. data/spec/unit/relation/test_relops.rb +20 -15
  240. data/spec/unit/sequel/alf.db +0 -0
  241. data/spec/unit/sequel/test_environment.rb +54 -0
  242. data/spec/unit/test_aggregator.rb +32 -22
  243. data/spec/unit/test_environment.rb +5 -0
  244. data/spec/unit/test_lispy.rb +4 -0
  245. data/spec/unit/test_relation.rb +5 -0
  246. data/spec/unit/text/test_cell.rb +6 -6
  247. data/spec/unit/text/test_row.rb +3 -3
  248. data/spec/unit/text/test_table.rb +6 -6
  249. data/spec/unit/tools/test_coalesce.rb +15 -0
  250. data/spec/unit/tools/test_coerce.rb +10 -0
  251. data/spec/unit/tools/test_to_lispy.rb +138 -0
  252. data/spec/unit/tools/test_to_ruby_literal.rb +10 -0
  253. data/spec/unit/tools/test_tuple_handle.rb +1 -59
  254. data/spec/unit/types/test_attr_list.rb +106 -0
  255. data/spec/unit/types/test_attr_name.rb +52 -0
  256. data/spec/unit/{test_heading.rb → types/test_heading.rb} +10 -0
  257. data/spec/unit/types/test_ordering.rb +127 -0
  258. data/spec/unit/types/test_renaming.rb +55 -0
  259. data/spec/unit/types/test_summarization.rb +63 -0
  260. data/spec/unit/types/test_tuple_computation.rb +60 -0
  261. data/spec/unit/types/test_tuple_expression.rb +64 -0
  262. data/spec/unit/types/test_tuple_predicate.rb +79 -0
  263. data/tasks/debug_mail.rake +1 -1
  264. data/tasks/debug_mail.txt +5 -0
  265. data/tasks/gh-pages.rake +63 -0
  266. metadata +325 -52
  267. data/spec/unit/operator/test_command_methods.rb +0 -38
  268. data/spec/unit/tools/test_ordering_key.rb +0 -94
  269. data/spec/unit/tools/test_parse_commandline_args.rb +0 -47
  270. data/spec/unit/tools/test_projection_key.rb +0 -83
data/spec/spec_helper.rb CHANGED
@@ -4,12 +4,6 @@ require "rspec"
4
4
 
5
5
  Alf::Lispy.extend(Alf::Lispy)
6
6
 
7
- def rel(*args)
8
- Alf::Relation.coerce(args)
9
- end
10
- def tuple(h)
11
- h
12
- end
13
7
  def _(path, file)
14
8
  File.expand_path("../#{path}", file)
15
9
  end
@@ -19,4 +13,4 @@ def wlang(str, binding)
19
13
  end
20
14
 
21
15
  require 'shared/an_operator_class'
22
- require 'shared/a_value'
16
+ require 'shared/a_value'
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'set'
3
+ describe Set do
4
+
5
+ specify "empty sets should be equal" do
6
+ Set.new([]).should eq(Set.new([]))
7
+ Set.new([]).should eql(Set.new([]))
8
+ end
9
+
10
+ describe "on DEE-like sets" do
11
+ let(:dee){ Set.new([{}]) }
12
+
13
+ specify "DEE sets should be equal" do
14
+ Set.new([{}]).should eq(dee)
15
+ Set.new([{}]).should eql(dee)
16
+ end
17
+
18
+ specify "DEE-like sets should be equal (1)" do
19
+ arr = [{}]
20
+ Set.new(arr).should eq(dee)
21
+ Set.new(arr).should eql(dee)
22
+ end
23
+
24
+ specify "DEE-like sets should be equal (2)" do
25
+ arr = [{}]
26
+ Set.new(arr.to_a).should eq(dee)
27
+ Set.new(arr.to_a).should eql(dee)
28
+ end
29
+
30
+ specify "DEE-like sets should be equal (3)" do
31
+ arr = [{}]
32
+ arr.to_set.should eq(dee)
33
+ arr.to_set.should eql(dee)
34
+ end
35
+
36
+ specify "DEE-like sets should be equal (4)" do
37
+ arr = [{}]
38
+ arr.to_set.should eq(dee)
39
+ arr.to_set.should eql(dee)
40
+ end
41
+
42
+ specify "DEE-like sets should be equal (5)" do
43
+ arr = Object.new.extend(Enumerable)
44
+ def arr.each
45
+ yield({})
46
+ end
47
+ arr.to_set.should eq(dee)
48
+ arr.to_set.should eql(dee)
49
+ end
50
+
51
+ specify "DEE-like sets should be equal (5)" do
52
+ arr = Object.new.extend(Enumerable)
53
+ def arr.each
54
+ tuple = {:sid => "1"}
55
+ tuple.delete(:sid)
56
+ yield(tuple)
57
+ end
58
+ arr.to_set.should eq(dee)
59
+ arr.to_set.should eql(dee)
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1 @@
1
+ #(command_name)
@@ -0,0 +1 @@
1
+ !(alf autonum suppliers -- unique_id)
@@ -0,0 +1,11 @@
1
+ $ alf autonum suppliers -- unique_id
2
+
3
+ +------+-------+---------+--------+------------+
4
+ | :sid | :name | :status | :city | :unique_id |
5
+ +------+-------+---------+--------+------------+
6
+ | S1 | Smith | 20 | London | 0 |
7
+ | S2 | Jones | 10 | Paris | 1 |
8
+ | S3 | Blake | 30 | Paris | 2 |
9
+ | S4 | Clark | 20 | London | 3 |
10
+ | S5 | Adams | 30 | Athens | 4 |
11
+ +------+-------+---------+--------+------------+
@@ -0,0 +1 @@
1
+ Hello
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Command
4
+ describe DocManager, ".call" do
5
+
6
+ let(:dm){ @dm ||= DocManager.new }
7
+ let(:cmd){ Alf::Command::Show }
8
+ subject{
9
+ dm.call(cmd, opts)
10
+ }
11
+
12
+ describe "without options" do
13
+ let(:opts){ {} }
14
+
15
+ describe "on a static file" do
16
+ before{
17
+ def dm.find_file(cmd);
18
+ File.expand_path('../static.md', __FILE__)
19
+ end
20
+ }
21
+ it { should eq("Hello\n") }
22
+ end
23
+
24
+ describe "on a dynamic file" do
25
+ before{
26
+ def dm.find_file(cmd);
27
+ File.expand_path('../dynamic.md', __FILE__)
28
+ end
29
+ }
30
+ it { should eq("show\n") }
31
+ end
32
+
33
+ unless RUBY_VERSION < "1.9"
34
+ describe "on an example file" do
35
+ before{
36
+ def dm.find_file(cmd);
37
+ File.expand_path('../example.md', __FILE__)
38
+ end
39
+ }
40
+ it { should eq(File.read(File.expand_path('../example_1.txt', __FILE__))) }
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ size
2
+ 10
3
+ 20
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module CSV
4
+ describe Reader do
5
+
6
+ describe "without options" do
7
+ let(:input){
8
+ StringIO.new << "size\n10\n20\n"
9
+ }
10
+ let(:expected){
11
+ [{:size => "10"}, {:size => "20"}]
12
+ }
13
+ subject{ reader.to_a }
14
+
15
+ describe "when called on a reader directly" do
16
+ let(:reader){
17
+ ::Alf::CSV::Reader.new(input)
18
+ }
19
+ it{ should eq(expected) }
20
+ end
21
+
22
+ describe "when called through registered one" do
23
+ let(:reader){
24
+ ::Alf::Reader.reader(_('input.csv', __FILE__))
25
+ }
26
+ it{ should eq(expected) }
27
+ end
28
+
29
+ describe "when called through factory method" do
30
+ let(:reader){
31
+ ::Alf::Reader.csv(input)
32
+ }
33
+ it{ should eq(expected) }
34
+ end
35
+ end
36
+
37
+ describe "with options" do
38
+ let(:input){
39
+ StringIO.new << "size;name\n10;blambeau\n20;mmathieu\n"
40
+ }
41
+ let(:options){
42
+ {:col_sep => ";"}
43
+ }
44
+ let(:expected){
45
+ [{:size => "10", :name => 'blambeau'}, {:size => "20", :name => 'mmathieu'}]
46
+ }
47
+ subject{ reader.to_a }
48
+
49
+ describe "when called on a reader directly" do
50
+ let(:reader){
51
+ ::Alf::CSV::Reader.new(input, options)
52
+ }
53
+ it{ should eq(expected) }
54
+ end
55
+
56
+ describe "when called through factory method" do
57
+ let(:reader){
58
+ ::Alf::Reader.csv(input, options)
59
+ }
60
+ it{ should eq(expected) }
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module CSV
4
+ describe Renderer do
5
+
6
+ describe "without options" do
7
+ let(:input){
8
+ [{:size => 10}, {:size => 20}]
9
+ }
10
+ let(:expected){
11
+ "size\n10\n20\n"
12
+ }
13
+ subject{ renderer.execute(StringIO.new).string }
14
+
15
+ describe "when called on a renderer directly" do
16
+ let(:renderer){
17
+ ::Alf::CSV::Renderer.new(input)
18
+ }
19
+ it{ should eq(expected) }
20
+ end
21
+
22
+ describe "when called through registererd one" do
23
+ let(:renderer){
24
+ ::Alf::Renderer.renderer(:csv, input)
25
+ }
26
+ it{ should eq(expected) }
27
+ end
28
+
29
+ describe "when called through factory method" do
30
+ let(:renderer){
31
+ ::Alf::Renderer.csv(input)
32
+ }
33
+ it{ should eq(expected) }
34
+ end
35
+ end
36
+
37
+ describe "with options" do
38
+ let(:input){
39
+ [{:size => 10, :name => "blambeau"}, {:size => 20, :name => "mmathieu"}]
40
+ }
41
+ let(:expected){
42
+ "size;name\n10;blambeau\n20;mmathieu\n"
43
+ }
44
+ let(:options){
45
+ {:col_sep => ";"}
46
+ }
47
+ subject{ renderer.execute(StringIO.new).string }
48
+
49
+ describe "when called on a renderer directly" do
50
+ let(:renderer){
51
+ ::Alf::CSV::Renderer.new(input, options)
52
+ }
53
+ it{ should eq(expected) }
54
+ end
55
+
56
+ describe "when called through registererd one" do
57
+ let(:renderer){
58
+ ::Alf::Renderer.renderer(:csv, input, options)
59
+ }
60
+ it{ should eq(expected) }
61
+ end
62
+
63
+ describe "when called through factory method" do
64
+ let(:renderer){
65
+ ::Alf::Renderer.csv(input, options)
66
+ }
67
+ it{ should eq(expected) }
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Lispy, "Relation(...)" do
4
+ let(:lispy){ Alf.lispy }
5
+ subject{ lispy.Relation(*args) }
6
+
7
+ describe 'on a single tuple' do
8
+ let(:args){ [{:name => "Alf"}] }
9
+ it{ should eq(Relation[*args]) }
10
+ end
11
+
12
+ describe 'on two tuples' do
13
+ let(:args){ [{:name => "Alf"}, {:name => "Lispy"}] }
14
+ it{ should eq(Relation[*args]) }
15
+ end
16
+
17
+ describe 'on a Symbol' do
18
+ let(:args){ [:suppliers] }
19
+ specify{
20
+ subject.should eq(lispy.environment.dataset(:suppliers).to_rel)
21
+ }
22
+ end
23
+
24
+ describe "on the documentation example" do
25
+ specify {
26
+ lispy.evaluate{
27
+ Relation(
28
+ Tuple(:pid => 'P1', :name => 'Nut', :color => 'red', :heavy => true ),
29
+ Tuple(:pid => 'P2', :name => 'Bolt', :color => 'green', :heavy => false),
30
+ Tuple(:pid => 'P3', :name => 'Screw', :color => 'blue', :heavy => false)
31
+ )
32
+ }.should be_a(Relation)
33
+ }
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Lispy, ".run" do
4
+
5
+ let(:cities){Relation[
6
+ {:city => "London"},
7
+ {:city => "Paris"},
8
+ {:city => "Athens"}
9
+ ]}
10
+
11
+ let(:lispy){ Alf.lispy(Environment.examples) }
12
+ subject{ lispy.run(args).to_rel }
13
+
14
+ describe "without any pipe, on a String" do
15
+ let(:args){ "project suppliers -- city" }
16
+ it{ should eq(cities) }
17
+ end
18
+
19
+ describe "without any pipe, on an Array" do
20
+ let(:args){ %w{project suppliers -- city} }
21
+ it{ should eq(cities) }
22
+ end
23
+
24
+ describe "with alf explicitely" do
25
+ let(:args){ %w{alf project suppliers -- city} }
26
+ it{ should eq(cities) }
27
+ end
28
+
29
+ describe "with piped commands" do
30
+ let(:args){ %w{alf project suppliers -- city | alf extend -- upcased city.upcase} }
31
+ it{ should eq(cities.extend(:upcased => lambda{ city.upcase })) }
32
+ end
33
+
34
+ describe "with piped commands and a dyadic op" do
35
+ let(:args){ %w{alf project suppliers -- city | alf matching suppliers} }
36
+ it{ should eq(cities) }
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ describe Lispy, "Tuple(...)" do
4
+ let(:lispy){ Alf.lispy }
5
+ subject{ lispy.Tuple(h) }
6
+
7
+ describe 'on an empty tuple' do
8
+ let(:h){ {} }
9
+ it{ should eq({}) }
10
+ end
11
+
12
+ describe 'on an valid tuple' do
13
+ let(:h){ {:name => "Alf"} }
14
+ it{ should eq({:name => "Alf"}) }
15
+ end
16
+
17
+ describe 'on an invalid tuple because of keys' do
18
+ let(:h){ {12 => "Alf"} }
19
+ specify{ lambda{subject}.should raise_error(ArgumentError) }
20
+ end
21
+
22
+ describe 'on an invalid tuple because of values' do
23
+ let(:h){ {:name => nil} }
24
+ specify{ lambda{subject}.should raise_error(ArgumentError) }
25
+ end
26
+
27
+ describe "on the documentation example" do
28
+ specify{
29
+ lispy.evaluate{
30
+ Tuple(:pid => 'P1', :name => 'Nut', :color => 'red', :heavy => true)
31
+ }.should eq(:pid => 'P1', :name => 'Nut', :color => 'red', :heavy => true)
32
+ }
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,5 @@
1
+ 125.76.230.10 - - [02/Sep/2009:03:33:46 +0200] "GET /cart/install.txt HTTP/1.1" 404 214 "-" "Toata dragostea mea pentru diavola"
2
+ 125.76.230.10 - - [02/Sep/2009:03:33:47 +0200] "GET /store/install.txt HTTP/1.1" 404 215 "-" "Toata dragostea mea pentru diavola"
3
+ 10.0.1.1 - - [02/Sep/2009:05:08:33 +0200] "GET / HTTP/1.1" 200 30 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-us) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9"
4
+ 10.0.1.1 - - [02/Sep/2009:06:41:51 +0200] "GET / HTTP/1.1" 200 30 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-us) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9"
5
+ 69.41.0.45 - - [02/Sep/2009:12:02:40 +0200] "GET //phpMyAdmin/ HTTP/1.1" 404 209 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)"
@@ -0,0 +1,29 @@
1
+ 2010-10-10 13:50:24 GMT [38626]: [1-1] LOG: 00000: database system was shut down at 2010-10-10 13:49:33 GMT
2
+ 2010-10-10 13:50:24 GMT [38626]: [2-1] LOCATION: StartupXLOG, xlog.c:4816
3
+ 2010-10-10 13:50:24 GMT [38624]: [1-1] LOG: 00000: database system is ready to accept connections
4
+ 2010-10-10 13:50:24 GMT [38624]: [2-1] LOCATION: reaper, postmaster.c:2156
5
+ 2010-10-10 13:50:24 GMT [38629]: [1-1] LOG: 00000: autovacuum launcher started
6
+ 2010-10-10 13:50:24 GMT [38629]: [2-1] LOCATION: AutoVacLauncherMain, autovacuum.c:520
7
+ 2010-10-10 13:52:04 GMT [38747]: [1-1] LOG: 00000: connection received: host=127.0.0.1 port=60020
8
+ 2010-10-10 13:52:04 GMT [38747]: [2-1] LOCATION: BackendInitialize, postmaster.c:3027
9
+ 2010-10-10 13:52:04 GMT [38747]: [3-1] LOG: 00000: connection authorized: user=root database=demonstration
10
+ 2010-10-10 13:52:04 GMT [38747]: [4-1] LOCATION: BackendInitialize, postmaster.c:3097
11
+ 2010-10-10 13:52:04 GMT [38747]: [5-1] LOG: 00000: duration: 0.329 ms statement: SHOW clients
12
+ 2010-10-10 13:52:05 GMT [38747]: [21-1] LOG: 00000: duration: 0.973 ms statement: SELECT tablename
13
+ FROM pg_tables
14
+ WHERE schemaname IN (E'"$user"',E'public')
15
+ 2010-10-10 13:52:07 GMT [38747]: [33-1] LOG: 00000: duration: 0.710 ms statement: SELECT * FROM "delayed_jobs"
16
+ 2010-10-10 13:52:08 GMT [38747]: [33-1] LOG: 00000: duration: 0.710 ms statement: SELECT * FROM "delayed_jobs"
17
+ 2010-10-10 15:00:02 GMT [38747]: [1667-1] LOG: 00000: duration: 0.024 ms statement: BEGIN
18
+ 2010-10-10 15:00:02 GMT [38747]: [1668-1] LOCATION: exec_simple_query, postgres.c:1081
19
+ 2010-10-10 15:00:02 GMT [38747]: [1669-1] LOG: 00000: duration: 0.195 ms statement: INSERT INTO "delayed_jobs" ("failed_at", "locked_by", "created_at", "handler", "updated_at", "priority", "run_at", "attempts", "locked_at", "last_error") VALUES(NULL, NULL, '2010-10-10 15:00:02.159884', E'--- !ruby/object:RuntheChooChootrain {}
20
+
21
+ ', '2010-10-10 15:00:02.159884', 0, '2010-10-10 16:00:00.000000', 0, NULL, NULL) RETURNING "id"
22
+ 2010-10-10 15:00:02 GMT [38747]: [1670-1] LOCATION: exec_simple_query, postgres.c:1081
23
+ 2010-10-10 15:00:02 GMT [38747]: [1671-1] LOG: 00000: duration: 0.065 ms statement: COMMIT
24
+ 2010-10-10 15:00:02 GMT [38747]: [1672-1] LOCATION: exec_simple_query, postgres.c:1081
25
+ 2010-10-10 15:00:02 GMT [38747]: [1673-1] LOG: 00000: duration: 0.020 ms statement: BEGIN
26
+ 2010-10-10 15:00:02 GMT [38747]: [1674-1] LOCATION: exec_simple_query, postgres.c:1081
27
+ 2010-10-10 15:00:02 GMT [38747]: [1675-1] LOG: 00000: duration: 0.157 ms statement: DELETE FROM "delayed_jobs" WHERE "id" = 123456
28
+ 2010-10-10 15:00:02 GMT [38747]: [1676-1] LOCATION: exec_simple_query, postgres.c:1081
29
+ 2010-10-10 15:00:02 GMT [38747]: [1677-1] LOG: 00000: duration: 0.050 ms statement: COMMIT
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ shared_examples_for "A valid Logs::Reader instance" do
4
+
5
+ specify{ reader.should be_a(::Alf::Logs::Reader) }
6
+
7
+ it "should yield a pseudo-relation" do
8
+ reader.all?{|tuple| tuple.is_a?(Hash)}.should be_true
9
+ end
10
+
11
+ end
12
+ describe Logs::Reader do
13
+
14
+ let(:input){ _("apache_combined.log", __FILE__) }
15
+
16
+ describe "when called on a reader directly" do
17
+ let(:reader){
18
+ ::Alf::Logs::Reader.new(input)
19
+ }
20
+ it_should_behave_like "A valid Logs::Reader instance"
21
+ end
22
+
23
+ describe "when called through registered one" do
24
+ let(:reader){
25
+ ::Alf::Reader.reader(input)
26
+ }
27
+ it_should_behave_like "A valid Logs::Reader instance"
28
+ end
29
+
30
+ describe "when called through factory method" do
31
+ let(:reader){
32
+ ::Alf::Reader.logs(input)
33
+ }
34
+ it_should_behave_like "A valid Logs::Reader instance"
35
+ end
36
+
37
+ describe "the auto-detect feature" do
38
+ let(:reader){ ::Alf::Logs::Reader.new(nil,nil,:file_format => nil) }
39
+ let(:relation){ reader.to_rel }
40
+
41
+ describe "on postgresql.log" do
42
+ before{ reader.pipe(_("postgresql.log", __FILE__)) }
43
+ it_should_behave_like "A valid Logs::Reader instance"
44
+ specify{ relation.should_not be_empty }
45
+ end
46
+
47
+ describe "on apache_combined.log" do
48
+ before{ reader.pipe(_("apache_combined.log", __FILE__)) }
49
+ it_should_behave_like "A valid Logs::Reader instance"
50
+ specify{ relation.should_not be_empty }
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end
@@ -38,7 +38,7 @@ module Alf
38
38
  end
39
39
 
40
40
  describe "when factored with Lispy" do
41
- let(:operator){ Lispy.clip(input, [:a], true) }
41
+ let(:operator){ Lispy.clip(input, [:a], :allbut => true) }
42
42
  it { should == expected }
43
43
  end
44
44
 
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::NonRelational
4
+ describe Coerce do
5
+
6
+ let(:operator_class){ Coerce }
7
+ it_should_behave_like("An operator class")
8
+
9
+ let(:input) {Alf::Relation[
10
+ {:a => "12", :b => "14.0"},
11
+ ]}
12
+
13
+ subject{ operator.to_rel }
14
+
15
+ describe "When used without --strict" do
16
+ let(:expected){Alf::Relation[
17
+ {:a => 12, :b => 14.0}
18
+ ]}
19
+
20
+ describe "when factored from commandline" do
21
+ let(:operator){ Coerce.run(%w{-- a Integer b Float}) }
22
+ before{ operator.pipe(input) }
23
+ it { should == expected }
24
+ end
25
+
26
+ describe "when factored with Lispy" do
27
+ let(:operator){ Lispy.coerce(input, :a => Integer, :b => Float) }
28
+ it { should == expected }
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -44,12 +44,25 @@ module Alf
44
44
  ]}
45
45
 
46
46
  describe "When factored with Lispy" do
47
- let(:operator){ Lispy.defaults(input, {:a => 1, :b => "b"}, true) }
47
+ let(:operator){ Lispy.defaults(input, {:a => 1, :b => "b"}, :strict => true) }
48
48
  it{ should == expected }
49
49
  end
50
50
 
51
51
  end
52
+
53
+ describe "when used with tuple expressions" do
54
+ let(:input) {[
55
+ {:a => nil, :b => "b"},
56
+ ]}
57
+ let(:expected) {[
58
+ {:a => "b", :b => "b"},
59
+ ]}
60
+ let(:operator){
61
+ Lispy.defaults(input, {:a => TupleExpression.coerce("b")})
62
+ }
63
+ it{ should == expected }
64
+ end
52
65
 
53
66
  end
54
67
  end
55
- end
68
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+ module Alf
3
+ module Operator::NonRelational
4
+ describe Generator do
5
+
6
+ let(:operator_class){ Generator }
7
+ it_should_behave_like("An operator class")
8
+
9
+ subject{ operator.to_rel }
10
+
11
+ describe "without providing anything" do
12
+
13
+ let(:expected){Relation[
14
+ {:num => 1},
15
+ {:num => 2},
16
+ {:num => 3},
17
+ {:num => 4},
18
+ {:num => 5},
19
+ {:num => 6},
20
+ {:num => 7},
21
+ {:num => 8},
22
+ {:num => 9},
23
+ {:num => 10},
24
+ ]}
25
+
26
+ describe "When factored with Lispy" do
27
+ let(:operator){ Lispy.generator() }
28
+ it{ should == expected }
29
+ end
30
+
31
+ describe "When factored from commandline args" do
32
+ let(:operator){ Generator.run(%w{}) }
33
+ it{ should == expected }
34
+ end
35
+
36
+ end
37
+
38
+ describe "when providing an size" do
39
+
40
+ let(:expected){Relation[
41
+ {:num => 1},
42
+ {:num => 2},
43
+ ]}
44
+
45
+ describe "When factored with Lispy" do
46
+ let(:operator){ Lispy.generator(2) }
47
+ it{ should == expected }
48
+ end
49
+
50
+ describe "When factored from commandline args" do
51
+ let(:operator){ Generator.run(["--", "2"]) }
52
+ it{ should == expected }
53
+ end
54
+
55
+ end
56
+
57
+ describe "when providing a size and a name" do
58
+
59
+ let(:expected){Relation[
60
+ {:id => 1},
61
+ {:id => 2},
62
+ ]}
63
+
64
+ describe "When factored with Lispy" do
65
+ let(:operator){ Lispy.generator(2, :id) }
66
+ it{ should == expected }
67
+ end
68
+
69
+ describe "When factored from commandline args" do
70
+ let(:operator){ Generator.run(["--", "2", "--", "id"]) }
71
+ it{ should == expected }
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+ end
78
+ end