csvreader 1.1.4 → 1.1.5

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: dd541a30e12622b666a01bc18b5ba80d93cbd1aa
4
- data.tar.gz: 773aa117ae2b41bfce6a8cde5df1ed1df4eadeab
3
+ metadata.gz: 5a26d07e0e618e2cfb6803c8f059e76cf0541a47
4
+ data.tar.gz: 71ed3dba6b2d0df06e733832b35a709bd427aabc
5
5
  SHA512:
6
- metadata.gz: b4720613f00b591b3d419f03c06aef8d5e8bb274e4d35e7b1f12f6d14aadb64d1611c7822e3fdc0d2a63c60b653b79a64339aabfd107fb73b14a47bf646c7153
7
- data.tar.gz: 3ce20e6925e81e80c6a61e03fd208d852741b7c8d3dd32d045f56b748844782a47810ce041eaa1a8d30f63f282c1655fc6939f7f0ff10294e25ec0be48ede043
6
+ metadata.gz: 10a4ef973d7c573243fd02c224ee16951a7403ad8472ad5a7b0806c252ec718be3ef404c90e3c32ff41dc2388e441e6a3931226330ce870da54dcff979ced024
7
+ data.tar.gz: '09030d9645657ef71643c1703209806613b29d6da34aa9c01eb88f3c9a7530c6b2b4953931e5f3789d5fc4a3a2daac9e65317544305dee00347f84cd5e41d22d'
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  class CsvReader
4
- class Builder ## rename to CsvReaderBuilder - why? why not?
4
+ class Builder
5
5
 
6
6
 
7
7
  def initialize( parser )
@@ -11,53 +11,35 @@ class Builder ## rename to CsvReaderBuilder - why? why not?
11
11
 
12
12
  ## (auto-)forward to wrapped parser
13
13
  ## note/fix: not all parser use/have config e.g. ParserTab, ParserFixed, etc.
14
- def config() @parser.config; end
15
-
16
-
14
+ ##
17
15
  ## todo/fix:
18
16
  ## add parser config (attribute) setter e.g.
19
17
  ## - sep=(value)
20
18
  ## - comment=(value)
21
19
  ## - and so on!!!
20
+ def config() @parser.config; end
21
+
22
22
 
23
- def open( path, mode=nil,
24
- sep: nil,
25
- converters: nil,
26
- width: nil,
27
- parser: @parser, &block )
28
- CsvReader.open( path, mode,
29
- sep: sep, converters: converters, width: width,
30
- parser: @parser, &block )
31
- end
32
23
 
33
- def read( path, sep: nil,
34
- converters: nil,
35
- width: nil )
36
- CsvReader.read( path,
37
- sep: sep, converters: converters, width: width,
38
- parser: @parser )
24
+ def open( path, mode=nil, **kwargs, &block )
25
+ CsvReader.open( path, mode, parser: @parser, **kwargs, &block )
39
26
  end
40
27
 
41
- def header( path, sep: nil, width: nil )
42
- CsvReader.header( path,
43
- sep: sep, width: width,
44
- parser: @parser )
28
+ def read( path, **kwargs )
29
+ CsvReader.read( path, parser: @parser, **kwargs )
45
30
  end
46
31
 
47
- def foreach( path, sep: nil,
48
- converters: nil, width: nil, &block )
49
- CsvReader.foreach( path,
50
- sep: sep, converters: converters, width: width,
51
- parser: @parser, &block )
32
+ def header( path, **kwargs )
33
+ CsvReader.header( path, parser: @parser, **kwargs )
52
34
  end
53
35
 
36
+ def foreach( path, **kwargs, &block )
37
+ CsvReader.foreach( path, parser: @parser, **kwargs, &block )
38
+ end
54
39
 
55
40
 
56
- def parse( data, sep: nil,
57
- converters: nil, width: nil, &block )
58
- CsvReader.parse( data,
59
- sep: sep, converters: converters, width: width,
60
- parser: @parser, &block )
41
+ def parse( str_or_readable, **kwargs, &block )
42
+ CsvReader.parse( str_or_readable, parser: @parser, **kwargs, &block )
61
43
  end
62
44
  end # class Builder
63
45
  end # class CsvReader
@@ -65,72 +47,38 @@ end # class CsvReader
65
47
 
66
48
 
67
49
  class CsvHashReader
68
- class Builder ## rename to CsvHashReaderBuilder - why? why not?
50
+ class Builder
69
51
  def initialize( parser )
