diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml index f26a4b6..ed8d822 100644 --- a/.github/workflows/lint_and_test.yml +++ b/.github/workflows/lint_and_test.yml @@ -23,6 +23,12 @@ jobs: python-version: 3.11 architecture: x64 + - name: Ensure Nexus mirror configuration is not committed + run: | + # Grep checks for Nexus mirror in the index-url parameter, + # the ! negates the grep exit code, which would be 0 if URL was present + ! grep -E '.*index-url.*nexus.*' requirements*.txt + - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/Dockerfile b/Dockerfile index b65585c..af1ce78 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.11-slim-2023-02-20 +FROM tiangolo/uvicorn-gunicorn-fastapi:python3.11-slim-2024-03-04 ## Install python-ags4 COPY requirements.txt . diff --git a/README.md b/README.md index 6ed5afe..8195e1c 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,20 @@ pytest -vs test The test environment is configured so that adding `--pdb` to the test command will start an IPython debugger session in the event of test failure. +### Updating dependencies + +We are using [pip-tools](https://pip-tools.readthedocs.io/en/stable/) to create a pinned list of all dependencies from the ones that we need to specify. + +To refresh the dependency list, update `requirements.in` and `requirements-dev.in` then run the following: + +```bash +pip-compile -o requirements.txt requirements.in +pip-compile -o requirements_dev.txt requirements_dev.in +``` + +The updated requirements files must be edited to remove reference to the Nexus mirror before they can then be committed. + + ### GUI Customisation To ammend the GUI HTML we recommend running via `Docker` using your own `Dockerfile` like the below to `COPY` in your own templates. @@ -108,7 +122,7 @@ COPY content/templates /app/app/templates Containers for the application are hosted in the GitHub Container Registry -Every push to `Main` branch commits builds `pyagsapi:latest`. +Every push to `main` branch commits builds `pyagsapi:latest`. Push Tagged Releases with `^v?[0-9]+[.][0-9]+([.][0-9])?` (v* == v2.0) builds `pyagsapi:2.0` (the "v" gets dropped for the tag). @@ -116,7 +130,7 @@ You can also push release candidates using the format `/^v?[0-9]+[.][0-9]+([.][0 ## Example Files -Files in [https://github.com/BritishGeologicalSurvey/pyagsapi/tree/main/test/files/real](https://github.com/BritishGeologicalSurvey/pyagsapi/tree/main/test/files/real) are a random collection of real AGS files which have been submitted to the BGS and are available under OGL, we have included them here as example files for testing pyagsapi. +Files in [https://github.com/BritishGeologicalSurvey/pyagsapi/tree/main/test/files/real](https://github.com/BritishGeologicalSurvey/pyagsapi/tree/main/test/files/real) are a collection of real AGS files which have been submitted to the BGS and are available under OGL, we have included them here as example files for testing pyagsapi. ## Licence diff --git a/app/checkers.py b/app/checkers.py index e01417e..9eff809 100644 --- a/app/checkers.py +++ b/app/checkers.py @@ -47,6 +47,9 @@ def check_ags(filename: Path, standard_AGS4_dictionary: Optional[str] = None) -> errors = {'File read error': [{'line': '-', 'group': '', 'desc': description}]} dictionary = '' + # Discard unecessary summary from errors dictionary + errors.pop('Summary of data', None) + return dict(checker=f'python_ags4 v{python_ags4.__version__}', errors=errors, dictionary=dictionary) diff --git a/app/conversion.py b/app/conversion.py index 0888d8b..ef66612 100644 --- a/app/conversion.py +++ b/app/conversion.py @@ -10,7 +10,7 @@ logger = logging.getLogger(__name__) -def convert(filename: Path, results_dir: Path, sort_tables=False) -> Tuple[Optional[Path], dict]: +def convert(filename: Path, results_dir: Path, sorting_strategy: Optional[str] = None) -> Tuple[Optional[Path], dict]: """ Convert filename between .ags and .xlsx. Write output to file in results_dir and return path alongside job status data in dictionary.""" @@ -28,7 +28,7 @@ def convert(filename: Path, results_dir: Path, sort_tables=False) -> Tuple[Optio success = False if filename.suffix.lower() == '.ags': try: - AGS4.AGS4_to_excel(filename, converted_file, sort_tables=sort_tables) + AGS4.AGS4_to_excel(filename, converted_file, sorting_strategy=sorting_strategy) success = True except IndexError: error_message = "ERROR: File does not have AGS4 format layout" diff --git a/app/routes.py b/app/routes.py index 354170a..7c813fe 100644 --- a/app/routes.py +++ b/app/routes.py @@ -110,7 +110,7 @@ class ResponseType(StrEnum): ) sort_tables_form = Form( - default=False, + default='default', title='Sort worksheets', description=('Sort the worksheets into alphabetical order ' 'or leave in the order found in the AGS file. ' @@ -240,7 +240,7 @@ def prepare_validation_response(request, data): " sort worksheets in .xlsx file in alphabetical order.")) async def convert(background_tasks: BackgroundTasks, files: List[UploadFile] = conversion_file, - sort_tables: bool = sort_tables_form, + sort_tables: str = sort_tables_form, request: Request = None): """ Convert files between .ags and .xlsx format. Option to sort worksheets in .xlsx file in alphabetical order. @@ -258,6 +258,8 @@ async def convert(background_tasks: BackgroundTasks, :raises Exception: If the conversion fails or an unexpected error occurs. """ + if sort_tables == 'default': + sort_tables = None if not files[0].filename: raise InvalidPayloadError(request) RESULTS = 'results' @@ -271,7 +273,7 @@ async def convert(background_tasks: BackgroundTasks, contents = await file.read() local_file = tmp_dir / file.filename local_file.write_bytes(contents) - converted, result = conversion.convert(local_file, results_dir, sort_tables=sort_tables) + converted, result = conversion.convert(local_file, results_dir, sorting_strategy=sort_tables) log = validation.to_plain_text(result) f.write(log) f.write('\n' + '=' * 80 + '\n') diff --git a/app/schemas.py b/app/schemas.py index 0f8c3ef..b12af8d 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -15,6 +15,8 @@ 'AGS Format Rule 13', 'AGS Format Rule 14', 'AGS Format Rule 15', 'AGS Format Rule 16', 'AGS Format Rule 17', 'AGS Format Rule 18', 'AGS Format Rule 19', 'AGS Format Rule 19a', 'AGS Format Rule 19b', 'AGS Format Rule 20', 'General', + # Warnings and FYIs + 'Warning (Related to Rule 16)', 'FYI (Related to Rule 1)', # Errors 'File read error' ] diff --git a/app/static/js/htmlView.js b/app/static/js/htmlView.js index ef94d48..b8d344d 100644 --- a/app/static/js/htmlView.js +++ b/app/static/js/htmlView.js @@ -207,9 +207,6 @@ agsHtml.displayFileResult=function(fileResult){ if(fileResult.additional_metadata.bgs_loca_rows){ xhtml=xhtml + "
Performs validation using the Official AGS Python Library version 0.4.1, this implements checks of the rules as written in the AGS data format standard v4.x.
+Performs validation using the Official AGS Python Library version 0.5.0, this implements checks of the rules as written in the AGS data format standard v4.x.
If you're using AGS Data Format Standard v3.x use our legacy AGS Validator