From c8d0625de342b09a1db899aa4ca77398707d803c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 13:25:28 +0000 Subject: [PATCH 1/4] Bump the python-packages group with 6 updates Bumps the python-packages group with 6 updates: | Package | From | To | | --- | --- | --- | | [fastapi[all]](https://github.com/tiangolo/fastapi) | `0.109.2` | `0.110.0` | | [pydantic-settings](https://github.com/pydantic/pydantic-settings) | `2.1.0` | `2.2.1` | | [email-validator](https://github.com/JoshData/python-email-validator) | `2.1.0.post1` | `2.1.1` | | [coverage](https://github.com/nedbat/coveragepy) | `7.4.1` | `7.4.3` | | [pytest](https://github.com/pytest-dev/pytest) | `8.0.0` | `8.1.0` | | [ruff](https://github.com/astral-sh/ruff) | `0.2.1` | `0.3.0` | Updates `fastapi[all]` from 0.109.2 to 0.110.0 - [Release notes](https://github.com/tiangolo/fastapi/releases) - [Commits](https://github.com/tiangolo/fastapi/compare/0.109.2...0.110.0) Updates `pydantic-settings` from 2.1.0 to 2.2.1 - [Release notes](https://github.com/pydantic/pydantic-settings/releases) - [Commits](https://github.com/pydantic/pydantic-settings/compare/v2.1.0...v2.2.1) Updates `email-validator` from 2.1.0.post1 to 2.1.1 - [Release notes](https://github.com/JoshData/python-email-validator/releases) - [Changelog](https://github.com/JoshData/python-email-validator/blob/main/CHANGELOG.md) - [Commits](https://github.com/JoshData/python-email-validator/commits/v2.1.1) Updates `coverage` from 7.4.1 to 7.4.3 - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.4.1...7.4.3) Updates `pytest` from 8.0.0 to 8.1.0 - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.0.0...8.1.0) Updates `ruff` from 0.2.1 to 0.3.0 - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.2.1...v0.3.0) --- updated-dependencies: - dependency-name: fastapi[all] dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-packages - dependency-name: pydantic-settings dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-packages - dependency-name: email-validator dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-packages - dependency-name: ruff dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- pyproject.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 16aff43..bc4117e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,13 +10,13 @@ classifiers = [ ] readme = { file = "./README.md", content-type = "text/markdown" } dependencies = [ - "fastapi[all] == 0.109.2", + "fastapi[all] == 0.110.0", "uvicorn == 0.27.1", "pyyaml == 6.0.1", "geojson_pydantic == 1.0.2", "pyproj == 3.6.1", - "pydantic-settings == 2.1.0", - "email-validator == 2.1.0.post1", + "pydantic-settings == 2.2.1", + "email-validator == 2.1.1", "geodense == 1.0.0", ] requires-python = ">=3.11.4" @@ -25,10 +25,10 @@ dynamic = ["version"] [project.optional-dependencies] dev = [ "black == 24.2.0", - "coverage == 7.4.1", + "coverage == 7.4.3", "mypy == 1.8.0", - "pytest == 8.0.0", - "ruff == 0.2.1", + "pytest == 8.1.0", + "ruff == 0.3.0", "types-ujson == 5.9.0.0", "types-PyYAML == 6.0.12.12", "pytest-asyncio == 0.23.5", From 07ffe31986e5f158188507de3e0e24abce75a428 Mon Sep 17 00:00:00 2001 From: Wouter Date: Tue, 5 Mar 2024 10:20:55 +0100 Subject: [PATCH 2/4] added 2d with epoch test --- tests/data/test_2d_with_epoch.json | 8 ++++++++ tests/test_geojson_transformation.py | 11 +++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/data/test_2d_with_epoch.json diff --git a/tests/data/test_2d_with_epoch.json b/tests/data/test_2d_with_epoch.json new file mode 100644 index 0000000..4b75d45 --- /dev/null +++ b/tests/data/test_2d_with_epoch.json @@ -0,0 +1,8 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [663000.0, 5781000.0] + } +} diff --git a/tests/test_geojson_transformation.py b/tests/test_geojson_transformation.py index a279a04..50d0525 100644 --- a/tests/test_geojson_transformation.py +++ b/tests/test_geojson_transformation.py @@ -162,6 +162,17 @@ def test_validate_crs_transformed_geojson(feature): validate_crs_transformed_geojson(feature_no_exc) +def test_2d_with_epoch(): + with open("tests/data/test_2d_with_epoch.json") as f: + data = json.load(f) + feature_2d = Feature(**data) + feature_2d_org = Feature(**data) + + crs_transform(feature_2d, "EPSG:3043", "EPSG:32631", 2024) + + assert feature_2d == feature_2d_org + + def test_wgs_epoch(): with open("tests/data/test_wgs_epoch.json") as f: data = json.load(f) From 0588c4a4238a6279662a31566024ade11a08f912 Mon Sep 17 00:00:00 2001 From: Wouter Date: Tue, 5 Mar 2024 14:13:25 +0100 Subject: [PATCH 3/4] mv logic -> own def, added & update tests --- .vscode/launch.json | 20 ++++---- .../crs_transform.py | 37 ++++++++++---- tests/test_geojson_transformation.py | 49 +++++++++++++++++-- tests/test_transformer_selection.py | 19 ++++++- 4 files changed, 101 insertions(+), 24 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index fb3c504..918d5a1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -27,16 +27,16 @@ }, "jinja": true, "justMyCode": false - }, - { - "name": "Python: Debug Tests", - "type": "debugpy", - "request": "launch", - "module": "pytest", - "args": ["${file}"], - "purpose": ["debug-test"], - "console": "integratedTerminal", - "justMyCode": false } + // { + // "name": "Python: Debug Tests", + // "type": "debugpy", + // "request": "launch", + // "module": "pytest", + // "args": ["${file}"], + // "purpose": ["debug-test"], + // "console": "integratedTerminal", + // "justMyCode": false + // } ] } diff --git a/src/coordinate_transformation_api/crs_transform.py b/src/coordinate_transformation_api/crs_transform.py index f78af26..7c036ba 100644 --- a/src/coordinate_transformation_api/crs_transform.py +++ b/src/coordinate_transformation_api/crs_transform.py @@ -341,6 +341,32 @@ def get_individual_epsg_code(compound_crs: CRS) -> tuple[str, str]: return (f"{horizontal[0]}:{horizontal[1]}", f"{vertical[0]}:{vertical[1]}") +def build_input_coord(coord: CoordinatesType, epoch: float | None) -> CoordinatesType: + + # When 2D input is given with an epoch we need to add a height. So pyproj knows to + # that the epoch is an epoch and not the height, without this intervention the epoch + # would be place in the firth position of the tuple. + if len(coord) == TWO_DIMENSIONAL and epoch is not None: + return tuple([*coord, 0.0, epoch]) + + # Default behaviour + # The input_coord == coord that are given. When an epoch is provided with a 3D coord + # this is added or the value None is given for any other. Note: with 2D the additional None + # is the height. But this doesn't influence the result, because it's None. + input_coord = tuple( + [ + *coord, + ( + float(epoch) + if len(coord) == THREE_DIMENSIONAL and epoch is not None + else None + ), + ] + ) + + return input_coord + + def get_transform_crs_fun( # source_crs: str, target_crs: str, @@ -414,16 +440,7 @@ def transform_crs(val: CoordinatesType) -> tuple[float, ...]: # when one of the src or tgt crs has a dynamic time component # or the transformation used has a datetime component # for now simple check on coords length (which is not correct) - input = tuple( - [ - *val, - ( - float(epoch) - if len(val) == THREE_DIMENSIONAL and epoch is not None - else None - ), - ] - ) + input = build_input_coord(val, epoch) # GeoJSON and CityJSON by definition has coordinates always in lon-lat-height (or x-y-z) order. Transformer has been created with `always_xy=True`, # to ensure input and output coordinates are in in lon-lat-height (or x-y-z) order. diff --git a/tests/test_geojson_transformation.py b/tests/test_geojson_transformation.py index 50d0525..ec474fe 100644 --- a/tests/test_geojson_transformation.py +++ b/tests/test_geojson_transformation.py @@ -165,12 +165,55 @@ def test_validate_crs_transformed_geojson(feature): def test_2d_with_epoch(): with open("tests/data/test_2d_with_epoch.json") as f: data = json.load(f) - feature_2d = Feature(**data) + feature_2d_2000 = Feature(**data) + feature_2d_2020 = Feature(**data) feature_2d_org = Feature(**data) - crs_transform(feature_2d, "EPSG:3043", "EPSG:32631", 2024) + crs_transform(feature_2d_2000, "EPSG:3043", "EPSG:32631", 2000) + crs_transform(feature_2d_2020, "EPSG:3043", "EPSG:32631", 2020) - assert feature_2d == feature_2d_org + assert feature_2d_2000 != feature_2d_org + assert feature_2d_2020 != feature_2d_org + + coords_2000 = feature_2d_2000.geometry.coordinates + coords_2020 = feature_2d_2020.geometry.coordinates + coords_org = feature_2d_org.geometry.coordinates + + dif_2000_org = 0.29 + dif_2020_org = 0.76 + + assert ( + round( + math.sqrt( + ( + (coords_2000[0] - coords_org[0]) + * (coords_2000[0] - coords_org[0]) + ) + + ( + (coords_2000[1] - coords_org[1]) + * (coords_2000[1] - coords_org[1]) + ) + ), + 2, + ) + == dif_2000_org + ) + assert ( + round( + math.sqrt( + ( + (coords_2020[0] - coords_org[0]) + * (coords_2020[0] - coords_org[0]) + ) + + ( + (coords_2020[1] - coords_org[1]) + * (coords_2020[1] - coords_org[1]) + ) + ), + 2, + ) + == dif_2020_org + ) def test_wgs_epoch(): diff --git a/tests/test_transformer_selection.py b/tests/test_transformer_selection.py index a1b807a..b7795e5 100644 --- a/tests/test_transformer_selection.py +++ b/tests/test_transformer_selection.py @@ -1,5 +1,9 @@ import pytest -from coordinate_transformation_api.crs_transform import get_transformer, needs_epoch +from coordinate_transformation_api.crs_transform import ( + build_input_coord, + get_transformer, + needs_epoch, +) # This test needs the modified proj.time.dependent.transformations.db from @@ -17,3 +21,16 @@ ) def test_time_dependant_operation_method(source, target, epoch, expectation): assert needs_epoch(get_transformer(source, target, epoch)) == expectation + + +@pytest.mark.parametrize( + ("coord", "epoch", "expectation"), + [ + (tuple([1000.0, 1000.0]), 2000.0, tuple([1000.0, 1000.0, 0.0, 2000.0])), + (tuple([1000.0, 1000.0]), None, tuple([1000.0, 1000.0, None])), + (tuple([1000.0, 1000.0, 10.0]), 2000.0, tuple([1000.0, 1000.0, 10.0, 2000.0])), + (tuple([1000.0, 1000.0, 10.0]), None, tuple([1000.0, 1000.0, 10.0, None])), + ], +) +def test_build_input_coord(coord, epoch, expectation): + assert build_input_coord(coord, epoch) == expectation From 6b1f8618683a995049817a6f63374fd948c3a7bb Mon Sep 17 00:00:00 2001 From: Wouter Date: Tue, 5 Mar 2024 14:15:20 +0100 Subject: [PATCH 4/4] fix launch.json --- .vscode/launch.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 918d5a1..fb3c504 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -27,16 +27,16 @@ }, "jinja": true, "justMyCode": false + }, + { + "name": "Python: Debug Tests", + "type": "debugpy", + "request": "launch", + "module": "pytest", + "args": ["${file}"], + "purpose": ["debug-test"], + "console": "integratedTerminal", + "justMyCode": false } - // { - // "name": "Python: Debug Tests", - // "type": "debugpy", - // "request": "launch", - // "module": "pytest", - // "args": ["${file}"], - // "purpose": ["debug-test"], - // "console": "integratedTerminal", - // "justMyCode": false - // } ] }