70
52
  @parser = parser
71
53
  end
72
54
 
73
55
  ## (auto-)forward to wrapped parser
74
56
  ## note/fix: not all parser use/have config e.g. ParserTab, ParserFixed, etc.
75
- def config() @parser.config; end
76
-
57
+ ##
77
58
  ## todo/fix:
78
59
  ## add parser config (attribute) setter e.g.
79
60
  ## - sep=(value)
80
61
  ## - comment=(value)
81
62
  ## - and so on!!!
63
+ def config() @parser.config; end
64
+
82
65
 
83
66
 
84
- def open( path, mode=nil,
85
- headers: nil,
86
- sep: nil,
87
- converters: nil,
88
- header_converters: nil,
89
- width: nil,
90
- parser: @parser, &block )
91
- CsvHashReader.open( path, mode,
92
- headers: headers, sep: sep, converters: converters,
93
- header_converters: header_converters,
94
- width: width,
95
- parser: @parser, &block )
67
+ def open( path, mode=nil, **kwargs, &block )
68
+ CsvHashReader.open( path, mode, parser: @parser, **kwargs, &block )
96
69
  end
97
70
 
98
- def read( path, headers: nil,
99
- sep: nil,
100
- converters: nil,
101
- header_converters: nil,
102
- width: nil )
103
- CsvHashReader.read( path,
104
- headers: headers,
105
- sep: sep, converters: converters,
106
- header_converters: header_converters,
107
- width: width,
108
- parser: @parser )
71
+ def read( path, **kwargs )
72
+ CsvHashReader.read( path, parser: @parser, **kwargs )
109
73
  end
110
74
 
111
- def foreach( path, headers: nil,
112
- sep: nil,
113
- converters: nil,
114
- header_converters: nil, width: nil, &block )
115
- CsvHashReader.foreach( path,
116
- headers: headers,
117
- sep: sep, converters: converters,
118
- header_converters: header_converters,
119
- width: width,
120
- parser: @parser, &block )
75
+ def foreach( path, **kwargs, &block )
76
+ CsvHashReader.foreach( path, parser: @parser, **kwargs, &block )
121
77
  end
122
78
 
123
79
 
124
- def parse( data, headers: nil,
125
- sep: nil,
126
- converters: nil,
127
- header_converters: nil, width: nil, &block )
128
- CsvHashReader.parse( data,
129
- headers: headers,
130
- sep: sep, converters: converters,
131
- header_converters: header_converters,
132
- width: width,
133
- parser: @parser, &block )
80
+ def parse( str_or_readable, **kwargs, &block )
81
+ CsvHashReader.parse( str_or_readable, parser: @parser, **kwargs, &block )
134
82
  end
135
83
  end # class Builder
136
84
  end # class CsvHashReader
@@ -110,7 +110,8 @@ def initialize( converters, registry=CONVERTERS )
110
110
  add_converter( converter, registry )
111
111
  end
112
112
  end
113
- end
113
+ end
114
+
114
115
 
115
116
  def to_a() @converters; end ## todo: rename to/use converters attribute name - why? why not?
116
117
  def empty?() @converters.empty?; end
@@ -44,7 +44,12 @@ def parse_lines( input, &block )
44
44
  ## pp line
45
45
 
46
46
  # note: trailing empty fields get (auto-)trimmed by split !!!!!!!
47
- values = line.split( "\t" )
47
+ # Solution!! change split( "\t" ) to split( "\t", -1 )
48
+ # If the limit parameter is omitted, trailing null fields are suppressed.
49
+ # If limit is a positive number, at most that number of fields will be returned
50
+ # (if limit is 1, the entire string is returned as the only entry in an array).
51
+ # If negative, there is no limit to the number of fields returned, and trailing null fields are not suppressed.
52
+ values = line.split( "\t", -1 )
48
53
  ## pp values
49
54
 
50
55
  ## note: requires block - enforce? how? why? why not?
@@ -5,15 +5,13 @@ class CsvReader
5
5
  def self.open( path, mode=nil,
6
6
  sep: nil,
7
7
  converters: nil,
8
- width: nil,
9
- parser: nil, &block ) ## rename path to filename or name - why? why not?
8
+ parser: nil, **kwargs, &block ) ## rename path to filename or name - why? why not?
10
9
 
11
10
  ## note: default mode (if nil/not passed in) to 'r:bom|utf-8'
