csvlint 0.2.6 → 0.3.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 +8 -8
- data/.gitattributes +1 -1
- data/.gitignore +1 -1
- data/csvlint.gemspec +2 -0
- data/features/fixtures/w3.org/.well-known/csvm +4 -0
- data/features/step_definitions/validation_errors_steps.rb +1 -1
- data/features/support/earl_formatter.rb +66 -0
- data/features/support/load_tests.rb +20 -15
- data/lib/csvlint/csvw/column.rb +103 -55
- data/lib/csvlint/csvw/date_format.rb +49 -16
- data/lib/csvlint/csvw/number_format.rb +36 -21
- data/lib/csvlint/csvw/property_checker.rb +90 -45
- data/lib/csvlint/csvw/table.rb +57 -39
- data/lib/csvlint/csvw/table_group.rb +9 -9
- data/lib/csvlint/schema.rb +2 -2
- data/lib/csvlint/validate.rb +10 -13
- data/lib/csvlint/version.rb +1 -1
- data/spec/csvw/column_spec.rb +6 -6
- data/spec/csvw/date_format_spec.rb +10 -10
- data/spec/csvw/number_format_spec.rb +29 -0
- metadata +34 -2
@@ -20,22 +20,22 @@ module Csvlint
|
|
20
20
|
@warnings += @tables.map{|url,table| table.warnings}.flatten
|
21
21
|
end
|
22
22
|
|
23
|
-
def validate_header(header, table_url)
|
23
|
+
def validate_header(header, table_url, strict)
|
24
24
|
reset
|
25
25
|
table_url = "file:#{File.absolute_path(table_url)}" if table_url.instance_of? File
|
26
26
|
table = tables[table_url]
|
27
|
-
table.validate_header(header)
|
27
|
+
table.validate_header(header, strict)
|
28
28
|
@errors += table.errors
|
29
29
|
@warnings += table.warnings
|
30
30
|
return valid?
|
31
31
|
end
|
32
32
|
|
33
|
-
def validate_row(values, row=nil, all_errors=[], table_url)
|
33
|
+
def validate_row(values, row=nil, all_errors=[], table_url, validate)
|
34
34
|
reset
|
35
35
|
table_url = "file:#{File.absolute_path(table_url)}" if table_url.instance_of? File
|
36
36
|
@validated_tables[table_url] = true
|
37
37
|
table = tables[table_url]
|
38
|
-
table.validate_row(values, row)
|
38
|
+
table.validate_row(values, row, validate)
|
39
39
|
@errors += table.errors
|
40
40
|
@warnings += table.warnings
|
41
41
|
return valid?
|
@@ -93,10 +93,10 @@ module Csvlint
|
|
93
93
|
annotations[property] = v
|
94
94
|
elsif type == :common
|
95
95
|
common_properties[property] = v
|
96
|
-
elsif type == :
|
97
|
-
warnings << Csvlint::ErrorMessage.new(:invalid_property, :metadata, nil, nil, "#{property}", nil)
|
98
|
-
else
|
96
|
+
elsif type == :inherited
|
99
97
|
inherited_properties[property] = v
|
98
|
+
else
|
99
|
+
warnings << Csvlint::ErrorMessage.new(:invalid_property, :metadata, nil, nil, "#{property}", nil)
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
@@ -118,7 +118,7 @@ module Csvlint
|
|
118
118
|
end
|
119
119
|
table_url = URI.join(base_url, table_url).to_s
|
120
120
|
table_desc["url"] = table_url
|
121
|
-
table = Csvlint::Csvw::Table.from_json(table_desc, base_url, lang, inherited_properties)
|
121
|
+
table = Csvlint::Csvw::Table.from_json(table_desc, base_url, lang, common_properties, inherited_properties)
|
122
122
|
tables[table_url] = table
|
123
123
|
else
|
124
124
|
warnings << Csvlint::ErrorMessage.new(:invalid_table_description, :metadata, nil, nil, "#{table_desc}", nil)
|
@@ -154,7 +154,7 @@ module Csvlint
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
157
|
-
return self.new(base_url, id: id, tables: tables, notes:
|
157
|
+
return self.new(base_url, id: id, tables: tables, notes: common_properties["notes"] || [], annotations: annotations, warnings: warnings)
|
158
158
|
end
|
159
159
|
|
160
160
|
private
|
data/lib/csvlint/schema.rb
CHANGED
@@ -54,7 +54,7 @@ module Csvlint
|
|
54
54
|
|
55
55
|
end
|
56
56
|
|
57
|
-
def validate_header(header, source_url=nil)
|
57
|
+
def validate_header(header, source_url=nil, validate=true)
|
58
58
|
reset
|
59
59
|
|
60
60
|
found_header = header.to_csv(:row_sep => '')
|
@@ -65,7 +65,7 @@ module Csvlint
|
|
65
65
|
return valid?
|
66
66
|
end
|
67
67
|
|
68
|
-
def validate_row(values, row=nil, all_errors=[], source_url=nil)
|
68
|
+
def validate_row(values, row=nil, all_errors=[], source_url=nil, validate=true)
|
69
69
|
reset
|
70
70
|
if values.length < fields.length
|
71
71
|
fields[values.size..-1].each_with_index do |field, i|
|
data/lib/csvlint/validate.rb
CHANGED
@@ -68,6 +68,7 @@ module Csvlint
|
|
68
68
|
@csv_header = true
|
69
69
|
@headers = {}
|
70
70
|
@lambda = options[:lambda]
|
71
|
+
@validate = options[:validate].nil? ? true : options[:validate]
|
71
72
|
@leading = ""
|
72
73
|
|
73
74
|
@limit_lines = options[:limit_lines]
|
@@ -151,6 +152,7 @@ module Csvlint
|
|
151
152
|
end
|
152
153
|
rescue ArgumentError => ae
|
153
154
|
build_errors(:invalid_encoding, :structure, @current_line, nil, @current_line) unless @reported_invalid_encoding
|
155
|
+
@current_line = @current_line+1
|
154
156
|
@reported_invalid_encoding = true
|
155
157
|
end
|
156
158
|
|
@@ -181,7 +183,6 @@ module Csvlint
|
|
181
183
|
build_exception_messages(e, stream, current_line)
|
182
184
|
end
|
183
185
|
|
184
|
-
@data << row
|
185
186
|
if row
|
186
187
|
if current_line <= 1 && @csv_header
|
187
188
|
# this conditional should be refactored somewhere
|
@@ -195,7 +196,7 @@ module Csvlint
|
|
195
196
|
build_errors(:blank_rows, :structure, current_line, nil, stream.to_s) if row.reject { |c| c.nil? || c.empty? }.size == 0
|
196
197
|
# Builds errors and warnings related to the provided schema file
|
197
198
|
if @schema
|
198
|
-
@schema.validate_row(row, current_line, all_errors, @source)
|
199
|
+
@schema.validate_row(row, current_line, all_errors, @source, @validate)
|
199
200
|
@errors += @schema.errors
|
200
201
|
all_errors += @schema.errors
|
201
202
|
@warnings += @schema.warnings
|
@@ -204,6 +205,7 @@ module Csvlint
|
|
204
205
|
end
|
205
206
|
end
|
206
207
|
end
|
208
|
+
@data << row
|
207
209
|
end
|
208
210
|
|
209
211
|
def finish
|
@@ -214,7 +216,7 @@ module Csvlint
|
|
214
216
|
# return expected_columns to calling class
|
215
217
|
build_warnings(:check_options, :structure) if @expected_columns == 1
|
216
218
|
check_consistency
|
217
|
-
check_foreign_keys
|
219
|
+
check_foreign_keys if @validate
|
218
220
|
check_mixed_linebreaks
|
219
221
|
validate_encoding
|
220
222
|
end
|
@@ -250,7 +252,7 @@ module Csvlint
|
|
250
252
|
schema = Schema.load_from_json(url)
|
251
253
|
if schema.instance_of? Csvlint::Csvw::TableGroup
|
252
254
|
if schema.tables[@source_url]
|
253
|
-
|
255
|
+
@schema = schema
|
254
256
|
else
|
255
257
|
warn_if_unsuccessful = true
|
256
258
|
build_warnings(:schema_mismatch, :context, nil, nil, @source_url, schema)
|
@@ -293,6 +295,7 @@ module Csvlint
|
|
293
295
|
end
|
294
296
|
@dialect = {
|
295
297
|
"header" => true,
|
298
|
+
"headerRowCount" => 1,
|
296
299
|
"delimiter" => ",",
|
297
300
|
"skipInitialSpace" => true,
|
298
301
|
"lineTerminator" => :auto,
|
@@ -358,7 +361,7 @@ module Csvlint
|
|
358
361
|
end
|
359
362
|
end
|
360
363
|
if @schema
|
361
|
-
@schema.validate_header(header, @source)
|
364
|
+
@schema.validate_header(header, @source, @validate)
|
362
365
|
@errors += @schema.errors
|
363
366
|
@warnings += @schema.warnings
|
364
367
|
end
|
@@ -441,15 +444,11 @@ module Csvlint
|
|
441
444
|
@schema = nil
|
442
445
|
end
|
443
446
|
end
|
444
|
-
link_schema = nil
|
445
|
-
@schema = link_schema if link_schema
|
446
|
-
|
447
447
|
paths = []
|
448
448
|
if @source_url =~ /^http(s)?/
|
449
449
|
begin
|
450
450
|
well_known_uri = URI.join(@source_url, "/.well-known/csvm")
|
451
|
-
|
452
|
-
# TODO
|
451
|
+
paths = open(well_known_uri).read.split("\n")
|
453
452
|
rescue OpenURI::HTTPError, URI::BadURIError
|
454
453
|
end
|
455
454
|
end
|
@@ -464,6 +463,7 @@ module Csvlint
|
|
464
463
|
if schema.instance_of? Csvlint::Csvw::TableGroup
|
465
464
|
if schema.tables[@source_url]
|
466
465
|
@schema = schema
|
466
|
+
return
|
467
467
|
else
|
468
468
|
warn_if_unsuccessful = true
|
469
469
|
build_warnings(:schema_mismatch, :context, nil, nil, @source_url, schema)
|
@@ -472,9 +472,6 @@ module Csvlint
|
|
472
472
|
rescue Errno::ENOENT
|
473
473
|
rescue OpenURI::HTTPError, URI::BadURIError, ArgumentError
|
474
474
|
rescue => e
|
475
|
-
STDERR.puts e.class
|
476
|
-
STDERR.puts e.message
|
477
|
-
STDERR.puts e.backtrace
|
478
475
|
raise e
|
479
476
|
end
|
480
477
|
end
|
data/lib/csvlint/version.rb
CHANGED
data/spec/csvw/column_spec.rb
CHANGED
@@ -4,21 +4,21 @@ describe Csvlint::Csvw::Column do
|
|
4
4
|
|
5
5
|
it "shouldn't generate errors for string values" do
|
6
6
|
column = Csvlint::Csvw::Column.new(1, "foo")
|
7
|
-
|
8
|
-
expect(
|
7
|
+
value = column.validate("bar", 2)
|
8
|
+
expect(value).to eq("bar")
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should generate errors for string values that aren't long enough" do
|
12
12
|
column = Csvlint::Csvw::Column.new(1, "foo", datatype: { "base" => "http://www.w3.org/2001/XMLSchema#string", "minLength" => 4 })
|
13
|
-
|
14
|
-
expect(
|
13
|
+
value = column.validate("bar", 2)
|
14
|
+
expect(value).to eq({ :invalid => "bar" })
|
15
15
|
expect(column.errors.length).to eq(1)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "shouldn't generate errors for string values that are long enough" do
|
19
19
|
column = Csvlint::Csvw::Column.new(1, "foo", datatype: { "base" => "http://www.w3.org/2001/XMLSchema#string", "minLength" => 4 })
|
20
|
-
|
21
|
-
expect(
|
20
|
+
value = column.validate("barn", 2)
|
21
|
+
expect(value).to eq("barn")
|
22
22
|
expect(column.errors.length).to eq(0)
|
23
23
|
end
|
24
24
|
|
@@ -1,40 +1,40 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Csvlint::Csvw::
|
3
|
+
describe Csvlint::Csvw::DateFormat do
|
4
4
|
|
5
5
|
it "should parse dates that match yyyy-MM-dd correctly" do
|
6
6
|
format = Csvlint::Csvw::DateFormat.new("yyyy-MM-dd")
|
7
|
-
expect(format.parse("2015-03-22")).to eql(Date.new(2015, 3, 22))
|
7
|
+
expect(format.parse("2015-03-22")[:dateTime]).to eql(Date.new(2015, 3, 22))
|
8
8
|
expect(format.parse("2015-02-30")).to eql(nil)
|
9
9
|
expect(format.parse("22/03/2015")).to eq(nil)
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should parse times that match HH:mm:ss correctly" do
|
13
13
|
format = Csvlint::Csvw::DateFormat.new("HH:mm:ss")
|
14
|
-
expect(format.parse("12:34:56")).to eql({
|
14
|
+
expect(format.parse("12:34:56")).to eql({ :hour => 12, :minute => 34, :second => 56.0, :string => "12:34:56", :dateTime => DateTime.new(0,1,1,12,34,56.0,"+00:00") })
|
15
15
|
expect(format.parse("22/03/2015")).to eq(nil)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should parse times that match HH:mm:ss.SSS correctly" do
|
19
19
|
format = Csvlint::Csvw::DateFormat.new("HH:mm:ss.SSS")
|
20
|
-
expect(format.parse("12:34:56")).to eql({
|
21
|
-
expect(format.parse("12:34:56.78")).to eql({
|
22
|
-
expect(format.parse("12:34:56.789")).to eql({
|
20
|
+
expect(format.parse("12:34:56")).to eql({ :hour => 12, :minute => 34, :second => 56.0, :string => "12:34:56", :dateTime => DateTime.new(0,1,1,12,34,56.0,"+00:00") })
|
21
|
+
expect(format.parse("12:34:56.78")).to eql({ :hour => 12, :minute => 34, :second => 56.78, :string => "12:34:56.78", :dateTime => DateTime.new(0,1,1,12,34,56.78,"+00:00") })
|
22
|
+
expect(format.parse("12:34:56.789")).to eql({ :hour => 12, :minute => 34, :second => 56.789, :string => "12:34:56.789", :dateTime => DateTime.new(0,1,1,12,34,56.789,"+00:00") })
|
23
23
|
expect(format.parse("12:34:56.7890")).to eql(nil)
|
24
24
|
expect(format.parse("22/03/2015")).to eq(nil)
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should parse dateTimes that match yyyy-MM-ddTHH:mm:ss correctly" do
|
28
28
|
format = Csvlint::Csvw::DateFormat.new("yyyy-MM-ddTHH:mm:ss")
|
29
|
-
expect(format.parse("2015-03-15T15:02:37")).to eql(DateTime.new(2015, 3, 15, 15, 2, 37))
|
29
|
+
expect(format.parse("2015-03-15T15:02:37")[:dateTime]).to eql(DateTime.new(2015, 3, 15, 15, 2, 37))
|
30
30
|
expect(format.parse("12:34:56")).to eql(nil)
|
31
31
|
expect(format.parse("22/03/2015")).to eq(nil)
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should parse dateTimes that match yyyy-MM-ddTHH:mm:ss.S correctly" do
|
35
35
|
format = Csvlint::Csvw::DateFormat.new("yyyy-MM-ddTHH:mm:ss.S")
|
36
|
-
expect(format.parse("2015-03-15T15:02:37")).to eql(DateTime.new(2015, 3, 15, 15, 2, 37.0))
|
37
|
-
expect(format.parse("2015-03-15T15:02:37.4")).to eql(DateTime.new(2015, 3, 15, 15, 2, 37.4))
|
36
|
+
expect(format.parse("2015-03-15T15:02:37")[:dateTime]).to eql(DateTime.new(2015, 3, 15, 15, 2, 37.0))
|
37
|
+
expect(format.parse("2015-03-15T15:02:37.4")[:dateTime]).to eql(DateTime.new(2015, 3, 15, 15, 2, 37.4))
|
38
38
|
expect(format.parse("2015-03-15T15:02:37.45")).to eql(nil)
|
39
39
|
expect(format.parse("12:34:56")).to eql(nil)
|
40
40
|
expect(format.parse("22/03/2015")).to eq(nil)
|
@@ -43,7 +43,7 @@ describe Csvlint::Csvw::NumberFormat do
|
|
43
43
|
it "should parse dateTimes that match M/d/yyyy HH:mm correctly" do
|
44
44
|
format = Csvlint::Csvw::DateFormat.new("M/d/yyyy HH:mm")
|
45
45
|
expect(format.parse("2015-03-15T15:02:37")).to eql(nil)
|
46
|
-
expect(format.parse("3/15/2015 15:02")).to eql(DateTime.new(2015, 3, 15, 15, 2))
|
46
|
+
expect(format.parse("3/15/2015 15:02")[:dateTime]).to eql(DateTime.new(2015, 3, 15, 15, 2))
|
47
47
|
end
|
48
48
|
|
49
49
|
end
|
@@ -152,6 +152,7 @@ describe Csvlint::Csvw::NumberFormat do
|
|
152
152
|
|
153
153
|
it "should parse numbers that match ##0 correctly" do
|
154
154
|
format = Csvlint::Csvw::NumberFormat.new("##0")
|
155
|
+
expect(format.parse("-1")).to eql(-1)
|
155
156
|
expect(format.parse("1")).to eql(1)
|
156
157
|
expect(format.parse("12")).to eql(12)
|
157
158
|
expect(format.parse("123")).to eql(123)
|
@@ -380,6 +381,21 @@ describe Csvlint::Csvw::NumberFormat do
|
|
380
381
|
expect(format.parse("12.34E5")).to eql(12.34E5)
|
381
382
|
end
|
382
383
|
|
384
|
+
it "should parse numbers that match %000 correctly" do
|
385
|
+
format = Csvlint::Csvw::NumberFormat.new("%000")
|
386
|
+
expect(format.parse("%001")).to eq(0.01)
|
387
|
+
expect(format.parse("%012")).to eq(0.12)
|
388
|
+
expect(format.parse("%123")).to eq(1.23)
|
389
|
+
expect(format.parse("%1234")).to eq(12.34)
|
390
|
+
end
|
391
|
+
|
392
|
+
it "should parse numbers that match -0 correctly" do
|
393
|
+
format = Csvlint::Csvw::NumberFormat.new("-0")
|
394
|
+
expect(format.parse("1")).to eq(nil)
|
395
|
+
expect(format.parse("-1")).to eq(-1)
|
396
|
+
expect(format.parse("-12")).to eq(-12)
|
397
|
+
end
|
398
|
+
|
383
399
|
it "should parse numbers normally when there is no pattern" do
|
384
400
|
format = Csvlint::Csvw::NumberFormat.new()
|
385
401
|
expect(format.parse("1")).to eql(1)
|
@@ -414,4 +430,17 @@ describe Csvlint::Csvw::NumberFormat do
|
|
414
430
|
expect(format.parse("-INF")).to eql(-Float::INFINITY)
|
415
431
|
end
|
416
432
|
|
433
|
+
it "should parse numbers including decimal separators when they are specified" do
|
434
|
+
format = Csvlint::Csvw::NumberFormat.new(nil, " ", ",")
|
435
|
+
expect(format.parse("1")).to eql(1)
|
436
|
+
expect(format.parse("12,3")).to eql(12.3)
|
437
|
+
expect(format.parse("12,34")).to eql(12.34)
|
438
|
+
expect(format.parse("12,3E4")).to eql(12.3E4)
|
439
|
+
expect(format.parse("12,3E45")).to eql(12.3E45)
|
440
|
+
expect(format.parse("12,34E5")).to eql(12.34E5)
|
441
|
+
expect(format.parse("1 234")).to eql(1234)
|
442
|
+
expect(format.parse("1 234 567")).to eql(1234567)
|
443
|
+
expect(format.parse("1 234")).to eq(nil)
|
444
|
+
end
|
445
|
+
|
417
446
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csvlint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pezholio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mime-types
|
@@ -332,6 +332,34 @@ dependencies:
|
|
332
332
|
- - ! '>='
|
333
333
|
- !ruby/object:Gem::Version
|
334
334
|
version: '0'
|
335
|
+
- !ruby/object:Gem::Dependency
|
336
|
+
name: rdf
|
337
|
+
requirement: !ruby/object:Gem::Requirement
|
338
|
+
requirements:
|
339
|
+
- - ! '>='
|
340
|
+
- !ruby/object:Gem::Version
|
341
|
+
version: '0'
|
342
|
+
type: :development
|
343
|
+
prerelease: false
|
344
|
+
version_requirements: !ruby/object:Gem::Requirement
|
345
|
+
requirements:
|
346
|
+
- - ! '>='
|
347
|
+
- !ruby/object:Gem::Version
|
348
|
+
version: '0'
|
349
|
+
- !ruby/object:Gem::Dependency
|
350
|
+
name: rdf-turtle
|
351
|
+
requirement: !ruby/object:Gem::Requirement
|
352
|
+
requirements:
|
353
|
+
- - ! '>='
|
354
|
+
- !ruby/object:Gem::Version
|
355
|
+
version: '0'
|
356
|
+
type: :development
|
357
|
+
prerelease: false
|
358
|
+
version_requirements: !ruby/object:Gem::Requirement
|
359
|
+
requirements:
|
360
|
+
- - ! '>='
|
361
|
+
- !ruby/object:Gem::Version
|
362
|
+
version: '0'
|
335
363
|
description: CSV Validator
|
336
364
|
email:
|
337
365
|
- pezholio@gmail.com
|
@@ -371,6 +399,7 @@ files:
|
|
371
399
|
- features/fixtures/title-row.csv
|
372
400
|
- features/fixtures/valid.csv
|
373
401
|
- features/fixtures/valid_many_rows.csv
|
402
|
+
- features/fixtures/w3.org/.well-known/csvm
|
374
403
|
- features/fixtures/windows-line-endings.csv
|
375
404
|
- features/information.feature
|
376
405
|
- features/parse_csv.feature
|
@@ -386,6 +415,7 @@ files:
|
|
386
415
|
- features/step_definitions/validation_info_steps.rb
|
387
416
|
- features/step_definitions/validation_warnings_steps.rb
|
388
417
|
- features/support/aruba.rb
|
418
|
+
- features/support/earl_formatter.rb
|
389
419
|
- features/support/env.rb
|
390
420
|
- features/support/load_tests.rb
|
391
421
|
- features/support/webmock.rb
|
@@ -458,6 +488,7 @@ test_files:
|
|
458
488
|
- features/fixtures/title-row.csv
|
459
489
|
- features/fixtures/valid.csv
|
460
490
|
- features/fixtures/valid_many_rows.csv
|
491
|
+
- features/fixtures/w3.org/.well-known/csvm
|
461
492
|
- features/fixtures/windows-line-endings.csv
|
462
493
|
- features/information.feature
|
463
494
|
- features/parse_csv.feature
|
@@ -473,6 +504,7 @@ test_files:
|
|
473
504
|
- features/step_definitions/validation_info_steps.rb
|
474
505
|
- features/step_definitions/validation_warnings_steps.rb
|
475
506
|
- features/support/aruba.rb
|
507
|
+
- features/support/earl_formatter.rb
|
476
508
|
- features/support/env.rb
|
477
509
|
- features/support/load_tests.rb
|
478
510
|
- features/support/webmock.rb
|