diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index be526422d..b9429c4ab 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -124,7 +124,6 @@ jobs: pip3 install -r requirements-django.txt python3 setup.py install pip3 install --global-option=build_ext --global-option="-I/usr/include/gdal" GDAL==`gdal-config --version` - #pip3 install --upgrade rasterio==1.1.8 - name: setup test data ⚙️ run: | python3 tests/load_es_data.py tests/data/ne_110m_populated_places_simple.geojson geonameid @@ -137,49 +136,20 @@ jobs: mysql -h 127.0.0.1 -P 3306 -u root -p'mysql' test_geo_app < tests/data/mysql_data.sql docker ps python3 tests/load_oracle_data.py - - name: run unit tests ⚙️ + - name: run API tests ⚙️ + run: pytest tests/api --ignore-glob='*_live.py' + - name: run Formatter tests ⚙️ + run: pytest tests/formatter + - name: run Provider tests ⚙️ env: POSTGRESQL_PASSWORD: ${{ secrets.DatabasePassword || 'postgres' }} - run: | - pytest tests/api --ignore=tests/api/test_admin_live.py - pytest tests/test_api_ogr_provider.py - pytest tests/test_base_provider.py - pytest tests/test_config.py - pytest tests/test_csv__formatter.py - pytest tests/test_csv__provider.py - pytest tests/test_django.py - pytest tests/test_elasticsearch__provider.py - pytest tests/test_opensearch__provider.py - pytest tests/test_esri_provider.py - pytest tests/test_filesystem_provider.py - pytest tests/test_geojson_provider.py - pytest tests/test_linked_data.py - pytest tests/test_mongo_provider.py - pytest tests/test_ogr_csv_provider.py - pytest tests/test_ogr_esrijson_provider.py - pytest tests/test_ogr_gpkg_provider.py - pytest tests/test_ogr_shapefile_provider.py - pytest tests/test_ogr_sqlite_provider.py - pytest tests/test_ogr_wfs_provider.py - pytest tests/test_postgresql_manager.py - # pytest tests/test_ogr_wfs_provider_live.py # NOTE: these are skipped in the file but listed here for completeness - pytest tests/test_openapi.py - pytest tests/test_oracle_provider.py - pytest tests/test_parquet_provider.py - pytest tests/test_postgresql_provider.py - pytest tests/test_postgresql_mvt_provider.py - pytest tests/test_mysql_provider.py - pytest tests/test_rasterio_provider.py - pytest tests/test_sensorthings_edr_provider.py - pytest tests/test_sensorthings_provider.py - pytest tests/test_socrata_provider.py - # pytest tests/test_socrata_provider_live.py.py # NOTE: these are skipped in the file but listed here for completeness - pytest tests/test_sqlite_geopackage_provider.py - pytest tests/test_tinydb_catalogue_provider.py - pytest tests/test_tinydb_manager_for_parallel_requests.py - pytest tests/test_util.py - pytest tests/test_xarray_netcdf_provider.py - pytest tests/test_xarray_zarr_provider.py + run: pytest tests/provider --ignore-glob='*_live.py' + - name: run Manager tests ⚙️ + env: + POSTGRESQL_PASSWORD: ${{ secrets.DatabasePassword || 'postgres' }} + run: pytest tests/manager + - name: run other tests ⚙️ + run: pytest tests/other --ignore-glob='*_live.py' - name: failed tests 🚩 if: ${{ failure() }} run: | diff --git a/docs/source/data-publishing/ogcapi-features.rst b/docs/source/data-publishing/ogcapi-features.rst index 91e6e6b2f..04969bcce 100644 --- a/docs/source/data-publishing/ogcapi-features.rst +++ b/docs/source/data-publishing/ogcapi-features.rst @@ -570,7 +570,7 @@ Custom SQL Manipulator Plugin The provider supports a SQL-Manipulator-Plugin class. With this, the SQL statement could be manipulated. This is useful e.g. for authorization at row level or manipulation of the explain plan with hints. -An example and more information about that feature can be found in the test class in tests/test_oracle_provider.py. +More information and examples about this feature can be found in ``tests/provider/test_oracle_provider.py``. .. _Parquet: diff --git a/docs/source/data-publishing/ogcapi-tiles.rst b/docs/source/data-publishing/ogcapi-tiles.rst index 9bada7490..4e4f7c684 100644 --- a/docs/source/data-publishing/ogcapi-tiles.rst +++ b/docs/source/data-publishing/ogcapi-tiles.rst @@ -201,6 +201,16 @@ This code block shows how to configure pygeoapi to read map tiles from a WMTS. min: 0 max: 20 + +Providing custom Tile Matrix Set definitions +-------------------------------------------- + +By default, pygeoapi provides the ``WorldCRS84Quad`` and ``WebMercatorQuad`` TMS +definitions, for tile providers to use accordingly. Additional TMS definitions +may be added in pygeoapi's ``resources/definitions/tiles`` (for example, by adding +TMS definition files directly, volume mapping / Docker ``COPY``, Docker Compose ``volumes``, etc.). + + Data access examples -------------------- diff --git a/docs/source/development.rst b/docs/source/development.rst index d783a9451..6c8cd1ce4 100644 --- a/docs/source/development.rst +++ b/docs/source/development.rst @@ -11,12 +11,12 @@ The pygeoapi codebase exists at https://github.com/geopython/pygeoapi. Pull Requests and GitHub Actions -------------------------------- -A given GitHub Pull Request is evaluated against the following GitHub actions: +A given GitHub Pull Request is evaluated against the following GitHub Actions: -- main: mainline testing harness (as defined in ``tests``) -- flake8: code linting -- docs: documentation updates (for files updated in ``docs/**.rst``) -- vulnerabilities: Trivy vulnerability scanning +- ``main``: mainline testing harness (as defined in ``tests``) +- ``flake8``: code linting +- ``docs``: documentation updates (for files updated in ``docs/**.rst``) +- ``vulnerabilities``: Trivy vulnerability scanning Testing ------- @@ -25,6 +25,11 @@ pygeoapi uses `pytest `_ for managing its automated tes exist in ``/tests`` and are developed for providers, formatters, processes, as well as the overall API. +- API specific tests can be found in ``/tests/api`` +- Provider specific tests can be found in ``/tests/provider`` +- Manager specific tests can be found in ``/tests/manager`` +- Additional/other tests can be found in ``/tests/other`` + Tests can be run locally as part of development workflow. They are also run on pygeoapi’s `GitHub Actions setup`_ against all commits and pull requests to the code repository. @@ -57,24 +62,23 @@ Using pre-commit ^^^^^^^^^^^^^^^^ You may optionally use `pre-commit`_ in order to check for linting and other static issues -before committing changes. Pygeoapi's repo includes a ``.pre-commit.yml`` +before committing changes. pygeoapi's repo includes a ``.pre-commit.yml`` file, check the pre-commit docs on how to set it up - in a nutshell: -- pre-commit is mentioned in pygeoapi's ``requirements-dev.txt`` file, so it will be included - when you pip install those -- run ``pre-commit install`` once in order to install its git commit hooks. -- optionally, run ``pre-commit run --all-files``, which will run all pre-commit hooks for all files in the repo. - This also prepares the pre-commit environment. -- from now on, whenever you do a ``git commit``, the pre-commit hooks will run and the commit - will only be done if all checks pass +- pre-commit is part of ``requirements-dev.txt`` file, so it will be included when installing same +- run ``pre-commit install`` once in order to install its git commit hooks +- optionally, run ``pre-commit run --all-files``, which will run all pre-commit hooks for all files + in the repository. Note that this also prepares the pre-commit environment +- When subsequent ``git commit`` commands are run, the pre-commit hooks will run and commit + on passing checks Building the documentation -------------------------- -To build the documentation in pygeoapi we use `Sphinx`_. The documentation is located in the docs folder. +Documentation is managed using `Sphinx`_ and located in the ``docs`` directory. .. note:: - For the following instructions to work, you must be located in the root folder of pygeoapi. + The following commands should be run from the root folder of the repository. Install the dependencies necessary for building the documentation using the following command: @@ -93,12 +97,17 @@ Or using the following ``make`` command: .. code-block:: bash - make -C docs html + make -C docs/ html + +After building the documentation, the ``docs/build`` directory will contain the generated documentation. + +To view the generated documentation locally, use one of the following options: -After building the documentation, the folder ``docs/build`` will contain the website generated with the documentation. -Add the folder to a web server or open the file ``docs/build/html/index.html`` file in a web browser to see the contents of the documentation. +- run ``python3 -m http.server`` and navigate to ``http://localhost:8000`` in a web browser. To use a different port, use ``python3 -m http.server 8001``, for example, and navigate to ``http://localhost:8001`` +- add the directory to a web server +- open the file ``docs/build/html/index.html`` file in a web browser -The documentation is hosted on `Read the Docs`_. It is automatically generated from the contents of the ``master`` branch on GitHub. +The documentation is hosted on `Read the Docs`_ and automatically generated from the contents of the ``master`` branch on GitHub. The file ``.readthedocs.yaml`` contains the configuration of the Read the Docs build. Refer to the `Read the Docs configuration file`_ documentation for more information. diff --git a/docs/source/index.rst b/docs/source/index.rst index 49191a7c1..f507561dd 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -21,7 +21,7 @@ reference documentation on all aspects of the project. .. note:: - Did you know about the `pygeoapi workshop`_? Ready to get your hands dirty? Dive in! + Did you know about the `Diving into pygeoapi workshop`_? Ready to get your hands dirty? Dive in! .. toctree:: :maxdepth: 4 @@ -61,4 +61,4 @@ Indices and tables * :ref:`modindex` * :ref:`search` -.. _`pygeoapi workshop`: https://dive.pygeoapi.io +.. _`Diving into pygeoapi workshop`: https://dive.pygeoapi.io diff --git a/docs/source/ogc-compliance.rst b/docs/source/ogc-compliance.rst index 126251e70..33cf6b5b7 100644 --- a/docs/source/ogc-compliance.rst +++ b/docs/source/ogc-compliance.rst @@ -16,4 +16,4 @@ Setting up your own CITE testing instance ----------------------------------------- Please see the pygeoapi `OGC Compliance `_ -for up to date information as well as technical details on setting up your own CITE instance. +wiki page for up to date information as well as technical details on setting up your own CITE instance. diff --git a/pygeoapi/api/__init__.py b/pygeoapi/api/__init__.py index b8adc0ce1..6e34712a6 100644 --- a/pygeoapi/api/__init__.py +++ b/pygeoapi/api/__init__.py @@ -63,7 +63,7 @@ ProviderConnectionError, ProviderGenericError, ProviderTypeError) from pygeoapi.util import ( - CrsTransformSpec, TEMPLATES, UrlPrefetcher, dategetter, + CrsTransformSpec, TEMPLATESDIR, UrlPrefetcher, dategetter, filter_dict_by_key_value, filter_providers_by_type, get_api_rules, get_base_url, get_provider_by_type, get_provider_default, get_typed_value, get_crs_from_uri, get_supported_crs_list, render_j2_template, to_json, @@ -555,7 +555,7 @@ def __init__(self, config, openapi): self.default_locale = self.locales[0] if 'templates' not in self.config['server']: - self.config['server']['templates'] = {'path': TEMPLATES} + self.config['server']['templates'] = {'path': TEMPLATESDIR} if 'pretty_print' not in self.config['server']: self.config['server']['pretty_print'] = False diff --git a/pygeoapi/config.py b/pygeoapi/config.py index 7b4ee9203..88f50e74b 100644 --- a/pygeoapi/config.py +++ b/pygeoapi/config.py @@ -3,7 +3,7 @@ # Authors: Tom Kralidis # Francesco Bartoli # -# Copyright (c) 2022 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # Copyright (c) 2025 Francesco Bartoli # # Permission is hereby granted, free of charge, to any person @@ -36,7 +36,7 @@ import os import yaml -from pygeoapi.util import to_json, yaml_load, THISDIR +from pygeoapi.util import SCHEMASDIR, to_json, yaml_load LOGGER = logging.getLogger(__name__) @@ -65,7 +65,7 @@ def get_config(raw: bool = False) -> dict: def load_schema() -> dict: """ Reads the JSON schema YAML file. """ - schema_file = THISDIR / 'schemas' / 'config' / 'pygeoapi-config-0.x.yml' + schema_file = SCHEMASDIR / 'config' / 'pygeoapi-config-0.x.yml' with schema_file.open() as fh2: return yaml_load(fh2) diff --git a/pygeoapi/models/provider/base.py b/pygeoapi/models/provider/base.py index 9788b0650..cc67443cf 100644 --- a/pygeoapi/models/provider/base.py +++ b/pygeoapi/models/provider/base.py @@ -1,12 +1,12 @@ -# ****************************** -*- -# flake8: noqa # ================================================================= # # Authors: Antonio Cerciello # Francesco Bartoli +# Tom Kralidis # # Copyright (c) 2022 Antonio Cerciello # Copyright (c) 2025 Francesco Bartoli +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -40,10 +40,9 @@ import pydantic from pydantic import BaseModel -from pygeoapi.util import THISDIR +from pygeoapi.util import DEFINITIONSDIR - -TMS_DIR = THISDIR / 'resources' / 'tilematrixsets' +TMS_DIR = DEFINITIONSDIR / 'tiles' class TilesMetadataFormat(str, Enum): @@ -93,10 +92,19 @@ def __init__(self, directory: Path): self.directory = directory def load_from_file(self, filename: str) -> TileMatrixSetEnumType: - """Load a single TMS JSON file.""" + """ + Load a single TMS JSON file. + + :param filename: filename of TMS + + :returns: `TileMatrixSetEnumType` of TMS + """ + filepath = self.directory / filename + with filepath.open(encoding='utf-8') as fh: data = json.load(fh) + return TileMatrixSetEnumType( tileMatrixSet=data["id"], tileMatrixSetURI=data["uri"], @@ -108,12 +116,18 @@ def load_from_file(self, filename: str) -> TileMatrixSetEnumType: ) def create_enum(self) -> Enum: - """Create an Enum with all TileMatrixSets in the directory.""" + """ + Create an Enum with all TileMatrixSets in the directory. + + :returns: `Enum` of `TileMatrixSetEnum` + """ + members = {} - for file_path in self.directory.glob("*.json"): - tms = self.load_from_file(file_path.name) - enum_name = tms.tileMatrixSet.upper().replace("-", "").replace(" ", "") + for filepath in self.directory.glob("*.json"): + tms = self.load_from_file(filepath.name) + enum_name = tms.tileMatrixSet.upper().replace("-", "").replace(" ", "") # noqa members[enum_name] = tms + return Enum("TileMatrixSetEnum", members) @@ -199,7 +213,7 @@ class TileSetMetadata(BaseModel): license_: Optional[str] = None # Restrictions on the availability of the Tile Set that the user needs to # be aware of before using or redistributing the Tile Set - accessConstraints: Optional[AccessConstraintsEnum] = AccessConstraintsEnum.UNCLASSIFIED + accessConstraints: Optional[AccessConstraintsEnum] = AccessConstraintsEnum.UNCLASSIFIED # noqa # Media types available for the tiles mediaTypes: Optional[List[str]] = None # Type of data represented in the tileset diff --git a/pygeoapi/openapi.py b/pygeoapi/openapi.py index 13d3185f3..62105813f 100644 --- a/pygeoapi/openapi.py +++ b/pygeoapi/openapi.py @@ -4,7 +4,7 @@ # Authors: Francesco Bartoli # Authors: Ricardo Garcia Silva # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # Copyright (c) 2025 Francesco Bartoli # Copyright (c) 2023 Ricardo Garcia Silva # @@ -47,7 +47,7 @@ from pygeoapi.api import all_apis from pygeoapi.models.openapi import OAPIFormat from pygeoapi.util import (filter_dict_by_key_value, to_json, yaml_load, - get_api_rules, get_base_url) + get_api_rules, get_base_url, SCHEMASDIR) LOGGER = logging.getLogger(__name__) @@ -62,8 +62,6 @@ 'pygeoapi': 'https://raw.githubusercontent.com/geopython/pygeoapi/master/pygeoapi/schemas/config/pygeoapi-config-0.x.yml' # noqa } -THISDIR = os.path.dirname(os.path.realpath(__file__)) - def get_ogc_schemas_location(server_config: dict) -> str: """ @@ -706,10 +704,9 @@ def get_visible_collections(cfg: dict) -> dict: def get_config_schema(): - schema_file = os.path.join(THISDIR, 'schemas', 'config', - 'pygeoapi-config-0.x.yml') + schema_file = SCHEMASDIR / 'config' / 'pygeoapi-config-0.x.yml' - with open(schema_file) as fh2: + with schema_file.open() as fh2: return yaml_load(fh2) @@ -957,10 +954,9 @@ def validate_openapi_document(instance_dict: dict) -> bool: :returns: `bool` of validation """ - schema_file = os.path.join(THISDIR, 'schemas', 'openapi', - 'openapi-3.0.x.json') + schema_file = SCHEMASDIR / 'openapi' / 'openapi-3.0.x.json' - with open(schema_file) as fh2: + with schema_file.open() as fh2: schema_dict = json.load(fh2) jsonschema_validate(instance_dict, schema_dict) diff --git a/pygeoapi/resources/tilematrixsets/WebMercatorQuad.json b/pygeoapi/resources/definitions/tiles/WebMercatorQuad.json similarity index 100% rename from pygeoapi/resources/tilematrixsets/WebMercatorQuad.json rename to pygeoapi/resources/definitions/tiles/WebMercatorQuad.json diff --git a/pygeoapi/resources/tilematrixsets/WorldCRS84Quad.json b/pygeoapi/resources/definitions/tiles/WorldCRS84Quad.json similarity index 100% rename from pygeoapi/resources/tilematrixsets/WorldCRS84Quad.json rename to pygeoapi/resources/definitions/tiles/WorldCRS84Quad.json diff --git a/pygeoapi/schemas/config/pygeoapi-config-0.x.yml b/pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml similarity index 100% rename from pygeoapi/schemas/config/pygeoapi-config-0.x.yml rename to pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml diff --git a/pygeoapi/schemas/openapi/openapi-3.0.x.json b/pygeoapi/resources/schemas/openapi/openapi-3.0.x.json similarity index 100% rename from pygeoapi/schemas/openapi/openapi-3.0.x.json rename to pygeoapi/resources/schemas/openapi/openapi-3.0.x.json diff --git a/pygeoapi/util.py b/pygeoapi/util.py index ded9b6eb3..4db52582f 100644 --- a/pygeoapi/util.py +++ b/pygeoapi/util.py @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2022 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -88,7 +88,10 @@ DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ' THISDIR = Path(__file__).parent.resolve() -TEMPLATES = THISDIR / 'templates' +RESOURCESDIR = THISDIR / 'resources' +TEMPLATESDIR = THISDIR / 'templates' +DEFINITIONSDIR = RESOURCESDIR / 'definitions' +SCHEMASDIR = RESOURCESDIR / 'schemas' # Type for Shapely geometrical objects. @@ -449,7 +452,7 @@ def render_j2_template(config: dict, tpl_config: dict, template: Path, :returns: string of rendered template """ - template_paths = [TEMPLATES, '.'] + template_paths = [TEMPLATESDIR, '.'] locale_dir = config['server'].get('locale_dir', 'locale') LOGGER.debug(f'Locale directory: {locale_dir}') @@ -459,7 +462,7 @@ def render_j2_template(config: dict, tpl_config: dict, template: Path, template_paths.insert(0, templates) LOGGER.debug(f'using custom templates: {templates}') except (KeyError, TypeError): - LOGGER.debug(f'using default templates: {TEMPLATES}') + LOGGER.debug(f'using default templates: {TEMPLATESDIR}') env = Environment(loader=FileSystemLoader(template_paths), extensions=['jinja2.ext.i18n'], diff --git a/tests/formatter/__init__.py b/tests/formatter/__init__.py new file mode 100644 index 000000000..39827f550 --- /dev/null +++ b/tests/formatter/__init__.py @@ -0,0 +1,28 @@ +# ================================================================= +# +# Authors: Tom Kralidis +# +# Copyright (c) 2025 Tom Kralidis +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# ================================================================= diff --git a/tests/test_csv__formatter.py b/tests/formatter/test_csv__formatter.py similarity index 100% rename from tests/test_csv__formatter.py rename to tests/formatter/test_csv__formatter.py diff --git a/tests/manager/__init__.py b/tests/manager/__init__.py new file mode 100644 index 000000000..39827f550 --- /dev/null +++ b/tests/manager/__init__.py @@ -0,0 +1,28 @@ +# ================================================================= +# +# Authors: Tom Kralidis +# +# Copyright (c) 2025 Tom Kralidis +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# ================================================================= diff --git a/tests/test_manager.py b/tests/manager/test_manager.py similarity index 96% rename from tests/test_manager.py rename to tests/manager/test_manager.py index 17017748d..c3ee4bb21 100644 --- a/tests/test_manager.py +++ b/tests/manager/test_manager.py @@ -1,8 +1,10 @@ # ================================================================= # # Authors: Ricardo Garcia Silva +# Tom Kralidis # # Copyright (c) 2023 Ricardo Garcia Silva +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -26,6 +28,7 @@ # OTHER DEALINGS IN THE SOFTWARE. # # ================================================================= + from typing import Dict import pytest @@ -33,7 +36,7 @@ from pygeoapi.process.base import UnknownProcessError, JobNotFoundError from pygeoapi.process.manager.base import get_manager -from .util import get_test_file_path +from ..util import get_test_file_path @pytest.fixture() diff --git a/tests/test_postgresql_manager.py b/tests/manager/test_postgresql_manager.py similarity index 98% rename from tests/test_postgresql_manager.py rename to tests/manager/test_postgresql_manager.py index d8c30ff97..af4cb897b 100644 --- a/tests/test_postgresql_manager.py +++ b/tests/manager/test_postgresql_manager.py @@ -1,8 +1,10 @@ # ================================================================= # # Authors: Francesco Martinelli +# Tom Kralidis # # Copyright (c) 2024 Francesco Martinelli +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -36,7 +38,7 @@ from werkzeug.wrappers import Request from werkzeug.test import create_environ -from .util import get_test_file_path +from ..util import get_test_file_path from pygeoapi.api import API, APIRequest import pygeoapi.api.processes as processes_api from pygeoapi.util import yaml_load diff --git a/tests/test_tinydb_manager_for_parallel_requests.py b/tests/manager/test_tinydb_manager_for_parallel_requests.py similarity index 98% rename from tests/test_tinydb_manager_for_parallel_requests.py rename to tests/manager/test_tinydb_manager_for_parallel_requests.py index d968dd0d2..8b216927f 100644 --- a/tests/test_tinydb_manager_for_parallel_requests.py +++ b/tests/manager/test_tinydb_manager_for_parallel_requests.py @@ -4,7 +4,7 @@ # Tom Kralidis # # Copyright (c) 2022 52°North Spatial Information Research GmbH -# Copyright (c) 2022 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -30,9 +30,9 @@ # ================================================================= import json +from multiprocessing import Process, Manager from pathlib import Path -from multiprocessing import Process, Manager import pytest from tinydb import TinyDB, Query from werkzeug.wrappers import Request @@ -41,7 +41,7 @@ from pygeoapi.api import API, APIRequest import pygeoapi.api.processes as processes_api from pygeoapi.util import yaml_load -from .util import get_test_file_path +from ..util import get_test_file_path @pytest.fixture() diff --git a/tests/other/__init__.py b/tests/other/__init__.py new file mode 100644 index 000000000..39827f550 --- /dev/null +++ b/tests/other/__init__.py @@ -0,0 +1,28 @@ +# ================================================================= +# +# Authors: Tom Kralidis +# +# Copyright (c) 2025 Tom Kralidis +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# ================================================================= diff --git a/tests/test_config.py b/tests/other/test_config.py similarity index 97% rename from tests/test_config.py rename to tests/other/test_config.py index b526c9455..0ab728ffe 100644 --- a/tests/test_config.py +++ b/tests/other/test_config.py @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2021 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -27,16 +27,16 @@ # # ================================================================= -import os from copy import deepcopy +import os -from jsonschema.exceptions import ValidationError import pytest +from jsonschema.exceptions import ValidationError from pygeoapi.config import validate_config from pygeoapi.util import yaml_load -from .util import get_test_file_path +from ..util import get_test_file_path @pytest.fixture() diff --git a/tests/other/test_django.py b/tests/other/test_django.py new file mode 100644 index 000000000..85c349e5d --- /dev/null +++ b/tests/other/test_django.py @@ -0,0 +1,73 @@ +# ================================================================= +# +# Authors: Bernhard Mallinger +# Tom Kralidis +# +# Copyright (c) 2024 Bernhard Mallinger +# Copyright (c) 2025 Tom Kralidis +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# ================================================================= + + +from http import HTTPStatus +import os +import sys +from unittest import mock + +import django +from django.test import Client +import pytest + +from ..util import get_test_file_path + + +@pytest.fixture +@mock.patch.dict(os.environ, { + "DJANGO_SETTINGS_MODULE": "django_.settings", + "PYGEOAPI_CONFIG": get_test_file_path('pygeoapi-test-config.yml'), + "PYGEOAPI_OPENAPI": get_test_file_path('pygeoapi-test-openapi.yml') +}) +@mock.patch.object(sys, "path", sys.path + ["./pygeoapi"]) +def django_(): + django.setup() + return django + + +def test_django_landing_page_loads(django_): + response = Client(SERVER_NAME="localhost").get("/") + + assert response.status_code == HTTPStatus.OK + assert response.json()["title"] == "pygeoapi default instance" + + +def test_django_edr_without_instance_id(django_): + edr_position_query = ("/collections/icoads-sst/position?coords=" + "POINT(12.779895 55.783523)&f=json") + response = Client(SERVER_NAME="localhost").get(edr_position_query) + + assert response.status_code == HTTPStatus.OK + # Validate CoverageJSON is returned + response_json = response.json() + assert response_json["type"] == "Coverage" + assert response_json["domain"]["domainType"] == "PointSeries" diff --git a/tests/test_l10n.py b/tests/other/test_l10n.py similarity index 91% rename from tests/test_l10n.py rename to tests/other/test_l10n.py index 2d9a643a1..674c24b41 100644 --- a/tests/test_l10n.py +++ b/tests/other/test_l10n.py @@ -1,8 +1,10 @@ # ================================================================= # # Authors: Sander Schaminee +# Tom Kralidis # # Copyright (c) 2021 GeoCat BV +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -33,7 +35,7 @@ from pygeoapi import l10n from pygeoapi.util import yaml_load -from .util import get_test_file_path +from ..util import get_test_file_path def test_str2locale(): @@ -67,16 +69,16 @@ def test_bestmatch(): assert l10n.best_match('de', ('en',)) == Locale('en') assert l10n.best_match(None, ['en', 'de']) == Locale('en') # noqa assert l10n.best_match('', ['en', 'de']) == Locale('en') - assert l10n.best_match('de-DE', ['en', 'de']) == Locale('de') - assert l10n.best_match('de-DE, en', ['en', 'de']) == Locale('de') - assert l10n.best_match('de, en', ['en_US', 'de-DE']) == Locale.parse('de_DE') # noqa + assert l10n.best_match('de-DE', ['de', 'en']) == Locale('de') + assert l10n.best_match('de-DE, en', ['de', 'en']) == Locale('de') + assert l10n.best_match('de, en', ['de-DE', 'en_US']) == Locale.parse('de_DE') # noqa assert l10n.best_match(Locale('de'), ['nl', 'de']) == Locale('de') accept = "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5" assert l10n.best_match(accept, ['fr', 'en']) == Locale('fr') - assert l10n.best_match(accept, ['it', 'de']) == Locale('de') - assert l10n.best_match(accept, ['fr-BE', 'fr']) == Locale('fr') + assert l10n.best_match(accept, ['de', 'it']) == Locale('de') + assert l10n.best_match(accept, ['fr', 'fr-BE']) == Locale('fr') assert l10n.best_match(accept, ['fr-BE', 'fr-FR']) == Locale.parse('fr_BE') assert l10n.best_match(accept, ['fr-BE', 'fr-FR']) == Locale.parse('fr_BE') assert l10n.best_match(accept, ['it', 'es']) == Locale('it') @@ -132,19 +134,6 @@ def test_translate(language_struct, nonlanguage_struct): l10n.translate(language_struct, 42) # noqa -def test_localefromheaders(): - assert l10n.locale_from_headers({}) is None - assert l10n.locale_from_headers({'Accept-Language': 'de'}) == 'de' - assert l10n.locale_from_headers({'accept-language': 'en_US'}) == 'en_US' - - -def test_localefromparams(): - assert l10n.locale_from_params({}) is None - assert l10n.locale_from_params({'lang': 'de'}) == 'de' - assert l10n.locale_from_params({'language': 'en_US'}) is None - assert l10n.locale_from_params({'lang': 'en_US'}) == 'en_US' - - def test_addlocale(): assert l10n.add_locale('http://a.pi/', None) == 'http://a.pi/' assert l10n.add_locale('http://a.pi/', 'en') == 'http://a.pi/?lang=en' @@ -198,7 +187,7 @@ def test_getpluginlocale(): assert l10n.get_plugin_locale({'languages': ['en']}, None) == Locale('en') # noqa assert l10n.get_plugin_locale({'languages': []}, 'nl') is None assert l10n.get_plugin_locale({'languages': ['en']}, 'fr') == Locale('en') - assert l10n.get_plugin_locale({'languages': ['en', 'de']}, 'de') == Locale('de') # noqa + assert l10n.get_plugin_locale({'languages': ['de', 'en']}, 'de') == Locale('de') # noqa assert l10n.get_plugin_locale({'languages': ['en', 'de']}, None) == Locale('en') # noqa diff --git a/tests/test_linked_data.py b/tests/other/test_linked_data.py similarity index 100% rename from tests/test_linked_data.py rename to tests/other/test_linked_data.py diff --git a/tests/test_ogr_capabilities.py b/tests/other/test_ogr_capabilities.py similarity index 100% rename from tests/test_ogr_capabilities.py rename to tests/other/test_ogr_capabilities.py diff --git a/tests/test_openapi.py b/tests/other/test_openapi.py similarity index 98% rename from tests/test_openapi.py rename to tests/other/test_openapi.py index 5d99aefe9..49f4f70ba 100644 --- a/tests/test_openapi.py +++ b/tests/other/test_openapi.py @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2022 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -27,15 +27,14 @@ # # ================================================================= -import pytest - from jsonschema.exceptions import ValidationError +import pytest from pygeoapi.openapi import (get_oas, get_ogc_schemas_location, validate_openapi_document) from pygeoapi.util import yaml_load -from .util import get_test_file_path +from ..util import get_test_file_path @pytest.fixture() diff --git a/tests/test_util.py b/tests/other/test_util.py similarity index 99% rename from tests/test_util.py rename to tests/other/test_util.py index b542a7b9d..e7570b756 100644 --- a/tests/test_util.py +++ b/tests/other/test_util.py @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2021 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -46,7 +46,7 @@ from pygeoapi.api import __version__ from pygeoapi.provider.base import ProviderTypeError -from .util import get_test_file_path +from ..util import get_test_file_path @pytest.fixture() diff --git a/tests/provider/__init__.py b/tests/provider/__init__.py new file mode 100644 index 000000000..39827f550 --- /dev/null +++ b/tests/provider/__init__.py @@ -0,0 +1,28 @@ +# ================================================================= +# +# Authors: Tom Kralidis +# +# Copyright (c) 2025 Tom Kralidis +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# ================================================================= diff --git a/tests/test_api_ogr_provider.py b/tests/provider/test_api_ogr_provider.py similarity index 99% rename from tests/test_api_ogr_provider.py rename to tests/provider/test_api_ogr_provider.py index c29fc629e..253356673 100644 --- a/tests/test_api_ogr_provider.py +++ b/tests/provider/test_api_ogr_provider.py @@ -4,7 +4,7 @@ # Authors: Tom Kralidis # # Copyright (c) 2019 Just van den Broecke -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -38,7 +38,7 @@ from pygeoapi.api.itemtypes import get_collection_item, get_collection_items from pygeoapi.util import yaml_load, geojson_to_geom -from .util import get_test_file_path, mock_api_request +from ..util import get_test_file_path, mock_api_request LOGGER = logging.getLogger(__name__) diff --git a/tests/test_base_provider.py b/tests/provider/test_base_provider.py similarity index 99% rename from tests/test_base_provider.py rename to tests/provider/test_base_provider.py index d6de0836e..c62631d77 100644 --- a/tests/test_base_provider.py +++ b/tests/provider/test_base_provider.py @@ -27,10 +27,12 @@ # # ================================================================= -import pytest import json from http import HTTPStatus +import pytest + + from pygeoapi.provider.base import ( BaseProvider, ProviderTypeError, ProviderItemNotFoundError, ProviderInvalidDataError, diff --git a/tests/test_csv__provider.py b/tests/provider/test_csv__provider.py similarity index 99% rename from tests/test_csv__provider.py rename to tests/provider/test_csv__provider.py index 639545031..0ad36f828 100644 --- a/tests/test_csv__provider.py +++ b/tests/provider/test_csv__provider.py @@ -35,7 +35,7 @@ ProviderInvalidQueryError) from pygeoapi.provider.csv_ import CSVProvider -from .util import get_test_file_path +from ..util import get_test_file_path LOGGER = logging.getLogger(__name__) diff --git a/tests/test_csw_provider.py b/tests/provider/test_csw_provider.py similarity index 100% rename from tests/test_csw_provider.py rename to tests/provider/test_csw_provider.py diff --git a/tests/test_elasticsearch__provider.py b/tests/provider/test_elasticsearch__provider.py similarity index 100% rename from tests/test_elasticsearch__provider.py rename to tests/provider/test_elasticsearch__provider.py diff --git a/tests/test_esri_provider.py b/tests/provider/test_esri_provider.py similarity index 100% rename from tests/test_esri_provider.py rename to tests/provider/test_esri_provider.py diff --git a/tests/test_filesystem_provider.py b/tests/provider/test_filesystem_provider.py similarity index 97% rename from tests/test_filesystem_provider.py rename to tests/provider/test_filesystem_provider.py index 5a23ac9e1..6e70efa1d 100644 --- a/tests/test_filesystem_provider.py +++ b/tests/provider/test_filesystem_provider.py @@ -40,7 +40,7 @@ def config(): return { 'name': 'FileSystem', 'type': 'stac', - 'data': os.path.join(THISDIR, 'data'), + 'data': os.path.join(THISDIR, '../data'), 'file_types': ['.gpkg'] } diff --git a/tests/test_geojson_provider.py b/tests/provider/test_geojson_provider.py similarity index 100% rename from tests/test_geojson_provider.py rename to tests/provider/test_geojson_provider.py diff --git a/tests/test_mongo_provider.py b/tests/provider/test_mongo_provider.py similarity index 100% rename from tests/test_mongo_provider.py rename to tests/provider/test_mongo_provider.py diff --git a/tests/test_mysql_provider.py b/tests/provider/test_mysql_provider.py similarity index 100% rename from tests/test_mysql_provider.py rename to tests/provider/test_mysql_provider.py diff --git a/tests/test_ogr_csv_provider.py b/tests/provider/test_ogr_csv_provider.py similarity index 100% rename from tests/test_ogr_csv_provider.py rename to tests/provider/test_ogr_csv_provider.py diff --git a/tests/test_ogr_esrijson_provider.py b/tests/provider/test_ogr_esrijson_provider.py similarity index 100% rename from tests/test_ogr_esrijson_provider.py rename to tests/provider/test_ogr_esrijson_provider.py diff --git a/tests/test_ogr_gpkg_provider.py b/tests/provider/test_ogr_gpkg_provider.py similarity index 100% rename from tests/test_ogr_gpkg_provider.py rename to tests/provider/test_ogr_gpkg_provider.py diff --git a/tests/test_ogr_shapefile_provider.py b/tests/provider/test_ogr_shapefile_provider.py similarity index 100% rename from tests/test_ogr_shapefile_provider.py rename to tests/provider/test_ogr_shapefile_provider.py diff --git a/tests/test_ogr_sqlite_provider.py b/tests/provider/test_ogr_sqlite_provider.py similarity index 100% rename from tests/test_ogr_sqlite_provider.py rename to tests/provider/test_ogr_sqlite_provider.py diff --git a/tests/test_ogr_wfs_provider.py b/tests/provider/test_ogr_wfs_provider.py similarity index 100% rename from tests/test_ogr_wfs_provider.py rename to tests/provider/test_ogr_wfs_provider.py diff --git a/tests/test_ogr_wfs_provider_live.py b/tests/provider/test_ogr_wfs_provider_live.py similarity index 100% rename from tests/test_ogr_wfs_provider_live.py rename to tests/provider/test_ogr_wfs_provider_live.py diff --git a/tests/test_opensearch__provider.py b/tests/provider/test_opensearch__provider.py similarity index 100% rename from tests/test_opensearch__provider.py rename to tests/provider/test_opensearch__provider.py diff --git a/tests/test_oracle_provider.py b/tests/provider/test_oracle_provider.py similarity index 99% rename from tests/test_oracle_provider.py rename to tests/provider/test_oracle_provider.py index b4091480b..42e1c3f31 100644 --- a/tests/test_oracle_provider.py +++ b/tests/provider/test_oracle_provider.py @@ -208,7 +208,7 @@ def config_private_synonym(): def config_manipulator(config): return { **config, - "sql_manipulator": "tests.test_oracle_provider.SqlManipulator", + "sql_manipulator": "tests.provider.test_oracle_provider.SqlManipulator", # noqa "sql_manipulator_options": {"foo": "bar"}, } diff --git a/tests/test_parquet_provider.py b/tests/provider/test_parquet_provider.py similarity index 98% rename from tests/test_parquet_provider.py rename to tests/provider/test_parquet_provider.py index 0280f85a8..736e3dff4 100644 --- a/tests/test_parquet_provider.py +++ b/tests/provider/test_parquet_provider.py @@ -1,8 +1,10 @@ # ================================================================= # # Authors: Leo Ghignone +# Tom Kralidis # # Copyright (c) 2024 Leo Ghignone +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -32,7 +34,7 @@ from pygeoapi.provider.base import ProviderItemNotFoundError from pygeoapi.provider.parquet import ParquetProvider -from .util import get_test_file_path +from ..util import get_test_file_path path = get_test_file_path( 'data/random.parquet') diff --git a/tests/test_postgresql_mvt_provider.py b/tests/provider/test_postgresql_mvt_provider.py similarity index 100% rename from tests/test_postgresql_mvt_provider.py rename to tests/provider/test_postgresql_mvt_provider.py diff --git a/tests/test_postgresql_provider.py b/tests/provider/test_postgresql_provider.py similarity index 99% rename from tests/test_postgresql_provider.py rename to tests/provider/test_postgresql_provider.py index bc0827ce6..17e2cb3fe 100644 --- a/tests/test_postgresql_provider.py +++ b/tests/provider/test_postgresql_provider.py @@ -63,7 +63,7 @@ from pygeoapi.util import (yaml_load, geojson_to_geom, get_transform_from_crs, get_crs_from_uri) -from .util import get_test_file_path, mock_api_request +from ..util import get_test_file_path, mock_api_request PASSWORD = os.environ.get('POSTGRESQL_PASSWORD', 'postgres') DEFAULT_CRS = 'http://www.opengis.net/def/crs/OGC/1.3/CRS84' diff --git a/tests/test_rasterio_provider.py b/tests/provider/test_rasterio_provider.py similarity index 97% rename from tests/test_rasterio_provider.py rename to tests/provider/test_rasterio_provider.py index e0dd1f2ac..331ce5799 100644 --- a/tests/test_rasterio_provider.py +++ b/tests/provider/test_rasterio_provider.py @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2021 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -31,7 +31,7 @@ from pygeoapi.provider.rasterio_ import RasterioProvider -from .util import get_test_file_path +from ..util import get_test_file_path path = get_test_file_path( 'tests/data/CMC_glb_TMP_TGL_2_latlon.15x.15_2020081000_P000.grib2') diff --git a/tests/test_sensorthings_edr_provider.py b/tests/provider/test_sensorthings_edr_provider.py similarity index 100% rename from tests/test_sensorthings_edr_provider.py rename to tests/provider/test_sensorthings_edr_provider.py diff --git a/tests/test_sensorthings_provider.py b/tests/provider/test_sensorthings_provider.py similarity index 100% rename from tests/test_sensorthings_provider.py rename to tests/provider/test_sensorthings_provider.py diff --git a/tests/test_socrata_provider.py b/tests/provider/test_socrata_provider.py similarity index 100% rename from tests/test_socrata_provider.py rename to tests/provider/test_socrata_provider.py diff --git a/tests/test_socrata_provider_live.py b/tests/provider/test_socrata_provider_live.py similarity index 100% rename from tests/test_socrata_provider_live.py rename to tests/provider/test_socrata_provider_live.py diff --git a/tests/test_sqlite_geopackage_provider.py b/tests/provider/test_sqlite_geopackage_provider.py similarity index 98% rename from tests/test_sqlite_geopackage_provider.py rename to tests/provider/test_sqlite_geopackage_provider.py index f95934042..c5a26ebce 100644 --- a/tests/test_sqlite_geopackage_provider.py +++ b/tests/provider/test_sqlite_geopackage_provider.py @@ -4,7 +4,7 @@ # Tom Kralidis # # Copyright (c) 2019 Just van den Broecke -# Copyright (c) 2023 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -38,7 +38,7 @@ from pygeoapi.provider.base import ProviderItemNotFoundError from pygeoapi.provider.sqlite import SQLiteGPKGProvider -from .util import get_test_file_path +from ..util import get_test_file_path @pytest.fixture() diff --git a/tests/test_tinydb_catalogue_provider.py b/tests/provider/test_tinydb_catalogue_provider.py similarity index 99% rename from tests/test_tinydb_catalogue_provider.py rename to tests/provider/test_tinydb_catalogue_provider.py index b5b2735db..b3f8f3346 100644 --- a/tests/test_tinydb_catalogue_provider.py +++ b/tests/provider/test_tinydb_catalogue_provider.py @@ -35,7 +35,7 @@ from pygeoapi.provider.base import ProviderItemNotFoundError from pygeoapi.provider.tinydb_ import TinyDBCatalogueProvider -from .util import get_test_file_path +from ..util import get_test_file_path path = get_test_file_path('tests/data/open.canada.ca/sample-records.tinydb') diff --git a/tests/test_tinydb_provider.py b/tests/provider/test_tinydb_provider.py similarity index 99% rename from tests/test_tinydb_provider.py rename to tests/provider/test_tinydb_provider.py index 6a1f96e24..19d8d8f4d 100644 --- a/tests/test_tinydb_provider.py +++ b/tests/provider/test_tinydb_provider.py @@ -36,7 +36,7 @@ ProviderInvalidQueryError) from pygeoapi.provider.tinydb_ import TinyDBProvider -from .util import get_test_file_path +from ..util import get_test_file_path path = get_test_file_path('tests/data/canada-hydat-daily-mean-02HC003.tinydb') diff --git a/tests/test_xarray_netcdf_provider.py b/tests/provider/test_xarray_netcdf_provider.py similarity index 95% rename from tests/test_xarray_netcdf_provider.py rename to tests/provider/test_xarray_netcdf_provider.py index 3546b902c..28ddb8c6f 100644 --- a/tests/test_xarray_netcdf_provider.py +++ b/tests/provider/test_xarray_netcdf_provider.py @@ -1,8 +1,10 @@ # ================================================================= # # Authors: Gregory Petrochenkov +# Tom Kralidis # # Copyright (c) 2021 Gregory Petrochenkov +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -32,7 +34,7 @@ from pygeoapi.provider.base import ProviderQueryError from pygeoapi.provider.xarray_ import XarrayProvider -from .util import get_test_file_path +from ..util import get_test_file_path path = get_test_file_path('tests/data/coads_sst.nc') diff --git a/tests/test_xarray_zarr_provider.py b/tests/provider/test_xarray_zarr_provider.py similarity index 96% rename from tests/test_xarray_zarr_provider.py rename to tests/provider/test_xarray_zarr_provider.py index ec014e655..9b1bdb660 100644 --- a/tests/test_xarray_zarr_provider.py +++ b/tests/provider/test_xarray_zarr_provider.py @@ -1,8 +1,10 @@ # ================================================================= # # Authors: Gregory Petrochenkov +# Tom Kralidis # # Copyright (c) 2021 Gregory Petrochenkov +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -35,7 +37,7 @@ from pygeoapi.provider.xarray_ import XarrayProvider from pygeoapi.util import json_serial -from .util import get_test_file_path +from ..util import get_test_file_path path = get_test_file_path( 'data/analysed_sst.zarr') diff --git a/tests/test_django.py b/tests/test_django.py deleted file mode 100644 index 10af13bc2..000000000 --- a/tests/test_django.py +++ /dev/null @@ -1,41 +0,0 @@ -from http import HTTPStatus -import sys -import os -from unittest import mock - -import django -import pytest -from django.test import Client - -from .util import get_test_file_path - - -@pytest.fixture -@mock.patch.dict(os.environ, { - "DJANGO_SETTINGS_MODULE": "django_.settings", - "PYGEOAPI_CONFIG": get_test_file_path('pygeoapi-test-config.yml'), - "PYGEOAPI_OPENAPI": get_test_file_path('pygeoapi-test-openapi.yml') -}) -@mock.patch.object(sys, "path", sys.path + ["./pygeoapi"]) -def django_(): - django.setup() - return django - - -def test_django_landing_page_loads(django_): - response = Client(SERVER_NAME="localhost").get("/") - - assert response.status_code == HTTPStatus.OK - assert response.json()["title"] == "pygeoapi default instance" - - -def test_django_edr_without_instance_id(django_): - edr_position_query = ("/collections/icoads-sst/position?coords=" - "POINT(12.779895 55.783523)&f=json") - response = Client(SERVER_NAME="localhost").get(edr_position_query) - - assert response.status_code == HTTPStatus.OK - # Validate CoverageJSON is returned - response_json = response.json() - assert response_json["type"] == "Coverage" - assert response_json["domain"]["domainType"] == "PointSeries"