12
11
  f = File.open( path, mode ? mode : 'r:bom|utf-8' )
13
- csv = new(f, sep: sep,
12
+ csv = new(f, sep: sep,
14
13
  converters: converters,
15
- width: width,
16
- parser: parser )
14
+ parser: parser, **kwargs )
17
15
 
18
16
  # handle blocks like Ruby's open(), not like the (old old) CSV library
19
17
  if block_given?
@@ -30,22 +28,21 @@ class CsvReader
30
28
 
31
29
  def self.read( path, sep: nil,
32
30
  converters: nil,
33
- width: nil,
34
- parser: nil )
31
+ parser: nil, **kwargs )
32
+
35
33
  open( path,
36
34
  sep: sep,
37
35
  converters: converters,
38
- width: width,
39
- parser: parser ) { |csv| csv.read }
36
+ parser: parser, **kwargs ) { |csv| csv.read }
40
37
  end
41
38
 
42
39
 
43
- def self.header( path, sep: nil, width: nil, parser: nil ) ## use header or headers - or use both (with alias)?
40
+ def self.header( path, sep: nil, parser: nil, **kwargs ) ## use header or headers - or use both (with alias)?
44
41
  # read first lines (only)
45
42
  # and parse with csv to get header from csv library itself
46
43
 
47
44
  records = []
48
- open( path, sep: sep, width: width, parser: parser ) do |csv|
45
+ open( path, sep: sep, parser: parser, **kwargs ) do |csv|
49
46
  csv.each do |record|
50
47
  records << record
51
48
  break ## only parse/read first record
@@ -60,8 +57,8 @@ class CsvReader
60
57
 
61
58
 
62
59
  def self.foreach( path, sep: nil,
63
- converters: nil, width: nil, parser: nil, &block )
64
- csv = open( path, sep: sep, converters: converters, width: width, parser: parser )
60
+ converters: nil, parser: nil, **kwargs, &block )
61
+ csv = open( path, sep: sep, converters: converters, parser: parser, **kwargs )
65
62
 
66
63
  if block_given?
67
64
  begin
@@ -78,11 +75,10 @@ class CsvReader
78
75
  end # method self.foreach
79
76
 
80
77
 
81
- def self.parse( data, sep: nil,
78
+ def self.parse( str_or_readable, sep: nil,
82
79
  converters: nil,
83
- width: nil,
84
- parser: nil, &block )
85
- csv = new( data, sep: sep, converters: converters, width: width, parser: parser )
80
+ parser: nil, **kwargs, &block )
81
+ csv = new( str_or_readable, sep: sep, converters: converters, parser: parser, **kwargs )
86
82
 
87
83
  if block_given?
88
84
  csv.each( &block ) ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
@@ -93,14 +89,15 @@ class CsvReader
93
89
 
94
90
 
95
91
 
92
+
96
93
  ############################
97
94
  ## note: only add parse_line convenience helper for default
98
95
  ## always use parse (do NOT/NOT/NOT use parse_line) - why? why not?
99
96
  ## todo/fix: remove parse_line!!!
100
- def self.parse_line( data, sep: nil,
101
- converters: nil, width: nil )
97
+ def self.parse_line( str_or_readable, sep: nil,
98
+ converters: nil, **kwargs )
102
99
  records = []
103
- parse( data, sep: sep, converters: converters, width: width ) do |record|
100
+ parse( str_or_readable, sep: sep, converters: converters, **kwargs ) do |record|
104
101
  records << record
105
102
  break # only parse first record
106
103
  end
@@ -110,15 +107,15 @@ class CsvReader
110
107
 
111
108
 
112
109
 
113
- def initialize( data, sep: nil, converters: nil, width: nil, parser: nil )
114
- raise ArgumentError.new( "Cannot parse nil as CSV" ) if data.nil?
110
+ def initialize( str_or_readable, sep: nil, converters: nil, parser: nil, **kwargs )
111
+ raise ArgumentError.new( "Cannot parse nil as CSV" ) if str_or_readable.nil?
115
112
  ## todo: use (why? why not) - raise ArgumentError, "Cannot parse nil as CSV" if data.nil?
116
113
 
117
114
  # create the IO object we will read from
118
- @io = data.is_a?(String) ? StringIO.new(data) : data
115
+ @io = str_or_readable.is_a?(String) ? StringIO.new(str_or_readable) : str_or_readable
119
116
 
