csvlint 0.1.1 → 0.1.2
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/README.md +1 -1
- data/lib/csvlint/field.rb +6 -2
- data/lib/csvlint/schema.rb +6 -2
- data/lib/csvlint/version.rb +1 -1
- data/spec/field_spec.rb +54 -49
- data/spec/schema_spec.rb +41 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjUyMGZlNGIyNjM4ZmU1OGVjMDc3Y2U2YmQ0NWEzMzM3ZGFkYzA0Yw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzYzMjUxY2NlZmE4ODY3NjYwNTU4NzUyMmE2NTU0NjM1MmQ0YzI4NQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODQwMGQzMjY4NGQzNGY5ZGY1Nzg3ODc5MDI3M2E3NmNmNzUwNzU1MzBjNjNk
|
10
|
+
YzRiMjE3NTJlNTc5YWI2NjhkNGJjNDcxNzVkMDgyZmRkYjZlYWFmZjUyOWQx
|
11
|
+
ZmVkOWRjZDJhMGU4M2QyYmI0YzZmMDBlYWRhMjFmNGFlZmJmZTg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZjhkODBhMWU1ODFjN2JiNjQ3ZjBlZmFkNzAwMmVhOTNiYzgwNDNjM2RjODg5
|
14
|
+
YWE2NGUwNjk1M2JlYWFjZmVlY2U0YjNmMTZmM2U4YTFlMDcyMGViNWU3NWY2
|
15
|
+
NTY5NmIyNmE5ZjYwNDkwOTE1NjQ2MWRiZGU0ZGRhM2MxMTEyYjU=
|
data/README.md
CHANGED
@@ -221,7 +221,7 @@ Schema validation provides some additional types of error and warning messages:
|
|
221
221
|
* `:min_length` (error) -- a column with a `minLength` constraint has a value that is too short
|
222
222
|
* `:max_length` (error) -- a column with a `maxLength` constraint has a value that is too long
|
223
223
|
* `:pattern` (error) -- a column with a `pattern` constraint has a value that doesn't match the regular expression
|
224
|
-
* `:
|
224
|
+
* `:malformed_header` (warning) -- the header in the CSV doesn't match the schema
|
225
225
|
* `:missing_column` (warning) -- a row in the CSV file has a missing column, that is specified in the schema. This is a warning only, as it may be legitimate
|
226
226
|
* `:extra_column` (warning) -- a row in the CSV file has extra column.
|
227
227
|
* `:unique` (error) -- a column with a `unique` constraint contains non-unique values
|
data/lib/csvlint/field.rb
CHANGED
@@ -105,8 +105,12 @@ module Csvlint
|
|
105
105
|
'http://www.w3.org/2001/XMLSchema#float' => lambda { |value, constraints| Float value },
|
106
106
|
'http://www.w3.org/2001/XMLSchema#double' => lambda { |value, constraints| Float value },
|
107
107
|
'http://www.w3.org/2001/XMLSchema#anyURI' => lambda do |value, constraints|
|
108
|
-
|
109
|
-
|
108
|
+
begin
|
109
|
+
u = URI.parse value
|
110
|
+
raise ArgumentError unless u.kind_of?(URI::HTTP) || u.kind_of?(URI::HTTPS)
|
111
|
+
rescue URI::InvalidURIError
|
112
|
+
raise ArgumentError
|
113
|
+
end
|
110
114
|
u
|
111
115
|
end,
|
112
116
|
'http://www.w3.org/2001/XMLSchema#boolean' => lambda do |value, constraints|
|
data/lib/csvlint/schema.rb
CHANGED
@@ -16,9 +16,13 @@ module Csvlint
|
|
16
16
|
|
17
17
|
def validate_header(header)
|
18
18
|
reset
|
19
|
-
|
20
|
-
|
19
|
+
|
20
|
+
found_header = header.join(',')
|
21
|
+
expected_header = @fields.map{ |f| f.name }.join(',')
|
22
|
+
if found_header != expected_header
|
23
|
+
build_warnings(:malformed_header, :schema, 1, nil, found_header, expected_header)
|
21
24
|
end
|
25
|
+
|
22
26
|
return valid?
|
23
27
|
end
|
24
28
|
|
data/lib/csvlint/version.rb
CHANGED
data/spec/field_spec.rb
CHANGED
@@ -1,45 +1,45 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Csvlint::Field do
|
4
|
-
|
4
|
+
|
5
5
|
it "should validate required fields" do
|
6
6
|
field = Csvlint::Field.new("test", { "required" => true } )
|
7
|
-
expect( field.validate_column( nil ) ).to be(false)
|
7
|
+
expect( field.validate_column( nil ) ).to be(false)
|
8
8
|
expect( field.errors.first.category ).to be(:schema)
|
9
9
|
expect( field.validate_column( "" ) ).to be(false)
|
10
10
|
expect( field.validate_column( "data" ) ).to be(true)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
it "should include the failed constraints" do
|
14
14
|
field = Csvlint::Field.new("test", { "required" => true } )
|
15
|
-
expect( field.validate_column( nil ) ).to be(false)
|
15
|
+
expect( field.validate_column( nil ) ).to be(false)
|
16
16
|
expect( field.errors.first.constraints ).to eql( { "required" => true } )
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
it "should validate minimum length" do
|
20
20
|
field = Csvlint::Field.new("test", { "minLength" => 3 } )
|
21
21
|
expect( field.validate_column( nil ) ).to be(false)
|
22
|
-
expect( field.validate_column( "" ) ).to be(false)
|
22
|
+
expect( field.validate_column( "" ) ).to be(false)
|
23
23
|
expect( field.validate_column( "ab" ) ).to be(false)
|
24
24
|
expect( field.validate_column( "abc" ) ).to be(true)
|
25
|
-
expect( field.validate_column( "abcd" ) ).to be(true)
|
25
|
+
expect( field.validate_column( "abcd" ) ).to be(true)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
it "should validate maximum length" do
|
29
29
|
field = Csvlint::Field.new("test", { "maxLength" => 3 } )
|
30
30
|
expect( field.validate_column( nil ) ).to be(true)
|
31
|
-
expect( field.validate_column( "" ) ).to be(true)
|
31
|
+
expect( field.validate_column( "" ) ).to be(true)
|
32
32
|
expect( field.validate_column( "ab" ) ).to be(true)
|
33
33
|
expect( field.validate_column( "abc" ) ).to be(true)
|
34
34
|
expect( field.validate_column( "abcd" ) ).to be(false)
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
it "should validate against regex" do
|
38
38
|
field = Csvlint::Field.new("test", { "pattern" => "\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\}"} )
|
39
39
|
expect( field.validate_column( "abc") ).to be(false)
|
40
|
-
expect( field.validate_column( "{3B0DA29C-C89A-4FAA-918A-0000074FA0E0}") ).to be(true)
|
40
|
+
expect( field.validate_column( "{3B0DA29C-C89A-4FAA-918A-0000074FA0E0}") ).to be(true)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
it "should apply combinations of constraints" do
|
44
44
|
field = Csvlint::Field.new("test", { "required"=>true, "pattern" => "\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\}"} )
|
45
45
|
expect( field.validate_column( "abc") ).to be(false)
|
@@ -47,9 +47,9 @@ describe Csvlint::Field do
|
|
47
47
|
|
48
48
|
expect( field.validate_column( nil ) ).to be(false)
|
49
49
|
expect( field.errors.first.constraints ).to eql( { "required"=>true } )
|
50
|
-
|
51
|
-
expect( field.validate_column( "{3B0DA29C-C89A-4FAA-918A-0000074FA0E0}") ).to be(true)
|
52
|
-
|
50
|
+
|
51
|
+
expect( field.validate_column( "{3B0DA29C-C89A-4FAA-918A-0000074FA0E0}") ).to be(true)
|
52
|
+
|
53
53
|
end
|
54
54
|
|
55
55
|
it "should enforce uniqueness for a column" do
|
@@ -65,13 +65,13 @@ describe Csvlint::Field do
|
|
65
65
|
field = Csvlint::Field.new("test", { "type" => "http://www.w3.org/2001/XMLSchema#int" })
|
66
66
|
expect( field.validate_column("")).to be(true)
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
it "validates strings" do
|
70
70
|
field = Csvlint::Field.new("test", { "type" => "http://www.w3.org/2001/XMLSchema#string" })
|
71
71
|
expect( field.validate_column("42")).to be(true)
|
72
72
|
expect( field.validate_column("forty-two")).to be(true)
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
it "validates ints" do
|
76
76
|
field = Csvlint::Field.new("test", { "type" => "http://www.w3.org/2001/XMLSchema#int" })
|
77
77
|
expect( field.validate_column("42")).to be(true)
|
@@ -82,7 +82,7 @@ describe Csvlint::Field do
|
|
82
82
|
field = Csvlint::Field.new("test", { "type" => "http://www.w3.org/2001/XMLSchema#integer" })
|
83
83
|
expect( field.validate_column("42")).to be(true)
|
84
84
|
expect( field.validate_column("forty-two")).to be(false)
|
85
|
-
end
|
85
|
+
end
|
86
86
|
|
87
87
|
it "validates floats" do
|
88
88
|
field = Csvlint::Field.new("test", { "type" => "http://www.w3.org/2001/XMLSchema#float" })
|
@@ -98,6 +98,11 @@ describe Csvlint::Field do
|
|
98
98
|
expect(field.validate_column("42.0")).to be(false)
|
99
99
|
end
|
100
100
|
|
101
|
+
it "works with invalid URIs" do
|
102
|
+
field = Csvlint::Field.new("test", { "type" => "http://www.w3.org/2001/XMLSchema#anyURI" })
|
103
|
+
expect(field.validate_column("£123")).to be(false)
|
104
|
+
end
|
105
|
+
|
101
106
|
it "validates booleans" do
|
102
107
|
field = Csvlint::Field.new("test", { "type" => "http://www.w3.org/2001/XMLSchema#boolean" })
|
103
108
|
expect(field.validate_column("true")).to be(true)
|
@@ -137,111 +142,111 @@ describe Csvlint::Field do
|
|
137
142
|
expect(field.validate_column("1")).to be(true)
|
138
143
|
end
|
139
144
|
end
|
140
|
-
|
145
|
+
|
141
146
|
context "when validating ranges" do
|
142
|
-
|
147
|
+
|
143
148
|
it "should enforce minimum values" do
|
144
|
-
field = Csvlint::Field.new("test", {
|
149
|
+
field = Csvlint::Field.new("test", {
|
145
150
|
"type" => "http://www.w3.org/2001/XMLSchema#int",
|
146
151
|
"minimum" => "40"
|
147
152
|
})
|
148
153
|
expect( field.validate_column("42")).to be(true)
|
149
154
|
|
150
|
-
field = Csvlint::Field.new("test", {
|
155
|
+
field = Csvlint::Field.new("test", {
|
151
156
|
"type" => "http://www.w3.org/2001/XMLSchema#int",
|
152
157
|
"minimum" => "40"
|
153
158
|
})
|
154
|
-
expect( field.validate_column("39")).to be(false)
|
159
|
+
expect( field.validate_column("39")).to be(false)
|
155
160
|
expect( field.errors.first.type ).to eql(:below_minimum)
|
156
161
|
end
|
157
|
-
|
162
|
+
|
158
163
|
it "should enforce maximum values" do
|
159
|
-
field = Csvlint::Field.new("test", {
|
164
|
+
field = Csvlint::Field.new("test", {
|
160
165
|
"type" => "http://www.w3.org/2001/XMLSchema#int",
|
161
166
|
"maximum" => "40"
|
162
167
|
})
|
163
168
|
expect( field.validate_column("39")).to be(true)
|
164
169
|
|
165
|
-
field = Csvlint::Field.new("test", {
|
170
|
+
field = Csvlint::Field.new("test", {
|
166
171
|
"type" => "http://www.w3.org/2001/XMLSchema#int",
|
167
172
|
"maximum" => "40"
|
168
173
|
})
|
169
|
-
expect( field.validate_column("41")).to be(false)
|
174
|
+
expect( field.validate_column("41")).to be(false)
|
170
175
|
expect( field.errors.first.type ).to eql(:above_maximum)
|
171
176
|
|
172
|
-
end
|
177
|
+
end
|
173
178
|
end
|
174
|
-
|
179
|
+
|
175
180
|
context "when validating dates" do
|
176
181
|
it "should validate a date time" do
|
177
|
-
field = Csvlint::Field.new("test", {
|
182
|
+
field = Csvlint::Field.new("test", {
|
178
183
|
"type" => "http://www.w3.org/2001/XMLSchema#dateTime"
|
179
184
|
})
|
180
185
|
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(true)
|
181
186
|
expect( field.validate_column("invalid-date")).to be(false)
|
182
|
-
expect( field.validate_column("2014-02-17")).to be(false)
|
187
|
+
expect( field.validate_column("2014-02-17")).to be(false)
|
183
188
|
end
|
184
189
|
it "should validate a date" do
|
185
|
-
field = Csvlint::Field.new("test", {
|
190
|
+
field = Csvlint::Field.new("test", {
|
186
191
|
"type" => "http://www.w3.org/2001/XMLSchema#date"
|
187
192
|
})
|
188
193
|
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(false)
|
189
194
|
expect( field.validate_column("invalid-date")).to be(false)
|
190
|
-
expect( field.validate_column("2014-02-17")).to be(true)
|
195
|
+
expect( field.validate_column("2014-02-17")).to be(true)
|
191
196
|
end
|
192
197
|
it "should validate a time" do
|
193
|
-
field = Csvlint::Field.new("test", {
|
198
|
+
field = Csvlint::Field.new("test", {
|
194
199
|
"type" => "http://www.w3.org/2001/XMLSchema#time"
|
195
200
|
})
|
196
201
|
expect( field.validate_column("11:09:00")).to be(true)
|
197
202
|
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(false)
|
198
|
-
expect( field.validate_column("not-a-time")).to be(false)
|
199
|
-
expect( field.validate_column("27:97:00")).to be(false)
|
203
|
+
expect( field.validate_column("not-a-time")).to be(false)
|
204
|
+
expect( field.validate_column("27:97:00")).to be(false)
|
200
205
|
end
|
201
206
|
it "should validate a year" do
|
202
|
-
field = Csvlint::Field.new("test", {
|
207
|
+
field = Csvlint::Field.new("test", {
|
203
208
|
"type" => "http://www.w3.org/2001/XMLSchema#gYear"
|
204
209
|
})
|
205
210
|
expect( field.validate_column("1999")).to be(true)
|
206
211
|
expect( field.validate_column("2525")).to be(true)
|
207
212
|
expect( field.validate_column("0001")).to be(true)
|
208
213
|
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(false)
|
209
|
-
expect( field.validate_column("not-a-time")).to be(false)
|
210
|
-
expect( field.validate_column("27:97:00")).to be(false)
|
214
|
+
expect( field.validate_column("not-a-time")).to be(false)
|
215
|
+
expect( field.validate_column("27:97:00")).to be(false)
|
211
216
|
end
|
212
217
|
it "should validate a year-month" do
|
213
|
-
field = Csvlint::Field.new("test", {
|
218
|
+
field = Csvlint::Field.new("test", {
|
214
219
|
"type" => "http://www.w3.org/2001/XMLSchema#gYearMonth"
|
215
220
|
})
|
216
221
|
expect( field.validate_column("1999-12")).to be(true)
|
217
222
|
expect( field.validate_column("2525-01")).to be(true)
|
218
223
|
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(false)
|
219
|
-
expect( field.validate_column("not-a-time")).to be(false)
|
220
|
-
expect( field.validate_column("27:97:00")).to be(false)
|
224
|
+
expect( field.validate_column("not-a-time")).to be(false)
|
225
|
+
expect( field.validate_column("27:97:00")).to be(false)
|
221
226
|
end
|
222
227
|
it "should allow user to specify custom date time pattern" do
|
223
|
-
field = Csvlint::Field.new("test", {
|
228
|
+
field = Csvlint::Field.new("test", {
|
224
229
|
"type" => "http://www.w3.org/2001/XMLSchema#dateTime",
|
225
230
|
"datePattern" => "%Y-%m-%d %H:%M:%S"
|
226
231
|
})
|
227
232
|
expect( field.validate_column("1999-12-01 10:00:00")).to be(true)
|
228
233
|
expect( field.validate_column("invalid-date")).to be(false)
|
229
|
-
expect( field.validate_column("2014-02-17")).to be(false)
|
230
|
-
expect( field.errors.first.constraints ).to eql( {
|
234
|
+
expect( field.validate_column("2014-02-17")).to be(false)
|
235
|
+
expect( field.errors.first.constraints ).to eql( {
|
231
236
|
"type" => "http://www.w3.org/2001/XMLSchema#dateTime",
|
232
237
|
"datePattern" => "%Y-%m-%d %H:%M:%S"
|
233
238
|
})
|
234
|
-
|
239
|
+
|
235
240
|
end
|
236
241
|
it "should allow user to compare dates" do
|
237
|
-
field = Csvlint::Field.new("test", {
|
242
|
+
field = Csvlint::Field.new("test", {
|
238
243
|
"type" => "http://www.w3.org/2001/XMLSchema#dateTime",
|
239
244
|
"datePattern" => "%Y-%m-%d %H:%M:%S",
|
240
245
|
"minimum" => "1990-01-01 10:00:00"
|
241
246
|
})
|
242
247
|
expect( field.validate_column("1999-12-01 10:00:00")).to be(true)
|
243
|
-
expect( field.validate_column("1989-12-01 10:00:00")).to be(false)
|
248
|
+
expect( field.validate_column("1989-12-01 10:00:00")).to be(false)
|
244
249
|
end
|
245
250
|
end
|
246
251
|
end
|
247
|
-
end
|
252
|
+
end
|
data/spec/schema_spec.rb
CHANGED
@@ -94,16 +94,50 @@ describe Csvlint::Schema do
|
|
94
94
|
|
95
95
|
expect( schema.validate_header(["wrong", "required"]) ).to eql(true)
|
96
96
|
expect( schema.warnings.size ).to eql(1)
|
97
|
-
expect( schema.warnings.first.
|
98
|
-
expect( schema.warnings.first.
|
99
|
-
expect( schema.warnings.first.
|
100
|
-
expect( schema.warnings.first.
|
101
|
-
|
97
|
+
expect( schema.warnings.first.row ).to eql(1)
|
98
|
+
expect( schema.warnings.first.type ).to eql(:malformed_header)
|
99
|
+
expect( schema.warnings.first.content ).to eql('wrong,required')
|
100
|
+
expect( schema.warnings.first.column ).to eql(nil)
|
101
|
+
expect( schema.warnings.first.category ).to eql(:schema)
|
102
|
+
expect( schema.warnings.first.constraints ).to eql('minimum,required')
|
103
|
+
|
102
104
|
expect( schema.validate_header(["minimum", "Required"]) ).to eql(true)
|
103
105
|
expect( schema.warnings.size ).to eql(1)
|
104
106
|
|
105
|
-
end
|
106
|
-
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should warn if column count is less than field count" do
|
110
|
+
minimum = Csvlint::Field.new("minimum", { "minLength" => 3 } )
|
111
|
+
required = Csvlint::Field.new("required", { "required" => true } )
|
112
|
+
schema = Csvlint::Schema.new("http://example.org", [minimum, required] )
|
113
|
+
|
114
|
+
expect( schema.validate_header(["minimum"]) ).to eql(true)
|
115
|
+
expect( schema.warnings.size ).to eql(1)
|
116
|
+
expect( schema.warnings.first.row ).to eql(1)
|
117
|
+
expect( schema.warnings.first.type ).to eql(:malformed_header)
|
118
|
+
expect( schema.warnings.first.content ).to eql("minimum")
|
119
|
+
expect( schema.warnings.first.column ).to eql(nil)
|
120
|
+
expect( schema.warnings.first.category ).to eql(:schema)
|
121
|
+
expect( schema.warnings.first.constraints ).to eql('minimum,required')
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should warn if column count is more than field count" do
|
126
|
+
minimum = Csvlint::Field.new("minimum", { "minLength" => 3 } )
|
127
|
+
schema = Csvlint::Schema.new("http://example.org", [minimum] )
|
128
|
+
|
129
|
+
expect( schema.validate_header(["wrong", "required"]) ).to eql(true)
|
130
|
+
expect( schema.warnings.size ).to eql(1)
|
131
|
+
expect( schema.warnings.first.row ).to eql(1)
|
132
|
+
expect( schema.warnings.first.type ).to eql(:malformed_header)
|
133
|
+
expect( schema.warnings.first.content ).to eql("wrong,required")
|
134
|
+
expect( schema.warnings.first.column ).to eql(nil)
|
135
|
+
expect( schema.warnings.first.category ).to eql(:schema)
|
136
|
+
expect( schema.warnings.first.constraints ).to eql('minimum')
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
107
141
|
|
108
142
|
context "when parsing JSON Tables" do
|
109
143
|
|
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.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pezholio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mime-types
|