Skip to content

Commit

Permalink
Merge pull request #132 from theodi/invalid-schema
Browse files Browse the repository at this point in the history
Invalid schema
  • Loading branch information
pezholio committed Jul 24, 2015
2 parents 7a671eb + 3c2cfe0 commit 9dc91dc
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 10 deletions.
2 changes: 2 additions & 0 deletions features/schema_validation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Feature: Schema Validation
Scenario: Schema with valid regex
Given I have a CSV with the following content:
"""
"firstname","id","email"
"Bob","1234","[email protected]"
"Alice","5","[email protected]"
"""
Expand All @@ -84,6 +85,7 @@ Feature: Schema Validation
Scenario: Schema with invalid regex
Given I have a CSV with the following content:
"""
"firstname","id","email"
"Bob","1234","[email protected]"
"Alice","5","[email protected]"
"""
Expand Down
20 changes: 13 additions & 7 deletions lib/csvlint/field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ def initialize(name, constraints={}, title=nil, description=nil)
reset
end

def validate_column(value, row=nil, column=nil)
def validate_column(value, row=nil, column=nil, all_errors=[])
reset
unless all_errors.any?{|error| ((error.type == :invalid_regex) && (error.column == column))}
validate_regex(value, row, column)
end
validate_length(value, row, column)
validate_values(value, row, column)
parsed = validate_type(value, row, column)
Expand All @@ -39,22 +42,25 @@ def validate_length(value, row, column)
end
end

def validate_values(value, row, column)
# If a pattern exists, raise an invalid regex error if it is not in
# valid regex form, else, if the value of the relevant field in the csv
# does not match the given regex pattern in the schema, raise a
# pattern error.
def validate_regex(value, row, column)
pattern = constraints["pattern"]
if pattern
begin
Regexp.new(pattern)
build_errors(:pattern, :schema, row, column, value,
{ "pattern" => constraints["pattern"] } ) if !value.nil? && !value.match( constraints["pattern"] )
rescue RegexpError
build_errors(:invalid_regex, :schema, row, column, value,
build_errors(:invalid_regex, :schema, nil, column, ("#{name}: Constraints: Pattern: #{pattern}"),
{ "pattern" => constraints["pattern"] })
end
end
end

def validate_values(value, row, column)
# If a pattern exists, raise an invalid regex error if it is not in
# valid regex form, else, if the value of the relevant field in the csv
# does not match the given regex pattern in the schema, raise a
# pattern error.
if constraints["unique"] == true
if @uniques.include? value
build_errors(:unique, :schema, row, column, value, { "unique" => true })
Expand Down
4 changes: 2 additions & 2 deletions lib/csvlint/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def validate_header(header)
return valid?
end

def validate_row(values, row=nil)
def validate_row(values, row=nil, all_errors=[])
reset
if values.length < fields.length
fields[values.size..-1].each_with_index do |field, i|
Expand All @@ -41,7 +41,7 @@ def validate_row(values, row=nil)

fields.each_with_index do |field,i|
value = values[i] || ""
result = field.validate_column(value, row, i+1)
result = field.validate_column(value, row, i+1, all_errors)
@errors += fields[i].errors
@warnings += fields[i].warnings
end
Expand Down
4 changes: 3 additions & 1 deletion lib/csvlint/validate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def parse_csv(io)
@expected_columns = 0
current_line = 0
reported_invalid_encoding = false
all_errors = []
@col_counts = []

@csv_options[:encoding] = @encoding
Expand Down Expand Up @@ -133,8 +134,9 @@ def parse_csv(io)
build_errors(:blank_rows, :structure, current_line, nil, wrapper.line) if row.reject{ |c| c.nil? || c.empty? }.size == 0
# Builds errors and warnings related to the provided schema file
if @schema
@schema.validate_row(row, current_line)
@schema.validate_row(row, current_line, all_errors)
@errors += @schema.errors
all_errors += @schema.errors
@warnings += @schema.warnings
else
build_errors(:ragged_rows, :structure, current_line, nil, wrapper.line) if !row.empty? && row.size != @expected_columns
Expand Down

0 comments on commit 9dc91dc

Please sign in to comment.