csvlint 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|