Skip to content

Commit a438349

Browse files
authored
Merge pull request #28 from TaskarCenterAtUW/feature-1378
Fixed Issue 1378
2 parents f2c47aa + 72f4867 commit a438349

File tree

12 files changed

+166
-51
lines changed

12 files changed

+166
-51
lines changed

.github/workflows/unit_tests.yml

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,68 @@
11
---
2-
name: Tests
3-
on:
4-
pull_request:
5-
branches: [develop]
6-
7-
jobs:
8-
Tests:
9-
name: Unit tests
10-
# Set the agent to run on
11-
runs-on: ubuntu-latest
12-
steps:
13-
- name: Checkout code
14-
uses: actions/checkout@v3
15-
16-
- name: Set up Python
17-
uses: actions/setup-python@v4
18-
with:
19-
python-version: "3.10"
20-
21-
- name: Install dependencies
22-
run: |
23-
pip install -r requirements.txt
24-
25-
- name: Run unit tests
26-
run: |
27-
python -m unittest discover -v tests/unit_tests
2+
name: Tests
3+
on:
4+
pull_request:
5+
branches: [ develop, main ]
6+
7+
jobs:
8+
Tests:
9+
name: Unit tests
10+
# Set the agent to run on
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout code
14+
uses: actions/checkout@v3
15+
16+
- name: Set up Python
17+
uses: actions/setup-python@v4
18+
with:
19+
python-version: "3.10"
20+
21+
- name: Install dependencies
22+
run: |
23+
pip install -r requirements.txt
24+
25+
- name: Determine output folder
26+
id: set_output_folder
27+
run: |
28+
if [[ $GITHUB_EVENT_NAME == "pull_request" ]]; then
29+
branch_name=$GITHUB_BASE_REF
30+
else
31+
branch_name=$GITHUB_REF_NAME
32+
fi
33+
if [[ $branch_name == "main" ]]; then
34+
echo "output_folder=prod" >> $GITHUB_ENV
35+
elif [[ $branch_name == "stage" ]]; then
36+
echo "output_folder=stage" >> $GITHUB_ENV
37+
elif [[ $branch_name == "develop" ]]; then
38+
echo "output_folder=dev" >> $GITHUB_ENV
39+
else
40+
echo "Unknown branch: $branch_name"
41+
exit 1
42+
fi
43+
44+
- name: Run tests with coverage
45+
run: |
46+
timestamp=$(date '+%Y-%m-%d_%H-%M-%S')
47+
mkdir -p test_results
48+
log_file="test_results/${timestamp}_report.log"
49+
echo -e "\nTest Cases Report Report\n" >> $log_file
50+
# Run the tests and append output to the log file
51+
python -m coverage run --source=src/python_osw_validation -m unittest discover -v tests/unit_tests >> $log_file 2>&1
52+
echo -e "\nCoverage Report\n" >> $log_file
53+
coverage report >> $log_file
54+
55+
- name: Check coverage
56+
run: |
57+
coverage report --fail-under=85
58+
59+
- name: Upload report to Azure
60+
uses: LanceMcCarthy/Action-AzureBlobUpload@v2
61+
with:
62+
source_folder: 'test_results'
63+
destination_folder: '${{ env.output_folder }}'
64+
connection_string: ${{ secrets.AZURE_STORAGE_CONNECTION_STRING }}
65+
container_name: 'python-osw-validation-package'
66+
clean_destination_folder: false
67+
delete_if_exists: false
68+

CHANGELOG.md

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,31 @@
11
# Change log
22

3+
### 0.2.8
4+
5+
- Fixed geopands version to `0.14.4`.
6+
- Latest geopands version `0.10.0` is not compatible and failing to parse the zones.
7+
- Added unit test cases for valid and invalid zone files
8+
39
### 0.2.7
10+
411
- Switch to `jsonschema_rs` for performance enhancement, instead of `jsonschema` package
512
- Refactor code for improve memory utilization
613
- Added garbage collector
714

8-
915
### 0.2.6
10-
- Add garbage collection to free up memory after validation
1116

17+
- Add garbage collection to free up memory after validation
1218

1319
### 0.2.5
14-
- Updated geopandas package
1520

21+
- Updated geopandas package
1622

1723
### 0.2.3
18-
- Performance improvement if there are any errors
1924

25+
- Performance improvement if there are any errors
2026

2127
### 0.2.2
28+
2229
- Added functionality to get the specific number of errors
2330
```
2431
validator = OSWValidation(zipfile_path=<ZIP_FILE_PATH>)
@@ -27,10 +34,12 @@
2734
```
2835

2936
### 0.2.1
37+
3038
- Updated zipfile_handler
3139
- Fixed "No .geojson files found in the specified directory or its subdirectories." issue
3240

3341
### 0.2.0
42+
3443
- Updated schema file to OSW 0.2
3544
- Added create_zip method to ZipFileHandler
3645
- Made all OSW files optional
@@ -40,20 +49,25 @@
4049
- Aggregate schema errors and data integrity errors separately before returning errors to user
4150

