Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change log

### 0.2.11

- Fixed [BUG-2065](https://dev.azure.com/TDEI-UW/TDEI/_workitems/edit/2065/)
- Added functionality to catch serialization errors
- Added unit test cases for that
- Added test file `test_serialization_error.zip` to test the serialization error

### 0.2.10

- Added limit the message error when u_id and v_id are missing
Expand Down
22 changes: 20 additions & 2 deletions src/python_osw_validation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,30 @@ def validate(self, max_errors=20) -> ValidationResult:
# Validate OSW external extensions
for file in validator.externalExtensions:
file_path = os.path.join(file)
file_name = os.path.basename(file)
extensionFile = gpd.read_file(file_path)
invalid_geojson = extensionFile[extensionFile.is_valid == False]
is_valid = len(invalid_geojson) == 0
if not is_valid:
self.errors.append(
f"Invalid geometries found in extension file {file}, list of invalid geometries: {invalid_geojson.to_json()}")
try:
# Safely extract invalid _id or fallback to index if _id is missing
invalid_ids = list(set(invalid_geojson.get('_id', invalid_geojson.index)))
num_invalid = len(invalid_ids)
limit = min(num_invalid, 20)
displayed_invalid = ', '.join(map(str, invalid_ids[:limit]))
self.errors.append(
f"Invalid geometries found in extension file `{file_name}`. Showing {limit if num_invalid > 20 else 'all'} of {num_invalid} invalid geometry IDs: {displayed_invalid}"
)
except Exception as e:
self.errors.append(f"Invalid features found in `{file_name}`, but failed to extract IDs: {e}")

# Optional: Test serializability of extension file
try:
for idx, row in extensionFile.drop(columns='geometry').iterrows():
json.dumps(row.to_dict())
except Exception as e:
self.errors.append(f"Extension file `{file_name}` has non-serializable properties: {e}")
break

if self.errors:
return ValidationResult(False, self.errors)
Expand Down
2 changes: 1 addition & 1 deletion src/python_osw_validation/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.2.10'
__version__ = '0.2.11'
Binary file added tests/assets/test_serialization_error.zip
Binary file not shown.
8 changes: 8 additions & 0 deletions tests/unit_tests/test_osw_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def setUp(self):
self.invalid_zones_file = os.path.join(ASSETS_PATH, 'UW.zones.invalid.zip')
self.valid_osw_file = os.path.join(ASSETS_PATH, 'wa.bellevue.zip')
self.invalid_v_id_file = os.path.join(ASSETS_PATH, '4151.zip')
self.serialization_file = os.path.join(ASSETS_PATH, 'test_serialization_error.zip')
self.schema_file_path = SCHEMA_FILE_PATH
self.invalid_schema_file_path = INVALID_SCHEMA_FILE_PATH

Expand Down Expand Up @@ -227,6 +228,13 @@ def test_invalid_zones_file(self):
self.assertFalse(result.is_valid)
self.assertIsNotNone(result.errors)

def test_invalid_serialization_file(self):
validation = OSWValidation(zipfile_path=self.serialization_file)
result = validation.validate()
self.assertFalse(result.is_valid)
self.assertIsNotNone(result.errors)
error_message = next((err for err in result.errors if 'non-serializable' in err.lower()), None)

def test_unmatched_ids_limited_to_20(self):
validation = OSWValidation(zipfile_path=self.invalid_v_id_file)
result = validation.validate()
Expand Down