csvreader 1.1.4 → 1.1.5

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: 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