csvyaml 0.0.1 → 0.1.0

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: 1d89beb0f7d059235cd458d33f33b107fba249cb
4
- data.tar.gz: c6404fe2ab304c3130ba97afdd72ab1e8badf9c6
3
+ metadata.gz: c07f82dfd13c43d0246141a6c79d36d42222d00a
4
+ data.tar.gz: 45ac0671f99a0d44b7ffd782c6ab3462f1304ba3
5
5
  SHA512:
6
- metadata.gz: 85372ed928cd3a8fc433afba51333951ac1632b254f9092e3eb2c0de698bbfff697e27ccfa9c90ee520fc5204ff71525ca19df6509f77e02c75a230c2d5a5a93
7
- data.tar.gz: 4c0eaca93f47884b0e4c88eef1eb5eef1c688fb874dd2cbd33d9a209b2a3e833f5f5da8d5ad8624d5104a28df77003a248d6cd73952d7dfaf3f87a5476251df9
6
+ metadata.gz: 0fae80b8706cf2def97794fc32f0aaae92efd3bc403dd9904e7be1370b05b84c4670ba25d4b64ca3aeb3af3135a83ae4c60577904d724678c8b8d48bfed2c593
7
+ data.tar.gz: 996746983caeeef7ce305533c5d564e375656cbd4787a8e9698d56fc5f2ba71cb6703fb93e33b672bb0f489ae75bc6269a5cd28d8921d0d758ff4699c8c22cb5
data/Manifest.txt CHANGED
@@ -3,4 +3,10 @@ Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/csvyaml.rb
6
+ lib/csvyaml/parser.rb
6
7
  lib/csvyaml/version.rb
8
+ test/data/hello.yaml.csv
9
+ test/data/hello11.yaml.csv
10
+ test/helper.rb
11
+ test/test_parser.rb
12
+ test/test_parser_misc.rb
data/README.md CHANGED
@@ -1,14 +1,15 @@
1
1
  # CSV <3 YAML Parser / Reader
2
2
 
3
- csvyaml library / gem - read tabular data in the CSV <3 YAML format, that is, comma-separated values CSV (line-by-line) records with yaml ain't markup language (YAML) encoding rules
3
+ csvyaml library / gem - read tabular data in the CSV <3 YAML format, that is, comma-separated values (CSV) line-by-line records with yaml ain't markup language (YAML) encoding rules
4
4
 
