Skip to content

Commit

Permalink
Handle case where import files are empty
Browse files Browse the repository at this point in the history
  • Loading branch information
DevChima committed Feb 17, 2025
1 parent c3270af commit 10bd8b2
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 32 deletions.
26 changes: 15 additions & 11 deletions home/import_assessments.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,20 +106,24 @@ def parse_file(self) -> list["AssessmentRow"]:
c. Validates that the snake_case headers contain all mandatory headers.
d. Transforms each row to use snake_case headers.
"""

row_iterator = parse_file(self.file_content, self.file_type)
rows = [row for _, row in row_iterator]

if rows:
original_headers = rows[0].keys()
headers_mapping = {
header: self.to_snake_case(header) for header in original_headers
}
snake_case_headers = list(headers_mapping.values())
self.validate_headers(snake_case_headers, MANDATORY_HEADERS, row_num=1)
transformed_rows = [
{headers_mapping[key]: value for key, value in row.items()}
for row in rows
]
if not rows:
raise ImportAssessmentException(
"The import file is empty or contains no valid rows.", row_num=1
)

original_headers = rows[0].keys()
headers_mapping = {
header: self.to_snake_case(header) for header in original_headers
}
snake_case_headers = list(headers_mapping.values())
self.validate_headers(snake_case_headers, MANDATORY_HEADERS, row_num=1)
transformed_rows = [
{headers_mapping[key]: value for key, value in row.items()} for row in rows
]

return [
AssessmentRow.from_flat(row, i + 2)
Expand Down
6 changes: 5 additions & 1 deletion home/import_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,11 @@ def fix_rows(rows: Iterator[dict[str | Any, Any]]) -> Iterator[dict[str, str | N
"""
Fix keys for all rows by lowercasing keys and removing whitespace from keys and values
"""
first_row = next(rows)
try:
first_row = next(rows)
except StopIteration:
return iter([])

if len(first_row) != len(fix_row(first_row)):
raise ImportException(
"Invalid format. Please check that there are no duplicate headers."
Expand Down
1 change: 1 addition & 0 deletions home/tests/import-export-data/empty.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

49 changes: 29 additions & 20 deletions home/tests/test_assessment_import_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ def test_single_assessment(self, impexp: ImportExport) -> None:

def test_snake_case_assessments(self, csv_impexp: ImportExport) -> None:
"""
Importing a csv with spaces in header names and uppercase text should be coverted to snake case
Importing a csv with spaces in header names and uppercase text should be converted to snake case
and pass, provided that the converted text are valid cms headers.
Here we check that the headers are changed to snake case, the assessment is saved
and finally we check that the saved assessment has the correct headers.
Expand All @@ -440,25 +440,24 @@ def test_snake_case_assessments(self, csv_impexp: ImportExport) -> None:
assessment_model = Assessment
model_fields = [field.name for field in assessment_model._meta.get_fields()]

expected_fields = {
"title": True,
"slug": True,
"high_inflection": True,
"medium_inflection": True,
"high_result_page": True,
"medium_result_page": True,
"low_result_page": True,
"skip_high_result_page": True,
"skip_threshold": True,
"generic_error": True,
"questions": True,
}

for field_name, should_exist in expected_fields.items():
if should_exist:
assert (
field_name in model_fields
), f"Field '{field_name}' not found in Assessment model."
expected_fields = [
"title",
"slug",
"high_inflection",
"medium_inflection",
"high_result_page",
"medium_result_page",
"low_result_page",
"skip_high_result_page",
"skip_threshold",
"generic_error",
"questions",
]

for field_name in expected_fields:
assert (
field_name in model_fields
), f"Field '{field_name}' not found in Assessment model."


@pytest.mark.usefixtures("result_content_pages")
Expand Down Expand Up @@ -702,6 +701,16 @@ def test_missing_generic_error(self, csv_impexp: ImportExport) -> None:
)
assert e.value.row_num == 2

def test_empty_rows(self, csv_impexp: ImportExport) -> None:
"""
Importing an empty CSV should return an error that the
import file has no rows.
"""
with pytest.raises(ImportAssessmentException) as e:
csv_impexp.import_file("empty.csv")
assert e.value.message == "The import file is empty or contains no valid rows."
assert e.value.row_num == 1


@pytest.mark.usefixtures("result_content_pages")
@pytest.mark.django_db()
Expand Down

0 comments on commit 10bd8b2

Please sign in to comment.