csvyaml 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.
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: {}