From 0398a7e6d90000b8d8e89d84d4b59857550b7332 Mon Sep 17 00:00:00 2001 From: Rohan Weeden Date: Fri, 3 Oct 2025 18:02:42 -0400 Subject: [PATCH 1/2] Add ruff format check --- .github/workflows/lint.yml | 10 + geo_extensions/transformations/cartesian.py | 23 +- geo_extensions/transformations/general.py | 1 + geo_extensions/transformations/geodetic.py | 1 + pyproject.toml | 7 + tests/conftest.py | 53 +- tests/test_checks.py | 72 ++- tests/test_geo_extensions.py | 26 +- tests/test_transformations.py | 562 +++++++++++--------- tests/test_transformer.py | 199 ++++--- 10 files changed, 562 insertions(+), 392 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 84431ce..578b70e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,6 +20,16 @@ jobs: max_line_length: 120 plugins: flake8-isort==6.1.2 flake8-quotes==3.4.0 flake8-commas==4.0.0 + ruff-format: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/ruff-action@v3 + with: + version: "~=0.13.3" + args: format --check --diff --output-format=github + mypy: runs-on: ubuntu-latest diff --git a/geo_extensions/transformations/cartesian.py b/geo_extensions/transformations/cartesian.py index 416abd0..29c24ca 100644 --- a/geo_extensions/transformations/cartesian.py +++ b/geo_extensions/transformations/cartesian.py @@ -104,20 +104,26 @@ def split(polygon: Polygon) -> TransformationResult: def _shift_polygon(polygon: Polygon) -> Polygon: """Shift into [0, 360) range.""" - return Polygon([ - ((360.0 + lon) % 360, lat) - for lon, lat in polygon.exterior.coords - ]) + return Polygon( + [ + # ruff hint + ((360.0 + lon) % 360, lat) + for lon, lat in polygon.exterior.coords + ] + ) def _shift_polygon_back(polygon: Polygon) -> Polygon: """Shift back to [-180, 180] range.""" _, _, max_lon, _ = polygon.bounds - return Polygon([ - (_adjust_lon(lon, max_lon), lat) - for lon, lat in polygon.exterior.coords - ]) + return Polygon( + [ + # ruff hint + (_adjust_lon(lon, max_lon), lat) + for lon, lat in polygon.exterior.coords + ] + ) def _adjust_lon(lon: float, max_lon: float) -> float: @@ -136,6 +142,7 @@ def _split_polygon( split_collection = shapely.ops.split(polygon, line) return [ + # ruff hint orient(geom) for geom in split_collection.geoms if isinstance(geom, Polygon) and not _ignore_polygon(geom) diff --git a/geo_extensions/transformations/general.py b/geo_extensions/transformations/general.py index e01eb73..be5ee7a 100644 --- a/geo_extensions/transformations/general.py +++ b/geo_extensions/transformations/general.py @@ -17,6 +17,7 @@ def drop_z_coordinate(polygon: Polygon) -> TransformationResult: yield Polygon( shell=((x, y) for x, y, *_ in polygon.exterior.coords), holes=[ + # ruff hint ((x, y) for x, y, *_ in interior.coords) for interior in polygon.interiors ], diff --git a/geo_extensions/transformations/geodetic.py b/geo_extensions/transformations/geodetic.py index d2aaf7f..131dc1c 100644 --- a/geo_extensions/transformations/geodetic.py +++ b/geo_extensions/transformations/geodetic.py @@ -49,6 +49,7 @@ def densify(polygon: Polygon) -> TransformationResult: yield Polygon( shell=_densify_ring(polygon.exterior.coords, tolerance_meters), holes=[ + # ruff hint _densify_ring(interior.coords, tolerance_meters) for interior in polygon.interiors ], diff --git a/pyproject.toml b/pyproject.toml index 137bb1a..00cb931 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,3 +27,10 @@ types-shapely = "^2.0.3" [tool.isort] profile = "black" + +[tool.ruff] +line-length = 120 + +[tool.ruff.lint] +# Add the `line-too-long` rule to the enforced rule set. +extend-select = ["E501"] diff --git a/tests/conftest.py b/tests/conftest.py index 1adcbc7..7a8ac4b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -12,10 +12,15 @@ def data_path(): @pytest.fixture def rectangle(): """A rectanglular polygon""" - polygon = Polygon([ - (160., 60.), (170., 60.), - (170., 70.), (160., 70.), (160., 60.), - ]) + polygon = Polygon( + [ + (160.0, 60.0), + (170.0, 60.0), + (170.0, 70.0), + (160.0, 70.0), + (160.0, 60.0), + ] + ) assert polygon.exterior.is_ccw assert polygon.exterior.is_valid @@ -25,10 +30,15 @@ def rectangle(): @pytest.fixture def centered_rectangle(): """A rectanglular polygon centered at 0, 0""" - polygon = Polygon([ - (-30., 10.), (-30., -10.), - (30., -10.), (30., 10.), (-30., 10.), - ]) + polygon = Polygon( + [ + (-30.0, 10.0), + (-30.0, -10.0), + (30.0, -10.0), + (30.0, 10.0), + (-30.0, 10.0), + ] + ) assert polygon.exterior.is_ccw assert polygon.exterior.is_valid @@ -38,10 +48,15 @@ def centered_rectangle(): @pytest.fixture def antimeridian_centered_rectangle(): """A rectanglular polygon centered over the antimeridian""" - polygon = Polygon([ - (150., 10.), (150., -10.), - (-150., -10.), (-150., 10.), (150., 10.), - ]) + polygon = Polygon( + [ + (150.0, 10.0), + (150.0, -10.0), + (-150.0, -10.0), + (-150.0, 10.0), + (150.0, 10.0), + ] + ) assert not polygon.exterior.is_ccw assert polygon.exterior.is_valid @@ -57,10 +72,16 @@ def multi_crossing_polygon(): | \ -------- """ - polygon = Polygon([ - (150., -10.), (-150., -10.), (160., 0.), - (-150., 10.), (150., 10.), (150., -10.), - ]) + polygon = Polygon( + [ + (150.0, -10.0), + (-150.0, -10.0), + (160.0, 0.0), + (-150.0, 10.0), + (150.0, 10.0), + (150.0, -10.0), + ] + ) assert not polygon.exterior.is_ccw assert not polygon.exterior.is_valid diff --git a/tests/test_checks.py b/tests/test_checks.py index aafd308..0756eba 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -17,10 +17,17 @@ def test_polygon_crosses_antimeridian_ccw_tricky(): / \ -------- """ - polygon = Polygon([ - (-30., 10.), (-10., 0.), (-30., -10.), - (30., -10.), (10., 0.), (30., 10.), (-30., 10.), - ]) + polygon = Polygon( + [ + (-30.0, 10.0), + (-10.0, 0.0), + (-30.0, -10.0), + (30.0, -10.0), + (10.0, 0.0), + (30.0, 10.0), + (-30.0, 10.0), + ] + ) assert polygon_crosses_antimeridian_ccw(polygon) is False @@ -31,10 +38,17 @@ def test_polygon_crosses_antimeridian_ccw_tricky_crosses(): / \ -------- """ - polygon = Polygon([ - (150., 10.), (170., 0.), (150., -10.), - (-150., 10.), (-170., 0.), (-150., -10.), (150., 10.), - ]) + polygon = Polygon( + [ + (150.0, 10.0), + (170.0, 0.0), + (150.0, -10.0), + (-150.0, 10.0), + (-170.0, 0.0), + (-150.0, -10.0), + (150.0, 10.0), + ] + ) assert polygon_crosses_antimeridian_ccw(polygon) is True @@ -50,12 +64,14 @@ def test_polygon_crosses_antimeridian_ccw_alos2_antarctica(): ALOS2 granule: ALOS2075945400-151019-WBDR1.1__D """ - polygon = Polygon([ - (-178.328, -79.438), - (179.625, -76.163), - (166.084, -76.163), - (164.037, -79.438), - ]) + polygon = Polygon( + [ + (-178.328, -79.438), + (179.625, -76.163), + (166.084, -76.163), + (164.037, -79.438), + ] + ) assert polygon_crosses_antimeridian_ccw(polygon) is True @@ -72,10 +88,17 @@ def test_polygon_crosses_antimeridian_fixed_size_tricky_crosses(): / \ -------- """ - polygon = Polygon([ - (150., 10.), (170., 0.), (150., -10.), - (-150., 10.), (-170., 0.), (-150., -10.), (150., 10.), - ]) + polygon = Polygon( + [ + (150.0, 10.0), + (170.0, 0.0), + (150.0, -10.0), + (-150.0, 10.0), + (-170.0, 0.0), + (-150.0, -10.0), + (150.0, 10.0), + ] + ) assert polygon_crosses_antimeridian_fixed_size(polygon, 30) is True @@ -83,8 +106,13 @@ def test_polygon_crosses_antimeridian_fixed_size_antarctica(): r"""A real polygon from ALOS2 granule ALOS2014555550-140830 which is located close to the south pole, and also crosses the antimeridian """ - polygon = Polygon([ - (-164.198, -82.125), (172.437, -83.885), (165.618, -80.869), - (-176.331, -79.578), (-164.198, -82.125), - ]) + polygon = Polygon( + [ + (-164.198, -82.125), + (172.437, -83.885), + (165.618, -80.869), + (-176.331, -79.578), + (-164.198, -82.125), + ] + ) assert polygon_crosses_antimeridian_fixed_size(polygon, 40) is True diff --git a/tests/test_geo_extensions.py b/tests/test_geo_extensions.py index 90bca8e..52c3f1f 100644 --- a/tests/test_geo_extensions.py +++ b/tests/test_geo_extensions.py @@ -10,18 +10,22 @@ def test_default_transformer(data_path): wkt_path = data_path / "OPERA_L2_RTC-S1_T114-243299-IW1_20230722T122534Z_20230818T184635Z_S1A_30_v0.4.wkt" - transformer = Transformer([ - split_polygon_on_antimeridian_ccw, - simplify_polygon(0.1), - ]) + transformer = Transformer( + [ + split_polygon_on_antimeridian_ccw, + simplify_polygon(0.1), + ] + ) polygons = transformer.from_wkt(wkt_path.read_text()) assert polygons == [ - Polygon([ - (-64.18242781701073, 80.92318071697005), - (-68.40445755029818, 81.31609026531473), - (-68.93161319601728, 81.16999707795055), - (-64.74688665108201, 80.78217738556877), - (-64.18242781701073, 80.92318071697005), - ]), + Polygon( + [ + (-64.18242781701073, 80.92318071697005), + (-68.40445755029818, 81.31609026531473), + (-68.93161319601728, 81.16999707795055), + (-64.74688665108201, 80.78217738556877), + (-64.18242781701073, 80.92318071697005), + ] + ), ] diff --git a/tests/test_transformations.py b/tests/test_transformations.py index 5afc007..99f211c 100644 --- a/tests/test_transformations.py +++ b/tests/test_transformations.py @@ -15,40 +15,48 @@ def test_simplify(): - polygon = Polygon([ - (20, 0), - (20, 0), - (20, 10), - (0, 10), - (0, 0), - (20, 0), - ]) - assert list(simplify_polygon(0.01)(polygon)) == [ - Polygon([ + polygon = Polygon( + [ + (20, 0), (20, 0), (20, 10), (0, 10), (0, 0), (20, 0), - ]), + ] + ) + assert list(simplify_polygon(0.01)(polygon)) == [ + Polygon( + [ + (20, 0), + (20, 10), + (0, 10), + (0, 0), + (20, 0), + ] + ), ] def test_simplify_line(): - polygon = Polygon([ - (20, 0), - (20, 10), - (20, 10), - (20, 0), - (20, 0), - ]) - assert list(simplify_polygon(0.01)(polygon)) == [ - Polygon([ + polygon = Polygon( + [ (20, 0), (20, 10), (20, 10), (20, 0), - ]), + (20, 0), + ] + ) + assert list(simplify_polygon(0.01)(polygon)) == [ + Polygon( + [ + (20, 0), + (20, 10), + (20, 10), + (20, 0), + ] + ), ] assert list(simplify_polygon(0.01, preserve_topology=False)(polygon)) == [ @@ -57,24 +65,28 @@ def test_simplify_line(): def test_densify(): - polygon = Polygon([ - (50, 75), - (10, 80), - (0, 77), - (40, 70), - (50, 75), - ]) - - assert list(densify_polygon(50_000)(polygon)) == [ - Polygon([ + polygon = Polygon( + [ (50, 75), - (34.100003241169595, 78.2028289318241), (10, 80), (0, 77), - (24.297878219303588, 74.40374356383884), (40, 70), (50, 75), - ]), + ] + ) + + assert list(densify_polygon(50_000)(polygon)) == [ + Polygon( + [ + (50, 75), + (34.100003241169595, 78.2028289318241), + (10, 80), + (0, 77), + (24.297878219303588, 74.40374356383884), + (40, 70), + (50, 75), + ] + ), ] @@ -125,18 +137,21 @@ def test_densify_with_holes(): def test_densify_idempotent(): - polygon = Polygon([ - (50, 75), - (10, 80), - (0, 77), - (40, 70), - (50, 75), - ]) + polygon = Polygon( + [ + (50, 75), + (10, 80), + (0, 77), + (40, 70), + (50, 75), + ] + ) transformation = densify_polygon(50_000) densified_polygons = list(transformation(polygon)) double_densified_polygons = [ + # ruff hint poly for densified_polygon in densified_polygons for poly in transformation(densified_polygon) @@ -155,32 +170,38 @@ def test_densify_error(): def test_drop_z_coordinate(): - polygon = Polygon([ - (180, 1, 10), - (180, 0, 10), - (-179.999, 0, 10), - (-179.999, 1, 10), - (180, 1, 10), - ]) + polygon = Polygon( + [ + (180, 1, 10), + (180, 0, 10), + (-179.999, 0, 10), + (-179.999, 1, 10), + (180, 1, 10), + ] + ) assert list(drop_z_coordinate(polygon)) == [ - Polygon([ + Polygon( + [ + (180, 1), + (180, 0), + (-179.999, 0), + (-179.999, 1), + (180, 1), + ] + ), + ] + + +def test_drop_z_coordinate_noop(): + polygon = Polygon( + [ (180, 1), (180, 0), (-179.999, 0), (-179.999, 1), (180, 1), - ]), - ] - - -def test_drop_z_coordinate_noop(): - polygon = Polygon([ - (180, 1), - (180, 0), - (-179.999, 0), - (-179.999, 1), - (180, 1), - ]) + ] + ) assert list(drop_z_coordinate(polygon)) == [polygon] @@ -237,9 +258,15 @@ def test_split_polygon_on_antimeridian_ccw_returns_non_empty_list(polygon): def test_split_polygon_on_antimeridian_ccw_returns_empty_list(): # There is a case where the input polygon is really small, and both split # parts are culled. - polygon = Polygon([ - (180, 1), (180, 0), (-179.999, 0), (-179.999, 1), (180, 1), - ]) + polygon = Polygon( + [ + (180, 1), + (180, 0), + (-179.999, 0), + (-179.999, 1), + (180, 1), + ] + ) assert list(split_polygon_on_antimeridian_ccw(polygon)) == [] @@ -264,20 +291,24 @@ def test_split_polygon_on_antimeridian_ccw_centered(antimeridian_centered_rectan assert poly.exterior.is_valid assert polygons == [ - Polygon([ - (180., -10), - (180., 10.), - (150., 10.), - (150., -10), - (180., -10), - ]), - Polygon([ - (-180., 10), - (-180., -10.), - (-150., -10.), - (-150., 10), - (-180., 10), - ]), + Polygon( + [ + (180.0, -10), + (180.0, 10.0), + (150.0, 10.0), + (150.0, -10), + (180.0, -10), + ] + ), + Polygon( + [ + (-180.0, 10), + (-180.0, -10.0), + (-150.0, -10.0), + (-150.0, 10), + (-180.0, 10), + ] + ), ] @@ -293,26 +324,33 @@ def test_split_polygon_on_antimeridian_ccw_crosses_multiple_times( assert poly.exterior.is_valid assert polygons == [ - Polygon([ - (180., -10), - (180., -4), - (160., 0), - (180., 4), - (180., 10), - (150., 10), - (150., -10), - ]), - Polygon([(-180., -4), (-180., -10), (-150., -10), (-180., -4)]), - Polygon([(-180., 10), (-180., 4), (-150., 10), (-180., 10)]), + Polygon( + [ + (180.0, -10), + (180.0, -4), + (160.0, 0), + (180.0, 4), + (180.0, 10), + (150.0, 10), + (150.0, -10), + ] + ), + Polygon([(-180.0, -4), (-180.0, -10), (-150.0, -10), (-180.0, -4)]), + Polygon([(-180.0, 10), (-180.0, 4), (-150.0, 10), (-180.0, 10)]), ] def test_split_polygon_on_antimeridian_ccw_west(): """Polygon is mostly west of the IDL""" - polygon = Polygon([ - (170., 70.), (170., 60.), (-179., 60.), - (-179., 70.), (170., 70.), - ]) + polygon = Polygon( + [ + (170.0, 70.0), + (170.0, 60.0), + (-179.0, 60.0), + (-179.0, 70.0), + (170.0, 70.0), + ] + ) assert not polygon.exterior.is_ccw polygons = list(split_polygon_on_antimeridian_ccw(polygon)) @@ -321,29 +359,38 @@ def test_split_polygon_on_antimeridian_ccw_west(): assert poly.exterior.is_valid assert polygons == [ - Polygon([ - (180., 60.), - (180., 70.), - (170., 70.), - (170., 60.), - (180., 60.), - ]), - Polygon([ - (-180., 70.), - (-180., 60.), - (-179., 60.), - (-179., 70.), - (-180., 70.), - ]), + Polygon( + [ + (180.0, 60.0), + (180.0, 70.0), + (170.0, 70.0), + (170.0, 60.0), + (180.0, 60.0), + ] + ), + Polygon( + [ + (-180.0, 70.0), + (-180.0, 60.0), + (-179.0, 60.0), + (-179.0, 70.0), + (-180.0, 70.0), + ] + ), ] def test_split_polygon_on_antimeridian_ccw_east(): """Polygon is mostly east of the IDL""" - polygon = Polygon([ - (179., 70.), (179., 60.), (-170., 60.), - (-170., 70.), (179., 70.), - ]) + polygon = Polygon( + [ + (179.0, 70.0), + (179.0, 60.0), + (-170.0, 60.0), + (-170.0, 70.0), + (179.0, 70.0), + ] + ) assert not polygon.exterior.is_ccw polygons = list(split_polygon_on_antimeridian_ccw(polygon)) @@ -352,30 +399,38 @@ def test_split_polygon_on_antimeridian_ccw_east(): assert poly.exterior.is_valid assert polygons == [ - Polygon([ - (180., 60.), - (180., 70.), - (179., 70.), - (179., 60.), - (180., 60.), - ]), - Polygon([ - (-180., 70.), - (-180., 60.), - (-170., 60.), - (-170., 70.), - (-180., 70.), - ]), + Polygon( + [ + (180.0, 60.0), + (180.0, 70.0), + (179.0, 70.0), + (179.0, 60.0), + (180.0, 60.0), + ] + ), + Polygon( + [ + (-180.0, 70.0), + (-180.0, 60.0), + (-170.0, 60.0), + (-170.0, 70.0), + (-180.0, 70.0), + ] + ), ] def test_split_polygon_on_antimeridian_ccw_close_point(): """Polygon has a point that is extremely close to the antimeridian""" - polygon = Polygon([ - (179.999999, 70.), - (179., 60.), (-170., 60.), - (-170., 70.), (179., 70.), - ]) + polygon = Polygon( + [ + (179.999999, 70.0), + (179.0, 60.0), + (-170.0, 60.0), + (-170.0, 70.0), + (179.0, 70.0), + ] + ) assert not polygon.exterior.is_ccw polygons = list(split_polygon_on_antimeridian_ccw(polygon)) @@ -387,31 +442,33 @@ def test_split_polygon_on_antimeridian_ccw_close_point(): coords = [list(poly.boundary.coords) for poly in polygons] assert coords == [ [ - (180., 60.), - (180., 70.), - (179.999999, 70.), - (179., 60.), - (180., 60.), + (180.0, 60.0), + (180.0, 70.0), + (179.999999, 70.0), + (179.0, 60.0), + (180.0, 60.0), ], [ - (-180., 70.), - (-180., 60.), - (-170., 60.), - (-170., 70.), - (-180., 70.), + (-180.0, 70.0), + (-180.0, 60.0), + (-170.0, 60.0), + (-170.0, 70.0), + (-180.0, 70.0), ], ] def test_split_polygon_on_antimeridian_ccw_alos_example(): """Example from ALOS mission: ALPSRP237090990-L1.1""" - polygon = Polygon([ - (179.648, 50.172), - (179.794, 49.658), - (-179.255, 49.766), - (-179.392, 50.281), - (179.648, 50.172), - ]) + polygon = Polygon( + [ + (179.648, 50.172), + (179.794, 49.658), + (-179.255, 49.766), + (-179.392, 50.281), + (179.648, 50.172), + ] + ) polygons = list(split_polygon_on_antimeridian_ccw(polygon)) for poly in polygons: @@ -422,30 +479,32 @@ def test_split_polygon_on_antimeridian_ccw_alos_example(): coords = [list(poly.boundary.coords) for poly in polygons] assert coords == [ [ - (180., 49.68139432176656), - (180., 50.21196666666666), + (180.0, 49.68139432176656), + (180.0, 50.21196666666666), (179.64800000000002, 50.172), (179.79399999999998, 49.658), - (180., 49.68139432176656), + (180.0, 49.68139432176656), ], [ - (-180., 50.21196666666666), - (-180., 49.68139432176656), + (-180.0, 50.21196666666666), + (-180.0, 49.68139432176656), (-179.255, 49.766), (-179.392, 50.281), - (-180., 50.21196666666666), + (-180.0, 50.21196666666666), ], ] def test_split_polygon_on_antimeridian_ccw_alos2_example(): """ALOS2 granule: ALOS2075945400-151019-WBDR1.1__D""" - polygon = Polygon([ - (-178.328, -79.438), - (179.625, -76.163), - (166.084, -76.163), - (164.037, -79.438), - ]) + polygon = Polygon( + [ + (-178.328, -79.438), + (179.625, -76.163), + (166.084, -76.163), + (164.037, -79.438), + ] + ) polygons = list(split_polygon_on_antimeridian_ccw(polygon)) for poly in polygons: @@ -456,18 +515,18 @@ def test_split_polygon_on_antimeridian_ccw_alos2_example(): coords = [list(poly.boundary.coords) for poly in polygons] assert coords == [ [ - (-180., -76.76296336101612), - (-180., -79.438), + (-180.0, -76.76296336101612), + (-180.0, -79.438), (-178.328, -79.438), - (-180., -76.76296336101612), + (-180.0, -76.76296336101612), ], [ - (180., -79.438), - (180., -76.76296336101612), + (180.0, -79.438), + (180.0, -76.76296336101612), (179.625, -76.163), (166.08400000000006, -76.163), (164.03700000000003, -79.438), - (180., -79.438), + (180.0, -79.438), ], ] @@ -494,18 +553,18 @@ def test_split_polygon_on_antimeridian_ccw_opera_example(): coords = [list(poly.boundary.coords) for poly in polygons] assert coords == [ [ - (180., 66.140), - (180., 66.663), + (180.0, 66.140), + (180.0, 66.663), (178.83400000000006, 66.663), (178.83400000000006, 66.140), - (180., 66.140), + (180.0, 66.140), ], [ - (-180., 66.663), - (-180., 66.140), + (-180.0, 66.663), + (-180.0, 66.140), (-178.918, 66.140), (-178.918, 66.663), - (-180., 66.663), + (-180.0, 66.663), ], ] @@ -515,14 +574,16 @@ def test_split_polygon_on_antimeridian_ccw_opera_example_pre_split(): OPERA_L2_CSLC-S1_T001-000688-IW1_20250504T183220Z_20250505T112029Z_S1A_VV_v1.1 """ - polygon = Polygon([ - (180, 64.67712437067621), - (180, 64.50629047887854), - (179.9988239237079, 64.50640025835617), - (179.9167734717595, 64.51400884003007), - (179.999315144991, 64.6771877237759), - (180, 64.67712437067621), - ]) + polygon = Polygon( + [ + (180, 64.67712437067621), + (180, 64.50629047887854), + (179.9988239237079, 64.50640025835617), + (179.9167734717595, 64.51400884003007), + (179.999315144991, 64.6771877237759), + (180, 64.67712437067621), + ] + ) assert not polygon.exterior.is_ccw polygons = list(split_polygon_on_antimeridian_ccw(polygon)) @@ -546,65 +607,67 @@ def test_split_polygon_on_antimeridian_ccw_opera_example_pre_split(): def test_split_polygon_on_antimeridian_ccw_sentinel_ocn_example(): """Sentinel-1 granule: S1A_WV_OCN__2SSV_20250417T170934_20250417T172302_058799_07490A_662C""" - polygon = Polygon([ - (-173.31352985574108, -23.14698567224461), - (-173.77162229214494, -24.907619019866505), - (-174.2415526063507, -26.665847671745183), - (-174.735358150903, -28.420448333916106), - (-175.23380277184344, -30.175206972263744), - (-175.74843654546004, -31.927869767925337), - (-176.2807594129271, -33.67798464336149), - (-176.84487055921355, -35.423184310947256), - (-177.41910677624742, -37.16801395691638), - (-178.0174237891529, -38.90994274849644), - (-178.6424368542418, -40.64852489269256), - (-179.29727678081028, -42.38361736393), - (-179.99919575326913, -44.11165778890455), - (179.27499973531806, -45.83867913785123), - (178.50719394616408, -47.561023088516535), - (177.69231780926836, -49.27817128078806), - (176.80904931895057, -50.986415957829536), - (175.87985821681252, -52.69120887337212), - (174.8814954194563, -54.38819050545594), - (173.80356416208477, -56.07742986626234), - (172.6342022987177, -57.75707684914518), - (171.3430337906186, -59.42214751260288), - (169.94378551545861, -61.077752113025916), - (168.3999709466183, -62.71805533391731), - (166.6843566389666, -64.34111371291355), - (164.74985524368935, -65.9397497607168), - (162.5883735575569, -67.5152692747083), - (160.1325459675333, -69.06048810117184), - (154.88126113623596, -68.86722808467104), - (157.66232733899088, -67.40109715863518), - (160.11788634153672, -65.89157783252615), - (162.30350978708452, -64.34830642665239), - (164.26115705334965, -62.776359315577984), - (166.0243795283944, -61.18062028554268), - (167.62930602018182, -59.5668614442984), - (169.08373088867933, -57.93420475768521), - (170.41560899457167, -56.28647419580335), - (171.64130903910598, -54.625361215229724), - (172.78119311087207, -52.95574121072587), - (173.83243861741815, -51.273905612708624), - (174.81205988512076, -49.58367135376619), - (175.72884840278266, -47.885484758555855), - (176.58940809511245, -46.18095578091026), - (177.407673659417, -44.471546605796334), - (178.17413248284223, -42.75510333566816), - (178.90089160626385, -41.03375212942789), - (179.59202341272197, -39.307739657248156), - (-179.74246296618378, -37.57885571562622), - (-179.11269276255436, -35.84470103625437), - (-178.50911206250385, -34.10700088461006), - (-177.92939864490123, -32.366184612752285), - (-177.3711810617254, -30.622149243259848), - (-176.8274107386524, -28.87700042708585), - (-176.30710772502422, -27.127570832268837), - (-175.8034798185683, -25.37659855071509), - (-175.3146666830624, -23.622777737104464), - (-173.31352985574108, -23.14698567224461), - ]) + polygon = Polygon( + [ + (-173.31352985574108, -23.14698567224461), + (-173.77162229214494, -24.907619019866505), + (-174.2415526063507, -26.665847671745183), + (-174.735358150903, -28.420448333916106), + (-175.23380277184344, -30.175206972263744), + (-175.74843654546004, -31.927869767925337), + (-176.2807594129271, -33.67798464336149), + (-176.84487055921355, -35.423184310947256), + (-177.41910677624742, -37.16801395691638), + (-178.0174237891529, -38.90994274849644), + (-178.6424368542418, -40.64852489269256), + (-179.29727678081028, -42.38361736393), + (-179.99919575326913, -44.11165778890455), + (179.27499973531806, -45.83867913785123), + (178.50719394616408, -47.561023088516535), + (177.69231780926836, -49.27817128078806), + (176.80904931895057, -50.986415957829536), + (175.87985821681252, -52.69120887337212), + (174.8814954194563, -54.38819050545594), + (173.80356416208477, -56.07742986626234), + (172.6342022987177, -57.75707684914518), + (171.3430337906186, -59.42214751260288), + (169.94378551545861, -61.077752113025916), + (168.3999709466183, -62.71805533391731), + (166.6843566389666, -64.34111371291355), + (164.74985524368935, -65.9397497607168), + (162.5883735575569, -67.5152692747083), + (160.1325459675333, -69.06048810117184), + (154.88126113623596, -68.86722808467104), + (157.66232733899088, -67.40109715863518), + (160.11788634153672, -65.89157783252615), + (162.30350978708452, -64.34830642665239), + (164.26115705334965, -62.776359315577984), + (166.0243795283944, -61.18062028554268), + (167.62930602018182, -59.5668614442984), + (169.08373088867933, -57.93420475768521), + (170.41560899457167, -56.28647419580335), + (171.64130903910598, -54.625361215229724), + (172.78119311087207, -52.95574121072587), + (173.83243861741815, -51.273905612708624), + (174.81205988512076, -49.58367135376619), + (175.72884840278266, -47.885484758555855), + (176.58940809511245, -46.18095578091026), + (177.407673659417, -44.471546605796334), + (178.17413248284223, -42.75510333566816), + (178.90089160626385, -41.03375212942789), + (179.59202341272197, -39.307739657248156), + (-179.74246296618378, -37.57885571562622), + (-179.11269276255436, -35.84470103625437), + (-178.50911206250385, -34.10700088461006), + (-177.92939864490123, -32.366184612752285), + (-177.3711810617254, -30.622149243259848), + (-176.8274107386524, -28.87700042708585), + (-176.30710772502422, -27.127570832268837), + (-175.8034798185683, -25.37659855071509), + (-175.3146666830624, -23.622777737104464), + (-173.31352985574108, -23.14698567224461), + ] + ) polygons = list(split_polygon_on_antimeridian_ccw(polygon)) for poly in polygons: @@ -685,10 +748,15 @@ def test_split_polygon_on_antimeridian_ccw_sentinel_ocn_example(): def test_split_polygon_on_antimeridian_fixed_size_alos2_example(): """Example from ALOS2: ALOS2014555550-140830""" - polygon = Polygon([ - (-164.198, -82.125), (172.437, -83.885), (165.618, -80.869), - (-176.331, -79.578), (-164.198, -82.125), - ]) + polygon = Polygon( + [ + (-164.198, -82.125), + (172.437, -83.885), + (165.618, -80.869), + (-176.331, -79.578), + (-164.198, -82.125), + ] + ) polygons = list(split_polygon_on_antimeridian_fixed_size(40)(polygon)) for poly in polygons: @@ -701,15 +769,15 @@ def test_split_polygon_on_antimeridian_fixed_size_alos2_example(): [ (-164.198, -82.125), (-176.331, -79.578), - (-180., -79.84040535150407), - (-180., -83.31530686924889), + (-180.0, -79.84040535150407), + (-180.0, -83.31530686924889), (-164.198, -82.125), ], [ - (180., -83.31530686924889), - (180., -79.84040535150407), + (180.0, -83.31530686924889), + (180.0, -79.84040535150407), (165.61799999999994, -80.869), (172.437, -83.885), - (180., -83.31530686924889), + (180.0, -83.31530686924889), ], ] diff --git a/tests/test_transformer.py b/tests/test_transformer.py index 9f559f3..8b4b4f8 100644 --- a/tests/test_transformer.py +++ b/tests/test_transformer.py @@ -8,9 +8,11 @@ @pytest.fixture def simplify_transformer(): - return Transformer([ - simplify_polygon(0.1), - ]) + return Transformer( + [ + simplify_polygon(0.1), + ] + ) def test_from_wkt(simplify_transformer): @@ -18,113 +20,132 @@ def test_from_wkt(simplify_transformer): assert simplify_transformer.from_wkt( "POLYGON ((50 20, 50 21, 51 21, 51 20, 50 20))", ) == [ - Polygon([ - (50.0, 20.0), - (50.0, 21.0), - (51.0, 21.0), - (51.0, 20.0), - (50.0, 20.0), - ]), + Polygon( + [ + (50.0, 20.0), + (50.0, 21.0), + (51.0, 21.0), + (51.0, 20.0), + (50.0, 20.0), + ] + ), ] assert simplify_transformer.from_wkt( "POLYGON(( 1 1, 2 1, 1 2, 1 1))", ) == [ - Polygon([ - (1, 1), - (2, 1), - (1, 2), - (1, 1), - ]), + Polygon( + [ + (1, 1), + (2, 1), + (1, 2), + (1, 1), + ] + ), ] # Duplicate point is removed assert simplify_transformer.from_wkt( "POLYGON ((50 20, 50 21, 51 21, 51 20, 50 20, 50 20))", ) == [ - Polygon([ - (50.0, 20.0), - (50.0, 21.0), - (51.0, 21.0), - (51.0, 20.0), - (50.0, 20.0), - ]), + Polygon( + [ + (50.0, 20.0), + (50.0, 21.0), + (51.0, 21.0), + (51.0, 20.0), + (50.0, 20.0), + ] + ), ] def test_from_wkt_multipolygon(simplify_transformer): assert simplify_transformer.from_wkt( - "MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20))," - "((15 5, 40 10, 10 20, 5 10, 15 5)))", + "MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))", ) == [ - Polygon([ - (30.0, 20.0), - (45.0, 40.0), - (10.0, 40.0), - (30.0, 20.0), - ]), - Polygon([ - (15.0, 5.0), - (40.0, 10.0), - (10.0, 20.0), - (5.0, 10.0), - (15.0, 5.0), - ]), + Polygon( + [ + (30.0, 20.0), + (45.0, 40.0), + (10.0, 40.0), + (30.0, 20.0), + ] + ), + Polygon( + [ + (15.0, 5.0), + (40.0, 10.0), + (10.0, 20.0), + (5.0, 10.0), + (15.0, 5.0), + ] + ), ] def test_from_geo_json(simplify_transformer): # Clockwise polygon remains clockwise - assert simplify_transformer.from_geo_json({ - "type": "Polygon", - "coordinates": [ - [ - [50, 20], - [50, 21], - [51, 21], - [51, 20], - [50, 20], + assert simplify_transformer.from_geo_json( + { + "type": "Polygon", + "coordinates": [ + [ + [50, 20], + [50, 21], + [51, 21], + [51, 20], + [50, 20], + ], ], - ], - }) == [ - Polygon([ - (50.0, 20.0), - (50.0, 21.0), - (51.0, 21.0), - (51.0, 20.0), - (50.0, 20.0), - ]), - ] - assert simplify_transformer.from_geo_json({ - "type": "Polygon", - "coordinates": [ + } + ) == [ + Polygon( [ - [1, 1], - [2, 1], - [1, 2], - [1, 1], + (50.0, 20.0), + (50.0, 21.0), + (51.0, 21.0), + (51.0, 20.0), + (50.0, 20.0), + ] + ), + ] + assert simplify_transformer.from_geo_json( + { + "type": "Polygon", + "coordinates": [ + [ + [1, 1], + [2, 1], + [1, 2], + [1, 1], + ], ], - ], - }) == [ - Polygon([ - (1, 1), - (2, 1), - (1, 2), - (1, 1), - ]), + } + ) == [ + Polygon( + [ + (1, 1), + (2, 1), + (1, 2), + (1, 1), + ] + ), ] # Duplicate point is removed - assert simplify_transformer.from_geo_json({ - "type": "Polygon", - "coordinates": [ - [ - [50.0, 20.0], - [50.0, 21.0], - [51.0, 21.0], - [51.0, 20.0], - [50.0, 20.0], - [50.0, 20.0], + assert simplify_transformer.from_geo_json( + { + "type": "Polygon", + "coordinates": [ + [ + [50.0, 20.0], + [50.0, 21.0], + [51.0, 21.0], + [51.0, 20.0], + [50.0, 20.0], + [50.0, 20.0], + ], ], - ], - }) == [ + } + ) == [ Polygon( [ (50.0, 20.0), @@ -198,10 +219,12 @@ def test_from_geo_json_bad_points(simplify_transformer): Exception, match=r"'POINT \(30 10\)' is not a Polygon or MultiPolygon", ): - simplify_transformer.from_geo_json({ - "type": "Point", - "coordinates": [[30, 10]], - }) + simplify_transformer.from_geo_json( + { + "type": "Point", + "coordinates": [[30, 10]], + } + ) with pytest.raises(AttributeError): simplify_transformer.from_geo_json({}) From 74351b3547a2cf42f4648137e957647ae0ed8511 Mon Sep 17 00:00:00 2001 From: Rohan Weeden Date: Mon, 22 Dec 2025 13:21:20 -0500 Subject: [PATCH 2/2] Remove flake8-commas lint This is because in preview versions of the ruff formatter, some nested brackets will be collapsed so long as there is no trailing comma. In these cases we can leave the commas off for now, and when (if) the collapsing feature is stabalized, the code will be reformatted automatically. --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 578b70e..7ba82e1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,7 +18,7 @@ jobs: with: flake8_version: 6.0.0 max_line_length: 120 - plugins: flake8-isort==6.1.2 flake8-quotes==3.4.0 flake8-commas==4.0.0 + plugins: flake8-isort==6.1.2 flake8-quotes==3.4.0 ruff-format: runs-on: ubuntu-latest