120
- @sep = sep # (optional) for ParserStd, ParserStrict
121
- @width = width # (optional) for ParserFixed
117
+ @sep = sep # (optional) for ParserStd, ParserStrict
118
+ @kwargs = kwargs # e.g. (optional) :width for ParserFixed
122
119
 
123
120
  @converters = Converter.create_converters( converters )
124
121
 
@@ -150,7 +147,11 @@ class CsvReader
150
147
  ## todo/fix: change sep keyword to "known" classes!!!!
151
148
  kwargs[:sep] = @sep if @sep && @parser.respond_to?( :'sep=' )
152
149
 
153
- kwargs[:width] = @width if @parser.is_a?( ParserFixed )
150
+
151
+ kwargs[:width] = @kwargs[:width] if @parser.is_a?( ParserFixed )
152
+
153
+ ## todo/fix: print warning about unused / unknown kwargs!!!!!
154
+
154
155
 
155
156
  ## check array / pipeline of converters is empty (size=0 e.g. is [])
156
157
  if @converters.empty?
@@ -15,8 +15,7 @@ def self.open( path, mode=nil,
15
15
  sep: nil,
16
16
  converters: nil,
17
17
  header_converters: nil,
18
- width: nil,
19
- parser: nil, &block ) ## rename path to filename or name - why? why not?
18
+ parser: nil, **kwargs, &block ) ## rename path to filename or name - why? why not?
20
19
 
21
20
  ## note: default mode (if nil/not passed in) to 'r:bom|utf-8'
22
21
  f = File.open( path, mode ? mode : 'r:bom|utf-8' )
@@ -24,8 +23,7 @@ def self.open( path, mode=nil,
24
23
  sep: sep,
25
24
  converters: converters,
26
25
  header_converters: header_converters,
27
- width: width,
28
- parser: parser )
26
+ parser: parser, **kwargs )
29
27
 
30
28
  # handle blocks like Ruby's open(), not like the (old old) CSV library
31
29
  if block_given?
@@ -44,15 +42,14 @@ def self.read( path, headers: nil,
44
42
  sep: nil,
45
43
  converters: nil,
46
44
  header_converters: nil,
47
- width: nil,
48
- parser: nil )
45
+ parser: nil,
46
+ **kwargs )
49
47
  open( path,
50
48
  headers: headers,
51
49
  sep: sep,
52
50
  converters: converters,
53
51
  header_converters: header_converters,
54
- width: width,
55
- parser: parser ) { |csv| csv.read }
52
+ parser: parser, **kwargs ) { |csv| csv.read }
56
53
  end
57
54
 
58
55
 
@@ -61,15 +58,14 @@ def self.foreach( path, headers: nil,
61
58
  sep: nil,
62
59
  converters: nil,
63
60
  header_converters: nil,
64
- width: nil,
65
- parser: nil, &block )
61
+ parser: nil, **kwargs, &block )
66
62
  csv = open( path,
67
63
  headers: headers,
68
64
  sep: sep,
69
65
  converters: converters,
70
66
  header_converters: header_converters,
71
- width: width,
72
- parser: parser )
67
+ parser: parser,
68
+ **kwargs )
73
69
 
74
70
  if block_given?
75
71
  begin