5
- * home :: [github.com/csv11/csvyaml](https://github.com/csv11/csvyaml)
6
- * bugs :: [github.com/csv11/csvyaml/issues](https://github.com/csv11/csvyaml/issues)
5
+ * home :: [github.com/csvreader/csvyaml](https://github.com/csvreader/csvyaml)
6
+ * bugs :: [github.com/csvreader/csvyaml/issues](https://github.com/csvreader/csvyaml/issues)
7
7
  * gem :: [rubygems.org/gems/csvyaml](https://rubygems.org/gems/csvyaml)
8
8
  * rdoc :: [rubydoc.info/gems/csvyaml](http://rubydoc.info/gems/csvyaml)
9
9
  * forum :: [wwwmake](http://groups.google.com/group/wwwmake)
10
10
 
11
11
 
12
+
12
13
  ## Usage
13
14
 
14
15
  to be done
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ Hoe.spec 'csvyaml' do
8
8
  self.summary = "csvyaml - read tabular data in the CSV <3 YAML format, that is, comma-separated values CSV (line-by-line) records with yaml ain't markup language (YAML) encoding rules"
9
9
  self.description = summary
10
10
 
11
- self.urls = ['https://github.com/csv11/csvyaml']
11
+ self.urls = ['https://github.com/csvreader/csvyaml']
12
12
 
13
13
  self.author = 'Gerald Bauer'
14
14
  self.email = 'wwwmake@googlegroups.com'
data/lib/csvyaml.rb CHANGED
@@ -1,11 +1,21 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'pp'
4
-
4
+ require 'yaml'
5
+ require 'logger'
5
6
 
6
7
  ## our own code
7
8
  require 'csvyaml/version' # note: let version always go first
9
+ require 'csvyaml/parser'
10
+
11
+
12
+
13
+ ## add some "alternative" shortcut aliases
14
+ CSV_YAML = CsvYaml
15
+ CSVYAML = CsvYaml
16
+ CSVY = CsvYaml
17
+ CsvY = CsvYaml
18
+
8
19
 
9
20
 
10
- pp CsvYaml.banner
11
- pp CsvYaml.root
21
+ puts CsvYaml.banner
@@ -0,0 +1,133 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ class CsvYaml
5
+
6
+ ###################################
7
+ ## add simple logger with debug flag/switch
8
+ #
9
+ # use Parser.debug = true # to turn on
10
+ #
11
+ # todo/fix: use logutils instead of std logger - why? why not?
12
+
13
+ def self.build_logger()
14
+ l = Logger.new( STDOUT )
15
+ l.level = :info ## set to :info on start; note: is 0 (debug) by default
16
+ l
17
+ end
18
+ def self.logger() @@logger ||= build_logger; end
19
+ def logger() self.class.logger; end
20
+
21
+
22
+
23
+
24
+
25
+ def self.open( path, mode=nil, &block ) ## rename path to filename or name - why? why not?
26
+
27
+ ## note: default mode (if nil/not passed in) to 'r:bom|utf-8'
28
+ f = File.open( path, mode ? mode : 'r:bom|utf-8' )
29
+ csv = new( f )
30
+
31
+ # handle blocks like Ruby's open()
32
+ if block_given?
33
+ begin
34
+ block.call( csv )
35
+ ensure
36
+ csv.close
37
+ end
38
+ else
39
+ csv
40
+ end
41
+ end # method self.open
42
+
43
+
44
+ def self.read( path )
45
+ open( path ) { |csv| csv.read }
46
+ end
47
+
48
+
49
+ def self.foreach( path, &block )
50
+ csv = open( path )
51
+
52
+ if block_given?
53
+ begin
54
+ csv.each( &block )
55
+ ensure
56
+ csv.close
57
+ end
58
+ else
59
+ csv.to_enum ## note: caller (responsible) must close file!!!
60
+ ## remove version without block given - why? why not?
61
+ ## use Csv.open().to_enum or Csv.open().each
62
+ ## or Csv.new( File.new() ).to_enum or Csv.new( File.new() ).each ???
63
+ end
64
+ end # method self.foreach
65
+
66
+
67
+ def self.parse( str_or_readable, &block )
68
+ csv = new( str_or_readable )
69
+
70
+ if block_given?
71
+ csv.each( &block ) ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
72
+ else # slurp contents, if no block is given
73
+ csv.read ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
74
+ end
75
+ end # method self.parse
76
+
77
+
78
+
79
+ def initialize( str_or_readable )
80
+ if str_or_readable.is_a?( String )
81
+ @input = str_or_readable # note: just needs each for each_line
82
+ else ## assume io
83
+ @input = str_or_readable
84
+ end
85
+ end
86
+
87
+
88
+
89
+ include Enumerable
90
+
91
+ def each( &block )
92
+ if block_given?
93
+ @input.each_line do |line|
94
+
95
+ logger.debug "line:" if logger.debug?
96
+ logger.debug line.pretty_inspect if logger.debug?
97
+
98
+
99
+ ## note: chomp('') if is an empty string,
100
+ ## it will remove all trailing newlines from the string.
101
+ ## use line.sub(/[\n\r]*$/, '') or similar instead - why? why not?
102
+ line = line.chomp( '' )
103
+ line = line.strip ## strip leading and trailing whitespaces (space/tab) too
104
+ logger.debug line.pretty_inspect if logger.debug?
105
+
106
+ if line.empty? ## skip blank lines
107
+ logger.debug "skip blank line" if logger.debug?
108
+ next
109
+ end
110
+
111
+ if line.start_with?( "#" ) ## skip comment lines
112
+ logger.debug "skip comment line" if logger.debug?
113
+ next
114
+ end
115
+
116
+ ## note: auto-wrap in array e.g. with []
117
+ ## add document marker (---) why? why not?
118
+ values = YAML.load( "---\n[#{line}]" )
119
+ logger.debug values.pretty_inspect if logger.debug?
120
+ block.call( values )
121
+ end
122
+ else
123
+ to_enum
124
+ end
125
+ end # method each
126
+
127
+ def read() to_a; end # method read
128
+
129
+ def close
130
+ @input.close if @input.respond_to?(:close) ## note: string needs no close
131
+ end
132
+
133
+ end # class CsvYaml
@@ -4,10 +4,11 @@
4
4
  class CsvYaml
5
5
 
6
6
  MAJOR = 0
7
- MINOR = 0
8
- PATCH = 1
7
+ MINOR = 1
8
+ PATCH = 0
9
9
  VERSION = [MAJOR,MINOR,PATCH].join('.')
10
10
 
11
+
11
12
  def self.version
12
13
  VERSION
13
14
  end
@@ -0,0 +1,3 @@
1
+ 1,John,12 Totem Rd. Aspen,true
2
+ 2,Bob,null,false
3
+ 3,Sue,"Bigsby, 345 Carnival, WA 23009",false
@@ -0,0 +1,5 @@
1
+ # hello world
2
+
3
+ 1, John, 12 Totem Rd. Aspen, true
4
+ 2, Bob, null, false
5
+ 3, Sue, "Bigsby, 345 Carnival, WA 23009", false
data/test/helper.rb ADDED
@@ -0,0 +1,20 @@
1
+ ## $:.unshift(File.dirname(__FILE__))
2
+
3
+ ## minitest setup
4
+
5
+ require 'minitest/autorun'
6
+
7
+
8
+ ## our own code
9
+ require 'csvyaml'
10
+
11
+
12
+ ## add test_data_dir helper
13
+ class CsvYaml
14
+ def self.test_data_dir
15
+ "#{root}/test/data"
16
+ end
17
+ end
18
+
19
+
20
+ CsvYaml.logger.level = :debug ## turn on "global" logging
@@ -0,0 +1,104 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_parser.rb
6
+
7
+
8
+ require 'helper'
9
+
10
+ class TestParser < MiniTest::Test
11
+
12
+
13
+ def parser
14
+ CsvYaml
15
+ end
16
+
17
+
18
+ def records ## "standard" records for testing
19
+ [[1, "John", "12 Totem Rd. Aspen", true],
20
+ [2, "Bob", nil, false],
21
+ [3, "Sue", "Bigsby, 345 Carnival, WA 23009", false]]
22
+ end
23
+
24
+
25
+
26
+ def test_parse
27
+ assert_equal records, parser.parse( <<TXT )
28
+ 1,John,12 Totem Rd. Aspen,true
29
+ 2,Bob,null,false
30
+ 3,Sue,"Bigsby, 345 Carnival, WA 23009",false
31
+ TXT
32
+
33
+ assert_equal records, parser.parse( <<TXT )
34
+ # hello world
35
+
36
+ 1,John,12 Totem Rd. Aspen,true
37
+ 2,Bob,null,false
38
+ 3,Sue,"Bigsby, 345 Carnival, WA 23009",false
39
+ TXT
40
+
41
+ assert_equal records, parser.parse( <<TXT )
42
+ # hello world (pretty printed)
43
+
44
+ 1, John, 12 Totem Rd. Aspen, true
45
+ 2, Bob, null, false
46
+ 3, Sue, "Bigsby, 345 Carnival, WA 23009", false
47
+
48
+ # try more comments and empty lines
49
+
50
+ TXT
51
+
52
+
53
+ txt =<<TXT
54
+ # hello world
55
+ 1,John,12 Totem Rd. Aspen,true
56
+ 2,Bob,null,false
57
+ 3,Sue,"Bigsby, 345 Carnival, WA 23009",false
58
+ TXT
59
+
60
+ recs = []
61
+ parser.parse( txt ) { |rec| recs << rec }
62
+ assert_equal records, recs
63
+ end
64
+
65
+
66
+ def test_read
67
+ assert_equal records, parser.read( "#{CsvYaml.test_data_dir}/hello.yaml.csv" )
68
+ assert_equal records, parser.read( "#{CsvYaml.test_data_dir}/hello11.yaml.csv" )
69
+ end
70
+
71
+
72
+ def test_open
73
+ assert_equal records, parser.open( "#{CsvYaml.test_data_dir}/hello.yaml.csv", "r:bom|utf-8" ).read
74
+ assert_equal records, parser.open( "#{CsvYaml.test_data_dir}/hello11.yaml.csv", "r:bom|utf-8" ).read
75
+ end
76
+
77
+
78
+ def test_foreach
79
+ recs = []
80
+ parser.foreach( "#{CsvYaml.test_data_dir}/hello.yaml.csv" ) { |rec| recs << rec }
81
+ assert_equal records, recs
82
+
83
+ recs = []
84
+ parser.foreach( "#{CsvYaml.test_data_dir}/hello11.yaml.csv" ) { |rec| recs << rec }
85
+ assert_equal records, recs
86
+ end
87
+
88
+
89
+ def test_enum
90
+ csv = CsvYaml.new( <<TXT )
91
+ # hello world
92
+
93
+ 1,John,12 Totem Rd. Aspen,true
94
+ 2,Bob,null,false
95
+ 3,Sue,"Bigsby, 345 Carnival, WA 23009",false
96
+ TXT
97
+
98
+ it = csv.to_enum
99
+ assert_equal [1, "John", "12 Totem Rd. Aspen", true], it.next
100
+ assert_equal [2, "Bob", nil, false], it.next
101
+ assert_equal [3, "Sue", "Bigsby, 345 Carnival, WA 23009", false], it.next
102
+ end
103
+
104
+ end # class TestParser
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_parser_misc.rb
6
+
7
+
8
+ require 'helper'
9
+
10
+ class TestParserMisc < MiniTest::Test
11
+
12
+
13
+ def parser
14
+ CsvYaml
15
+ end
16
+
17
+
18
+ def test_quotes_and_commas
19
+ assert_equal [
20
+ [1, "John", "12 Totem Rd., Aspen", true],
21
+ [2, "Bob", nil, false],
22
+ [3, "Sue", "\"Bigsby\", 345 Carnival, WA 23009", false]
23
+ ], parser.parse( <<TXT )
24
+ 1,John,"12 Totem Rd., Aspen",true
25
+ 2,Bob,null,false
26
+ 3,Sue,"\\"Bigsby\\", 345 Carnival, WA 23009",false
27
+ TXT
28
+ end
29
+
30
+
31
+ def test_arrays
32
+ assert_equal [
33
+ [1, "directions", ["north","south","east","west"]],
34
+ [2, "colors", ["red","green","blue"]],
35
+ [3, "drinks", ["soda","water","tea","coffe"]],
36
+ [4, "spells", []],
37
+ ], parser.parse( <<TXT )
38
+ # CSV <3 YAML with array values
39
+
40
+ 1,directions,[north,south,east,west]
41
+ 2,colors,[red,green,blue]
42
+ 3,drinks,[soda,water,tea,coffe]
43
+ 4,spells,[]
44
+ TXT
45
+ end
46
+
47
+ def test_misc
48
+ ## note:
49
+ ## in the csv <3 json source text backslash needs to get doubled / escaped twice e.g.
50
+ ## \\" for quotes
51
+ ## \\n for newlines and so on
52
+
53
+ assert_equal [
54
+ ["index", "value1", "value2"],
55
+ ["number", 1, 2],
56
+ ["boolean", false, true],
57
+ ["null", nil, "non null"],
58
+ ["array of numbers", [1], [1,2]],
59
+ ["simple object", {"a" => 1}, {"a" => 1, "b" => 2}],
60
+ ["array with mixed objects", [1, nil,"ball"], [2,{"a" => 10, "b" => 20},"cube"]],
61
+ ["string with quotes", "a\"b", "alert(\"Hi!\")"],
62
+ ["string with bell&newlines","bell is \u0007","multi\nline\ntext"]
63
+ ], parser.parse( <<TXT )
64
+ # CSV with all kinds of values
65
+
66
+ index,value1,value2
67
+ number,1,2
68
+ boolean,false,true
69
+ "null",null,non null
70
+ array of numbers,[1],[1,2]
71
+ ## note: key:value pairs need a space after colon!!! NOT working {a:1},{a:1, b:2}
72
+ simple object,{a: 1},{a: 1, b: 2}
73
+ ## note: again - key:value pairs need a space after colon!!! NOT working {a:10, b:20}
74
+ array with mixed objects,[1,null,ball],[2,{a: 10,b: 20},cube]
75
+ string with quotes,"a\\"b","alert(\\"Hi!\\")"
76
+ string with bell&newlines,"bell is \\u0007","multi\\nline\\ntext"
77
+ TXT
78
+
79
+ end
80
+
81
+
82
+ end # class TestParserMisc
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csvyaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-17 00:00:00.000000000 Z
11
+ date: 2018-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -54,8 +54,14 @@ files:
54
54
  - README.md
55
55
  - Rakefile
56
56
  - lib/csvyaml.rb
57
+ - lib/csvyaml/parser.rb
57
58
  - lib/csvyaml/version.rb
58
- homepage: https://github.com/csv11/csvyaml
59
+ - test/data/hello.yaml.csv
60
+ - test/data/hello11.yaml.csv
61
+ - test/helper.rb
62
+ - test/test_parser.rb
63
+ - test/test_parser_misc.rb
64
+ homepage: https://github.com/csvreader/csvyaml
59
65
  licenses:
60
66
  - Public Domain
61
67
  metadata: {}