4251
### 0.0.5
52+
4353
- Support for multi-level geojson file
4454
- Now handles the following two folder structures when unzipped abc.zip
45-
1. abc\{nodes, edges, points}.geojson
46-
2. {nodes, edges, points}.geojson
47-
55+
1. abc\{nodes, edges, points}.geojson
56+
2. {nodes, edges, points}.geojson
57+
4858
### 0.0.4
59+
4960
- Points are not required for a valid OSW dataset
5061

5162
### 0.0.3
63+
5264
- Added schema file to package
5365

5466
### 0.0.2
67+
5568
- Updated package Unit test cases.
5669
- Updated README file
5770

5871
### 0.0.1
72+
5973
- Initial version of python_osw_validation package.

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
jsonschema_rs
22
zipfile36
33
coverage
4-
geopandas
4+
geopandas==0.14.4

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
long_description_content_type='text/markdown',
2020
url='https://github.com/TaskarCenterAtUW/TDEI-python-lib-osw-validation',
2121
install_requires=[
22-
'jsonschema_rs',
23-
'zipfile36',
24-
'geopandas'
22+
'jsonschema_rs==0.26.1',
23+
'zipfile36==0.0.12',
24+
'geopandas==0.14.4'
2525
],
2626
packages=find_packages(where='src'),
2727
classifiers=[

src/python_osw_validation/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import Dict, Any, Optional, List
88
from .extracted_data_validator import ExtractedDataValidator, OSW_DATASET_FILES
99
from .version import __version__
10+
import traceback
1011

1112
SCHEMA_PATH = os.path.join(os.path.dirname(__file__), 'schema')
1213

@@ -149,6 +150,7 @@ def validate(self, max_errors=20) -> ValidationResult:
149150
return ValidationResult(True)
150151
except Exception as e:
151152
self.errors.append(f'Unable to validate: {e}')
153+
traceback.print_exc()
152154
return ValidationResult(False, self.errors)
153155
finally:
154156
del OSW_DATASET
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.2.7'
1+
__version__ = '0.2.8'

src/python_osw_validation/zipfile_handler.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import os
2+
import glob
23
import shutil
34
import tempfile
4-
from typing import Optional
55
import zipfile36 as zipfile
6-
import glob
6+
from typing import Optional
77

88

99
class ZipFileHandler:
@@ -21,19 +21,19 @@ def create_zip(self, file_pattern) -> Optional[str]:
2121
try:
2222
# Build the full pattern with the directory
2323
full_pattern = os.path.join(os.path.dirname(self.zip_file_path), file_pattern)
24-
24+
2525
# Find all files in the directory matching the pattern
2626
files_to_zip = glob.glob(full_pattern)
27-
27+
2828
# Create a zip file and add matching files to it
2929
with zipfile.ZipFile(self.zip_file_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
3030
for file in files_to_zip:
3131
archive_name = os.path.relpath(file, os.path.dirname(self.zip_file_path))
3232
zipf.write(file, arcname=archive_name)
33-
33+
3434
# Get the full path to the created zip file
3535
full_zip_path = os.path.abspath(self.zip_file_path)
36-
36+
3737
# Return the full path to the zip file
3838
return full_zip_path
3939
except Exception as e:
@@ -49,22 +49,21 @@ def extract_zip(self) -> Optional[str]:
4949

5050
if len(zip_ref.namelist()) == 0:
5151
raise Exception('ZIP file is empty')
52-
52+
5353
internal_folder_name = self.find_internal_folder(zip_ref)
54-
return os.path.join(self.extracted_dir,internal_folder_name)
54+
return os.path.join(self.extracted_dir, internal_folder_name)
5555
except Exception as e:
5656
self.error = f'Error extracting ZIP file: {e}'
57-
57+
5858
# finds the first folder available in the extracted folder.
5959
# returns empty if there are no folders inside
60-
def find_internal_folder(self, zip_ref: zipfile.ZipFile)-> str:
60+
def find_internal_folder(self, zip_ref: zipfile.ZipFile) -> str:
6161
for filename in zip_ref.namelist():
62-
path = os.path.join(self.extracted_dir,filename)
63-
if(os.path.isdir(path)):
62+
path = os.path.join(self.extracted_dir, filename)
63+
if (os.path.isdir(path)):
6464
return filename
6565
return ''
6666

67-
6867
def remove_extracted_files(self) -> None:
6968
if self.extracted_dir and os.path.exists(self.extracted_dir):
7069
shutil.rmtree(self.extracted_dir)

tests/assets/UW.zones.invalid.zip

26.2 KB
Binary file not shown.

tests/assets/UW.zones.valid.zip

26.2 KB
Binary file not shown.

tests/assets/wa.bellevue.zip

6.32 MB
Binary file not shown.

0 commit comments

Comments
 (0)