@@ -86,19 +82,17 @@ def self.foreach( path, headers: nil,
86
82
  end # method self.foreach
87
83
 
88
84
 
89
- def self.parse( data, headers: nil,
85
+ def self.parse( str_or_readable, headers: nil,
90
86
  sep: nil,
91
87
  converters: nil,
92
88
  header_converters: nil,
93
- width: nil,
94
- parser: nil, &block )
95
- csv = new( data,
89
+ parser: nil, **kwargs, &block )
90
+ csv = new( str_or_readable,
96
91
  headers: headers,
97
92
  sep: sep,
98
93
  converters: converters,
99
94
  header_converters: header_converters,
100
- width: width,
101
- parser: parser )
95
+ parser: parser, **kwargs )
102
96
 
103
97
  if block_given?
104
98
  csv.each( &block ) ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
@@ -111,24 +105,24 @@ end # method self.parse
111
105
 
112
106
 
113
107
 
114
- def initialize( data, headers: nil, sep: nil,
108
+ def initialize( str_or_readable, headers: nil, sep: nil,
115
109
  converters: nil,
116
110
  header_converters: nil,
117
- width: nil,
118
- parser: nil )
119
- raise ArgumentError.new( "Cannot parse nil as CSV" ) if data.nil?
111
+ parser: nil,
112
+ **kwargs )
113
+ raise ArgumentError.new( "Cannot parse nil as CSV" ) if str_or_readable.nil?
120
114
  ## todo: use (why? why not) - raise ArgumentError, "Cannot parse nil as CSV" if data.nil?
121
115
 
122
116
  # create the IO object we will read from
123
- @io = data.is_a?(String) ? StringIO.new(data) : data
117
+ @io = str_or_readable.is_a?(String) ? StringIO.new(str_or_readable) : str_or_readable
124
118
 
125
119
  ## pass in headers as array e.g. ['A', 'B', 'C']
126
120
  ## double check: run header_converters on passed in headers?
127
121
  ## for now - do NOT auto-convert passed in headers - keep them as-is (1:1)
128
122
  @names = headers ? headers : nil
129
123
 
130
- @sep = sep
131
- @width = width
124
+ @sep = sep
125
+ @kwargs = kwargs
132
126
 
133
127
  @converters = Converter.create_converters( converters )
134
128
  @header_converters = Converter.create_header_converters( header_converters )
@@ -170,7 +164,7 @@ def_delegators :@io,
170
164
  ## todo/fix: change sep keyword to "known" classes!!!!
171
165
  kwargs[:sep] = @sep if @sep && @parser.respond_to?( :'sep=' )
172
166
 
173
- kwargs[:width] = @width if @parser.is_a?( ParserFixed )
167
+ kwargs[:width] = @kwargs[:width] if @parser.is_a?( ParserFixed )
174
168
 
175
169
 
176
170
  @parser.parse( @io, kwargs ) do |raw_values| # sep: sep
@@ -6,7 +6,7 @@ class CsvReader ## note: uses a class for now - change to module - why? why no
6
6
  module Version
7
7
  MAJOR = 1 ## todo: namespace inside version or something - why? why not??
8
8
  MINOR = 1
9
- PATCH = 4
9
+ PATCH = 5
10
10
 
11
11
  ## self.to_s - why? why not?
12
12
  end
@@ -11,7 +11,7 @@ class TestParser < MiniTest::Test
11
11
 
12
12
 
13
13
  def parser
14
- parser = CsvReader::Parser::DEFAULT
14
+ CsvReader::Parser::DEFAULT
15
15
  end
16
16
 
17
17
 
@@ -11,7 +11,7 @@ class TestParserDirective < MiniTest::Test
11
11
 
12
12
 
13
13
  def parser
14
- parser = CsvReader::Parser::DEFAULT
14
+ CsvReader::Parser::DEFAULT
15
15
  end
16
16
 
17
17
 
@@ -11,7 +11,7 @@ class TestParserMeta < MiniTest::Test
11
11
 
12
12
 
13
13
  def parser
14
- parser = CsvReader::Parser::DEFAULT
14
+ CsvReader::Parser::DEFAULT
15
15
  end
16
16
 
17
17
 
@@ -11,7 +11,7 @@ class TestParserTab < MiniTest::Test
11
11
 
12
12
 
13
13
  def parser
14
- parser = CsvReader::Parser::TAB
14
+ CsvReader::Parser::TAB
15
15
  end
16
16
 
17
17
 
@@ -33,11 +33,12 @@ def test_parse
33
33
  end
34
34
 
35
35
  def test_parse_empties
36
- # note: trailing empty fields get (auto-)trimmed !!!!!!!
37
- assert_equal [[]], parser.parse( "\t\t" )
38
- assert_equal [[]], parser.parse( "\t\t\t\t" )
39
- assert_equal [["1"]], parser.parse( "1\t\t" )
40
- assert_equal [["1"]], parser.parse( "1\t\t\t\t" )
36
+ # note: trailing empty fields got (auto-)trimmed !!!!!!!;
37
+ # add missing -1 limit option :-) now works
38
+ assert_equal [["","",""]], parser.parse( "\t\t" )
39
+ assert_equal [["","","","",""]], parser.parse( "\t\t\t\t" )
40
+ assert_equal [["1","",""]], parser.parse( "1\t\t" )
41
+ assert_equal [["1","","","",""]], parser.parse( "1\t\t\t\t" )
41
42
  assert_equal [["","","3"]], parser.parse( "\t\t3" )
42
43
  assert_equal [["","","","","5"]], parser.parse( "\t\t\t\t5" )
43
44
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csvreader
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.5
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-27 00:00:00.000000000 Z
11
+ date: 2018-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc