diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml index ed8d822..dc8caf4 100644 --- a/.github/workflows/lint_and_test.yml +++ b/.github/workflows/lint_and_test.yml @@ -15,10 +15,10 @@ jobs: steps: - name: Checkout source repository - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4.5.0 + uses: actions/setup-python@v5 with: python-version: 3.11 architecture: x64 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0aadcbb..9523348 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,7 +30,7 @@ jobs: contents: read steps: - - uses: actions/checkout@v3.3.0 + - uses: actions/checkout@v4 - name: Build image run: docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}" diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 2c651d1..32c2483 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -14,11 +14,11 @@ jobs: run: | git config user.name github-actions[bot] git config user.email 41898282+github-actions[bot]@users.noreply.github.com - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: 3.x - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: key: mkdocs-material-${{ env.cache_id }} path: .cache diff --git a/app/borehole_map.py b/app/borehole_map.py index 1e5d70c..c1bedbd 100644 --- a/app/borehole_map.py +++ b/app/borehole_map.py @@ -22,7 +22,7 @@ def extract_geojson(filepath: Path) -> dict: Read an AGS4 file and extract geojson represenation of LOCA table and metadata. """ - logger.info("Extracting geojson from %s", filepath.name) + logger.info("Extracting geojson from %s", filepath.name) # Read data file tables, load_error, _ = load_tables_reporting_errors(filepath) diff --git a/app/checkers.py b/app/checkers.py index a473626..04f2145 100644 --- a/app/checkers.py +++ b/app/checkers.py @@ -43,11 +43,11 @@ def check_ags(filename: Path, standard_AGS4_dictionary: Optional[str] = None) -> errors = {'File read error': [{'line': line_no, 'group': '', 'desc': description}]} dictionary = '' - # Discard unecessary summary from errors dictionary - errors.pop('Summary of data', None) + # Use summary from errors dictionary is available + summary = errors.pop('Summary of data', []) return dict(checker=f'python_ags4 v{python_ags4.__version__}', - errors=errors, dictionary=dictionary) + errors=errors, dictionary=dictionary, summary=summary) def check_bgs(filename: Path, **kwargs) -> dict: diff --git a/app/routes.py b/app/routes.py index 7d34654..d5226ec 100644 --- a/app/routes.py +++ b/app/routes.py @@ -16,6 +16,7 @@ from requests.exceptions import Timeout, ConnectionError, HTTPError from app import conversion, validation +from app.borehole_map import extract_geojson from app.checkers import check_ags, check_bgs from app.errors import error_responses, InvalidPayloadError from app.schemas import ValidationResponse, BoreholeCountResponse @@ -72,6 +73,14 @@ class Checker(StrEnum): bgs = "bgs" +# Enum for sorting strategy logic +class SortingStrategy(StrEnum): + default = "default" + alphabetical = "alphabetical" + hierarchy = "hierarchy" + dictionary = "dictionary" + + # Enum for pdf response type logic class ResponseType(StrEnum): attachment = "attachment" @@ -89,6 +98,13 @@ class ResponseType(StrEnum): description='Response format: json or text', ) +geometry_form = Form( + default=False, + title='GeoJSON Option', + description=('Return GeoJSON if possible, otherwise return an error message ' + ' Option: True or False'), +) + dictionary_form = Form( default=None, title='Validation Dictionary', @@ -114,10 +130,10 @@ class ResponseType(StrEnum): ) sort_tables_form = Form( - default='default', + default=SortingStrategy.default, title='Sort worksheets', - description=('Sort the worksheets into alphabetical order ' - 'or leave in the order found in the AGS file. ' + description=('Sort the worksheets into alphabetical, hierarchical ' + 'dictionary or default order, that found in the AGS file. ' 'This option is ignored when converting to AGS.'), ) @@ -167,6 +183,7 @@ async def validate(background_tasks: BackgroundTasks, std_dictionary: Dictionary = dictionary_form, checkers: List[Checker] = validate_form, fmt: Format = format_form, + return_geometry: bool = geometry_form, request: Request = None): """ Validate an AGS4 file to the AGS File Format v4.x rules and the NGDC data submission requirements. @@ -182,6 +199,8 @@ async def validate(background_tasks: BackgroundTasks, :param fmt: The format to return the validation results in. Options are "text" or "json". :type fmt: Format + :param return_geometry: Include GeoJSON in validation response. Options are True or False. + :type return_geometry: bool :param request: The request object. :type request: Request :return: A response with the validation results in either plain text or JSON format. @@ -207,6 +226,13 @@ async def validate(background_tasks: BackgroundTasks, local_ags_file.write_bytes(contents) result = validation.validate( local_ags_file, checkers=checkers, standard_AGS4_dictionary=dictionary) + if return_geometry: + try: + geojson = extract_geojson(local_ags_file) + result['geojson'] = geojson + except ValueError as ve: + result['geojson'] = {} + result['geojson_error'] = str(ve) data.append(result) if fmt == Format.TEXT: @@ -262,7 +288,7 @@ async def convert(background_tasks: BackgroundTasks, :raises Exception: If the conversion fails or an unexpected error occurs. """ - if sort_tables == 'default': + if sort_tables == SortingStrategy.default: sort_tables = None if not files[0].filename: raise InvalidPayloadError(request) diff --git a/app/schemas.py b/app/schemas.py index c78477d..859f04f 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -47,7 +47,10 @@ class Validation(BaseModel): message: str = Field(None, example="7 error(s) found in file!") errors: Dict[str, List[LineError]] = Field(..., example="Rule 1a") valid: bool = Field(..., example='false') + summary: List[dict] = list() additional_metadata: dict = Field(...) + geojson: dict = dict() + geojson_error: str = None @validator('errors') def errors_keys_must_be_known_rules(cls, errors): diff --git a/app/templates/landing_page.html b/app/templates/landing_page.html index 8d9098b..13e4201 100644 --- a/app/templates/landing_page.html +++ b/app/templates/landing_page.html @@ -123,12 +123,20 @@