From ba360aa01cb99267873de947e78ad34334a8d3f8 Mon Sep 17 00:00:00 2001 From: Jongbin Jung Date: Fri, 11 Oct 2024 16:00:36 -0700 Subject: [PATCH 1/9] Use ruff to lint and format code --- .flake8 | 20 ----- pyproject.toml | 48 +++++++++-- src/h3/__init__.py | 2 - src/h3/_cy/__init__.py | 6 +- src/h3/_h3shape.py | 48 ++++------- src/h3/api/basic_int/__init__.py | 15 ++-- src/h3/api/numpy_int/_convert.py | 1 + tests/polyfill/test_h3.py | 83 +++++++++---------- tests/polyfill/test_polyfill.py | 33 +++----- tests/polyfill/test_polyfill_ordering.py | 20 ++--- tests/polyfill/test_to_multipoly.py | 12 +-- tests/test_apis/test_basic_int.py | 2 +- tests/test_apis/test_basic_str.py | 5 +- tests/test_apis/test_collection_inputs.py | 42 +++++----- tests/test_cells_and_edges.py | 99 ++++++++++------------- tests/test_error_codes.py | 2 - tests/test_h3.py | 23 ++---- tests/test_length_area.py | 23 ++---- tests/util.py | 5 +- 19 files changed, 212 insertions(+), 277 deletions(-) delete mode 100644 .flake8 diff --git a/.flake8 b/.flake8 deleted file mode 100644 index f77f556a3..000000000 --- a/.flake8 +++ /dev/null @@ -1,20 +0,0 @@ -# https://lintlyci.github.io/Flake8Rules/ -[flake8] -max-line-length = 88 -include = - #W292 No newline at end of file - W292, -ignore = - # E251 unexpected spaces around keyword / parameter equals - E251, - # sometimes I just want to line up decimal points... - # E201 whitespace after '[' - E201, - # E241 multiple spaces after ',' - E241, - # E731 do not assign a lambda expression, use a def - E731, - # https://stackoverflow.com/questions/67942075/w504-line-break-after-binary-operator - W503,W504, - # E272 multiple spaces before keyword - E272 diff --git a/pyproject.toml b/pyproject.toml index 9e24b7d78..7f4af1e81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,10 +46,10 @@ Changelog = 'https://package.readthedocs.io/en/latest/changelog.html' [project.optional-dependencies] numpy = ['numpy'] -test = ['pytest', 'pytest-cov', 'flake8', 'pylint', 'numpy'] +test = ['pytest', 'pytest-cov', 'ruff', 'numpy'] all = [ + 'h3[test]', 'jupyter-book', - 'flake8', 'sphinx>=7.3.3', # https://github.com/sphinx-doc/sphinx/issues/12290 'jupyterlab', 'jupyterlab-geojson', @@ -59,15 +59,51 @@ all = [ 'contextily', 'cartopy', 'geoviews', - 'numpy', - 'pytest', - 'pytest-cov', - 'pylint', ] [tool.pytest.ini_options] addopts = "--cov=h3 --cov=tests --cov-report=term-missing --durations=10" +[tool.ruff] +src = [ + "src", + "tests", +] + +lint.select = [ + "E", + "F", + "W", +] + +lint.extend-select = [ + "I", +] + +lint.ignore = [ + "E251", # unexpected spaces around keyword / parameter equals + "E272", # multiple spaces before keyword + # sometimes I just want to line up decimal points... + "E201", # whitespace after '[' + "E241", # multiple spaces after ',' + "E731", # do not assign a lambda expression, use a def + # Ignore when using formatter (https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules) + "E501", # Line-too-long; +] + +respect-gitignore = true + +[tool.ruff.format] +indent-style = "space" +quote-style = "single" + +[tool.ruff.per-file-ignores] +# Do not enforce usage in init files +"__init__.py" = [ + "E402", + "F401", +] + [tool.coverage.run] omit = [ '*/h3/api/basic_int/__init__.py', diff --git a/src/h3/__init__.py b/src/h3/__init__.py index 4f7cb32f1..d5964d1c0 100644 --- a/src/h3/__init__.py +++ b/src/h3/__init__.py @@ -6,11 +6,9 @@ from ._cy import ( UnknownH3ErrorCode, H3BaseException, - H3GridNavigationError, H3MemoryError, H3ValueError, - H3FailedError, H3DomainError, H3LatLngDomainError, diff --git a/src/h3/_cy/__init__.py b/src/h3/_cy/__init__.py index 804b6b0e3..324bc249d 100644 --- a/src/h3/_cy/__init__.py +++ b/src/h3/_cy/__init__.py @@ -70,9 +70,7 @@ is_valid_vertex, ) -from .to_multipoly import ( - cells_to_multi_polygon -) +from .to_multipoly import cells_to_multi_polygon from .util import ( c_version, @@ -87,11 +85,9 @@ from .error_system import ( UnknownH3ErrorCode, H3BaseException, - H3GridNavigationError, H3MemoryError, H3ValueError, - H3FailedError, H3DomainError, H3LatLngDomainError, diff --git a/src/h3/_h3shape.py b/src/h3/_h3shape.py index 5c3629512..80fe35856 100644 --- a/src/h3/_h3shape.py +++ b/src/h3/_h3shape.py @@ -5,10 +5,11 @@ class H3Shape(metaclass=ABCMeta): """ Abstract parent class of ``LatLngPoly`` and ``LatLngMultiPoly``. """ + @property @abstractmethod def __geo_interface__(self): - """ https://github.com/pytest-dev/pytest-cov/issues/428 """ + """https://github.com/pytest-dev/pytest-cov/issues/428""" class LatLngPoly(H3Shape): @@ -51,6 +52,7 @@ class LatLngPoly(H3Shape): ... ) """ + def __init__(self, outer, *holes): loops = [outer] + list(holes) for loop in loops: @@ -63,10 +65,7 @@ def __init__(self, outer, *holes): raise ValueError('LatLngPoly only accepts 2D points: lat/lng.') self.outer = tuple(_open_ring(outer)) - self.holes = tuple( - _open_ring(hole) - for hole in holes - ) + self.holes = tuple(_open_ring(hole) for hole in holes) def __repr__(self): return ''.format(self.loopcode) @@ -80,7 +79,7 @@ def __len__(self): @property def loopcode(self): - """ Short code for describing the length of the outer loop and each hole + """Short code for describing the length of the outer loop and each hole Example: ``[382/(18, 6, 6)]`` indicates an outer loop of 382 points, along with 3 holes with 18, 6, and 6 points, respectively. @@ -116,12 +115,13 @@ class LatLngMultiPoly(H3Shape): polys : list[LatLngPoly] List of lat/lng points describing the outer loop of the polygon """ + def __init__(self, *polys): self.polys = tuple(polys) for p in self.polys: if not isinstance(p, LatLngPoly): - raise ValueError('LatLngMultiPoly requires each input to be an LatLngPoly object, instead got: ' + str(p)) # noqa + raise ValueError('LatLngMultiPoly requires each input to be an LatLngPoly object, instead got: ' + str(p)) # fmt: skip def __repr__(self): out = [p.loopcode for p in self.polys] @@ -133,8 +133,7 @@ def __iter__(self): return iter(self.polys) def __len__(self): - """ Give the number of polygons in this multi-polygon. - """ + """Give the number of polygons in this multi-polygon.""" """ TODO: Pandas series or dataframe representation changes depending @@ -195,19 +194,13 @@ def __geo_interface__(self): def _mpoly_to_LL3(mpoly): - ll3 = tuple( - _polygon_to_LL2(poly) - for poly in mpoly - ) + ll3 = tuple(_polygon_to_LL2(poly) for poly in mpoly) return ll3 def _LL3_to_mpoly(ll3): - polys = [ - _LL2_to_polygon(ll2) - for ll2 in ll3 - ] + polys = [_LL2_to_polygon(ll2) for ll2 in ll3] mpoly = LatLngMultiPoly(*polys) @@ -216,10 +209,7 @@ def _LL3_to_mpoly(ll3): def _polygon_to_LL2(poly): ll2 = [poly.outer] + list(poly.holes) - ll2 = tuple( - _close_ring(_swap_latlng(ll1)) - for ll1 in ll2 - ) + ll2 = tuple(_close_ring(_swap_latlng(ll1)) for ll1 in ll2) return ll2 @@ -230,15 +220,9 @@ def _remove_z(ll1): def _LL2_to_polygon(ll2): - ll2 = [ - _remove_z(ll1) - for ll1 in ll2 - ] - - ll2 = [ - _swap_latlng(ll1) - for ll1 in ll2 - ] + ll2 = [_remove_z(ll1) for ll1 in ll2] + + ll2 = [_swap_latlng(ll1) for ll1 in ll2] h3poly = LatLngPoly(*ll2) return h3poly @@ -263,9 +247,7 @@ def _LL3_to_geojson_dict(ll3): def _swap_latlng(ll1): - ll1 = tuple( - (b, a) for a, b in ll1 - ) + ll1 = tuple((b, a) for a, b in ll1) return ll1 diff --git a/src/h3/api/basic_int/__init__.py b/src/h3/api/basic_int/__init__.py index 603596629..93891bc1e 100644 --- a/src/h3/api/basic_int/__init__.py +++ b/src/h3/api/basic_int/__init__.py @@ -3,17 +3,16 @@ from ... import _cy from ..._h3shape import ( H3Shape, - LatLngPoly, LatLngMultiPoly, + LatLngPoly, geo_to_h3shape, h3shape_to_geo, ) - from ._convert import ( - _in_scalar, - _out_scalar, _in_collection, + _in_scalar, _out_collection, + _out_scalar, ) @@ -1071,9 +1070,11 @@ def great_circle_distance(latlng1, latlng2, unit='km'): lat1, lng1 = latlng1 lat2, lng2 = latlng2 return _cy.great_circle_distance( - lat1, lng1, - lat2, lng2, - unit = unit + lat1, + lng1, + lat2, + lng2, + unit=unit, ) diff --git a/src/h3/api/numpy_int/_convert.py b/src/h3/api/numpy_int/_convert.py index 6b293cc9c..f1be5c33c 100644 --- a/src/h3/api/numpy_int/_convert.py +++ b/src/h3/api/numpy_int/_convert.py @@ -7,6 +7,7 @@ def _in_scalar(x): def _in_collection(x): import numpy as np + # array is copied only if dtype does not match # `list`s should work, but not `set`s of integers return np.asarray(x, dtype='uint64') diff --git a/tests/polyfill/test_h3.py b/tests/polyfill/test_h3.py index 8d9d9480e..b9cfdce59 100644 --- a/tests/polyfill/test_h3.py +++ b/tests/polyfill/test_h3.py @@ -1,6 +1,7 @@ -import h3 import pytest +import h3 + from .. import util as u @@ -28,9 +29,7 @@ def latlng_closed(): def swap_latlng(ll1): - ll1 = tuple( - (b, a) for a, b in ll1 - ) + ll1 = tuple((b, a) for a, b in ll1) return ll1 @@ -43,10 +42,12 @@ def lnglat_closed(): def get_mocked(loop): - geo = MockGeoInterface({ - 'type': 'Polygon', - 'coordinates': [loop] - }) + geo = MockGeoInterface( + { + 'type': 'Polygon', + 'coordinates': [loop], + } + ) return geo @@ -82,8 +83,7 @@ def test_geo_interface(): assert ( poly.__geo_interface__['coordinates'] - == - mpoly.__geo_interface__['coordinates'][0] + == mpoly.__geo_interface__['coordinates'][0] ) @@ -91,11 +91,7 @@ def test_shape_repr(): poly = h3.LatLngPoly(sf_hole1) mpoly = h3.LatLngMultiPoly(poly) - assert ( - '' - == str(mpoly) - == repr(mpoly) - ) + assert '' == str(mpoly) == repr(mpoly) def test_polyfill(): @@ -125,23 +121,16 @@ def test_polyfill_with_hole(): foo = lambda x: set(h3.h3shape_to_cells(h3.LatLngPoly(x), 9)) - assert u.same_set( - out, - foo(sf_7x7) - foo(sf_hole1) - ) + assert u.same_set(out, foo(sf_7x7) - foo(sf_hole1)) def test_polyfill_with_two_holes(): - poly = h3.LatLngPoly(sf_7x7, sf_hole1, sf_hole2) out = h3.h3shape_to_cells(poly, 9) assert len(out) == 1172 foo = lambda x: set(h3.h3shape_to_cells(h3.LatLngPoly(x), 9)) - assert u.same_set( - out, - foo(sf_7x7) - (foo(sf_hole1) | foo(sf_hole2)) - ) + assert u.same_set(out, foo(sf_7x7) - (foo(sf_hole1) | foo(sf_hole2))) def test_polyfill_geo_json_compliant(): @@ -177,12 +166,14 @@ def test_geo_to_h3shape(): expected = { 'type': 'Polygon', - 'coordinates': (( - (-122.408, 37.813), - (-122.512, 37.707), - (-122.479, 37.815), - (-122.408, 37.813), - ),) + 'coordinates': ( + ( + (-122.408, 37.813), + (-122.512, 37.707), + (-122.479, 37.815), + (-122.408, 37.813), + ), + ), } for shape in shapes: @@ -192,12 +183,16 @@ def test_geo_to_h3shape(): multi_expected = { 'type': 'MultiPolygon', - 'coordinates': ((( - (-122.408, 37.813), - (-122.512, 37.707), - (-122.479, 37.815), - (-122.408, 37.813), - ),),) + 'coordinates': ( + ( + ( + (-122.408, 37.813), + (-122.512, 37.707), + (-122.479, 37.815), + (-122.408, 37.813), + ), + ), + ), } for mp in mpolys: @@ -360,8 +355,12 @@ def test_cells_to_h3shape_non_contiguous(): def test_cells_to_h3shape_hole(): # Six hexagons in a ring around a hole cells = [ - '892830828c7ffff', '892830828d7ffff', '8928308289bffff', - '89283082813ffff', '8928308288fffff', '89283082883ffff', + '892830828c7ffff', + '892830828d7ffff', + '8928308289bffff', + '89283082813ffff', + '8928308288fffff', + '89283082883ffff', ] mpoly = h3.cells_to_h3shape(cells, tight=False) @@ -386,7 +385,6 @@ def test_cells_to_h3shape_2grid_disk(): def test_multipoly_checks(): - with pytest.raises(ValueError): h3.LatLngMultiPoly('foo') @@ -400,7 +398,7 @@ def test_multipoly_checks(): def test_3d_geo(): loop = lnglat_open() - loop2d = [(lng, lat) for lng, lat in loop] + loop2d = [(lng, lat) for lng, lat in loop] loop3d = [(lng, lat, 0.0) for lng, lat in loop] geo2d = get_mocked(loop2d) @@ -418,10 +416,7 @@ def test_3d_geo(): def test_against_3d_polygons(): # LatLngPoly still expects just a lat/lng. it won't handle 3d coords - loop3d = [ - (lat, lng, 0.0) - for lat, lng in latlng_open() - ] + loop3d = [(lat, lng, 0.0) for lat, lng in latlng_open()] with pytest.raises(ValueError): h3.LatLngPoly(loop3d) diff --git a/tests/polyfill/test_polyfill.py b/tests/polyfill/test_polyfill.py index 1431b8765..e530f2032 100644 --- a/tests/polyfill/test_polyfill.py +++ b/tests/polyfill/test_polyfill.py @@ -7,36 +7,29 @@ def get_us_box_coords(): - # big center chunk of the US in lat/lng order outer = [ [42.68, -110.61], [32.17, -109.02], - [31.57, -94.26], - [42.94, -89.38], - [42.68, -110.61] + [31.57, -94.26], + [42.94, -89.38], + [42.68, -110.61], ] hole1 = [ [39.77, -105.07], [34.81, -104.72], - [34.77, -98.39], - [40.14, -96.72], - [39.77, -105.07] + [34.77, -98.39], + [40.14, -96.72], + [39.77, -105.07], ] - hole2 = [ - [41.37, -98.61], - [40.04, -91.80], - [42.32, -91.80], - [41.37, -98.61] - ] + hole2 = [[41.37, -98.61], [40.04, -91.80], [42.32, -91.80], [41.37, -98.61]] return outer, hole1, hole2 def test_h3shape_to_cells(): - # approximate lat/lngs for State of Maine maine = [ (45.137, -67.137), @@ -68,7 +61,7 @@ def test_h3shape_to_cells(): '832b1afffffffff', '832b1efffffffff', '832ba9fffffffff', - '832badfffffffff' + '832badfffffffff', } poly = h3.LatLngPoly(maine) @@ -93,12 +86,9 @@ def test_h3shape_to_cells2(): def test_h3shape_to_cells_holes(): - outer, hole1, hole2 = get_us_box_coords() - assert 7063 == len( - h3.h3shape_to_cells(h3.LatLngPoly(outer), 5) - ) + assert 7063 == len(h3.h3shape_to_cells(h3.LatLngPoly(outer), 5)) for res in 1, 2, 3, 4, 5: cells_all = h3.h3shape_to_cells(h3.LatLngPoly(outer), res) @@ -109,10 +99,7 @@ def test_h3shape_to_cells_holes(): cells_2 = set(h3.h3shape_to_cells(h3.LatLngPoly(hole2), res)) assert len(cells_all) == len(cells_holes) + len(cells_1) + len(cells_2) - assert u.same_set( - cells_all, - set.union(cells_holes, cells_1, cells_2) - ) + assert u.same_set(cells_all, set.union(cells_holes, cells_1, cells_2)) def test_resolution(): diff --git a/tests/polyfill/test_polyfill_ordering.py b/tests/polyfill/test_polyfill_ordering.py index e0e43d8fb..24ef7e4c8 100644 --- a/tests/polyfill/test_polyfill_ordering.py +++ b/tests/polyfill/test_polyfill_ordering.py @@ -8,9 +8,10 @@ may follow a different subset of rules. """ -import h3 import itertools +import h3 + def reverse(loop): return list(reversed(loop)) @@ -21,7 +22,7 @@ def drop_last(loop): def toggle_map(func, poly): - """ Return all permutations of `func` being applied or not + """Return all permutations of `func` being applied or not to each element of `poly` returns iterable of length 2**len(poly) @@ -50,29 +51,28 @@ def input_permutations(geo, res=5): def get_us_box_coords(): - # big center chunk of the US in lat/lng order outer = [ [42.68, -110.61], [32.17, -109.02], - [31.57, -94.26], - [42.94, -89.38], - [42.68, -110.61] + [31.57, -94.26], + [42.94, -89.38], + [42.68, -110.61], ] hole1 = [ [39.77, -105.07], [34.81, -104.72], - [34.77, -98.39], - [40.14, -96.72], - [39.77, -105.07] + [34.77, -98.39], + [40.14, -96.72], + [39.77, -105.07], ] hole2 = [ [41.37, -98.61], [40.04, -91.80], [42.32, -91.80], - [41.37, -98.61] + [41.37, -98.61], ] return outer, hole1, hole2 diff --git a/tests/polyfill/test_to_multipoly.py b/tests/polyfill/test_to_multipoly.py index 61f77f63b..5b361f13e 100644 --- a/tests/polyfill/test_to_multipoly.py +++ b/tests/polyfill/test_to_multipoly.py @@ -37,13 +37,7 @@ def test_2_polys(): mpoly = h3.cells_to_h3shape(cells) - out = [ - set(h3.h3shape_to_cells(poly, 9)) - for poly in mpoly - ] - - assert u.same_set( - set.union(*out), - cells - ) + out = [set(h3.h3shape_to_cells(poly, 9)) for poly in mpoly] + + assert u.same_set(set.union(*out), cells) assert set(map(len, out)) == {1, 12} diff --git a/tests/test_apis/test_basic_int.py b/tests/test_apis/test_basic_int.py index a567b3de1..466fe1f3c 100644 --- a/tests/test_apis/test_basic_int.py +++ b/tests/test_apis/test_basic_int.py @@ -9,7 +9,7 @@ def test_int_output(): lng = -122.418307270836 assert h3.latlng_to_cell(lat, lng, 9) == 617700169958293503 - assert h3.latlng_to_cell(lat, lng, 9) == 0x8928308280fffff + assert h3.latlng_to_cell(lat, lng, 9) == 0x8928308280FFFFF def test_grid_disk(): diff --git a/tests/test_apis/test_basic_str.py b/tests/test_apis/test_basic_str.py index fccc164f0..30b426ab6 100644 --- a/tests/test_apis/test_basic_str.py +++ b/tests/test_apis/test_basic_str.py @@ -17,7 +17,7 @@ def test5(): '89283082807ffff', '8928308280bffff', '8928308280fffff', - '89283082803ffff' + '89283082803ffff', ] out = h3.grid_disk('8928308280fffff', 1) @@ -25,7 +25,6 @@ def test5(): def test_string_subtypes(): - class my_str(str): pass @@ -36,7 +35,7 @@ class my_str(str): '89283082807ffff', '8928308280bffff', '8928308280fffff', - '89283082803ffff' + '89283082803ffff', ] out = h3.grid_disk(my_str('8928308280fffff'), 1) diff --git a/tests/test_apis/test_collection_inputs.py b/tests/test_apis/test_collection_inputs.py index 5f826a14b..5f0f8ed08 100644 --- a/tests/test_apis/test_collection_inputs.py +++ b/tests/test_apis/test_collection_inputs.py @@ -62,15 +62,18 @@ def test_list(): def test_np_array(): - ints = np.array([ - 619056821839331327, - 619056821839593471, - 619056821839855615, - 619056821840117759, - 619056821840379903, - 619056821840642047, - 619056821840904191, - ], dtype='uint64') + ints = np.array( + [ + 619056821839331327, + 619056821839593471, + 619056821839855615, + 619056821840117759, + 619056821840379903, + 619056821840642047, + 619056821840904191, + ], + dtype='uint64', + ) h = 614553222213795839 @@ -111,17 +114,18 @@ def test_list_to_array(): def test_iterator(): - def foo(): - ints = iter([ - 619056821839331327, - 619056821839593471, - 619056821839855615, - 619056821840117759, - 619056821840379903, - 619056821840642047, - 619056821840904191, - ]) + ints = iter( + [ + 619056821839331327, + 619056821839593471, + 619056821839855615, + 619056821840117759, + 619056821840379903, + 619056821840642047, + 619056821840904191, + ] + ) return ints diff --git a/tests/test_cells_and_edges.py b/tests/test_cells_and_edges.py index d23ff4d63..30ddac2ee 100644 --- a/tests/test_cells_and_edges.py +++ b/tests/test_cells_and_edges.py @@ -1,16 +1,15 @@ -import h3 import pytest +import h3 from h3 import ( + H3CellInvalidError, + H3DomainError, H3FailedError, + H3NotNeighborsError, H3ResDomainError, - H3DomainError, H3ResMismatchError, - H3CellInvalidError, - H3NotNeighborsError, ) - from . import util as u @@ -58,7 +57,7 @@ def test5(): '89283082807ffff', '8928308280bffff', '8928308280fffff', - '89283082803ffff' + '89283082803ffff', ] out = h3.grid_disk('8928308280fffff', 1) @@ -78,7 +77,7 @@ def test7(): '8928308280bffff', '8928308283bffff', '89283082873ffff', - '89283082877ffff' + '89283082877ffff', ] out = h3.grid_ring('8928308280fffff', 1) @@ -152,7 +151,7 @@ def test_children(): '8a28308280dffff', '8a28308280e7fff', '8a28308280effff', - '8a28308280f7fff' + '8a28308280f7fff', ] out = h3.cell_to_children(h, 10) assert u.same_set(out, expected) @@ -195,7 +194,7 @@ def test_distance(): def test_distance_error(): - """ Two valid cells, but they are too far apart compute the distance + """Two valid cells, but they are too far apart compute the distance todo: make sure this raises a E_TOO_FAR error (when we add it in the future) """ @@ -208,34 +207,36 @@ def test_distance_error(): def get_maine_cells(): # lat/lngs for State of Maine - poly = h3.LatLngPoly([ - (45.137451890638886, -67.13734351262877), - (44.8097, -66.96466), - (44.3252, -68.03252), - (43.98, -69.06), - (43.68405, -70.11617), - (43.090083319667144, -70.64573401557249), - (43.08003225358635, -70.75102474636725), - (43.21973948828747, -70.79761105007827), - (43.36789581966826, -70.98176001655037), - (43.46633942318431, -70.94416541205806), - (45.3052400000002, -71.08482), - (45.46022288673396, -70.6600225491012), - (45.914794623389355, -70.30495378282376), - (46.69317088478567, -70.00014034695016), - (47.44777598732787, -69.23708614772835), - (47.184794623394396, -68.90478084987546), - (47.35462921812177, -68.23430497910454), - (47.066248887716995, -67.79035274928509), - (45.702585354182816, -67.79141211614706), - (45.137451890638886, -67.13734351262877) - ]) + poly = h3.LatLngPoly( + [ + (45.137451890638886, -67.13734351262877), + (44.8097, -66.96466), + (44.3252, -68.03252), + (43.98, -69.06), + (43.68405, -70.11617), + (43.090083319667144, -70.64573401557249), + (43.08003225358635, -70.75102474636725), + (43.21973948828747, -70.79761105007827), + (43.36789581966826, -70.98176001655037), + (43.46633942318431, -70.94416541205806), + (45.3052400000002, -71.08482), + (45.46022288673396, -70.6600225491012), + (45.914794623389355, -70.30495378282376), + (46.69317088478567, -70.00014034695016), + (47.44777598732787, -69.23708614772835), + (47.184794623394396, -68.90478084987546), + (47.35462921812177, -68.23430497910454), + (47.066248887716995, -67.79035274928509), + (45.702585354182816, -67.79141211614706), + (45.137451890638886, -67.13734351262877), + ] + ) res = 5 cells_uncomp = h3.h3shape_to_cells(poly, res=res) # the expected result from h3.compact_cells(cells_uncomp) - cells_comp = ['852b114ffffffff', '852b189bfffffff', '852b1163fffffff', '842ba9bffffffff', '842bad3ffffffff', '852ba9cffffffff', '842badbffffffff', '852b1e8bfffffff', '852a346ffffffff', '842b1e3ffffffff', '852b116ffffffff', '842b185ffffffff', '852b1bdbfffffff', '852bad47fffffff', '852ba9c3fffffff', '852b106bfffffff', '852a30d3fffffff', '842b1edffffffff', '852b12a7fffffff', '852b1027fffffff', '842baddffffffff', '852a349bfffffff', '852b1227fffffff', '852a3473fffffff', '852b117bfffffff', '842ba99ffffffff', '852a341bfffffff', '852ba9d3fffffff', '852b1067fffffff', '852a3463fffffff', '852baca7fffffff', '852b116bfffffff', '852b1c6bfffffff', '852a3493fffffff', '852ba9dbfffffff', '852b180bfffffff', '842bad7ffffffff', '852b1063fffffff', '842ba93ffffffff', '852a3693fffffff', '852ba977fffffff', '852b1e9bfffffff', '852bad53fffffff', '852b100ffffffff', '852b102bfffffff', '852a3413fffffff', '852ba8b7fffffff', '852bad43fffffff', '852b1c6ffffffff', '852a340bfffffff', '852b103bfffffff', '852b1813fffffff', '852b12affffffff', '842a34dffffffff', '852b1873fffffff', '852b106ffffffff', '852b115bfffffff', '852baca3fffffff', '852b114bfffffff', '852b1143fffffff', '852a348bfffffff', '852a30d7fffffff', '852b181bfffffff', '842a345ffffffff', '852b1e8ffffffff', '852b1883fffffff', '852b1147fffffff', '852a3483fffffff', '852b12a3fffffff', '852a346bfffffff', '852ba9d7fffffff', '842b18dffffffff', '852b188bfffffff', '852a36a7fffffff', '852bacb3fffffff', '852b187bfffffff', '852bacb7fffffff', '842b1ebffffffff', '842b1e5ffffffff', '852ba8a7fffffff', '842bad9ffffffff', '852a36b7fffffff', '852a347bfffffff', '832b13fffffffff', '852ba9c7fffffff', '832b1afffffffff', '842ba91ffffffff', '852bad57fffffff', '852ba8affffffff', '852b1803fffffff', '842b1e7ffffffff', '852bad4ffffffff', '852b102ffffffff', '852b1077fffffff', '852b1237fffffff', '852b1153fffffff', '852a3697fffffff', '852a36b3fffffff', '842bad1ffffffff', '842b1e1ffffffff', '852b186bfffffff', '852b1023fffffff'] # noqa + cells_comp = ['852b114ffffffff', '852b189bfffffff', '852b1163fffffff', '842ba9bffffffff', '842bad3ffffffff', '852ba9cffffffff', '842badbffffffff', '852b1e8bfffffff', '852a346ffffffff', '842b1e3ffffffff', '852b116ffffffff', '842b185ffffffff', '852b1bdbfffffff', '852bad47fffffff', '852ba9c3fffffff', '852b106bfffffff', '852a30d3fffffff', '842b1edffffffff', '852b12a7fffffff', '852b1027fffffff', '842baddffffffff', '852a349bfffffff', '852b1227fffffff', '852a3473fffffff', '852b117bfffffff', '842ba99ffffffff', '852a341bfffffff', '852ba9d3fffffff', '852b1067fffffff', '852a3463fffffff', '852baca7fffffff', '852b116bfffffff', '852b1c6bfffffff', '852a3493fffffff', '852ba9dbfffffff', '852b180bfffffff', '842bad7ffffffff', '852b1063fffffff', '842ba93ffffffff', '852a3693fffffff', '852ba977fffffff', '852b1e9bfffffff', '852bad53fffffff', '852b100ffffffff', '852b102bfffffff', '852a3413fffffff', '852ba8b7fffffff', '852bad43fffffff', '852b1c6ffffffff', '852a340bfffffff', '852b103bfffffff', '852b1813fffffff', '852b12affffffff', '842a34dffffffff', '852b1873fffffff', '852b106ffffffff', '852b115bfffffff', '852baca3fffffff', '852b114bfffffff', '852b1143fffffff', '852a348bfffffff', '852a30d7fffffff', '852b181bfffffff', '842a345ffffffff', '852b1e8ffffffff', '852b1883fffffff', '852b1147fffffff', '852a3483fffffff', '852b12a3fffffff', '852a346bfffffff', '852ba9d7fffffff', '842b18dffffffff', '852b188bfffffff', '852a36a7fffffff', '852bacb3fffffff', '852b187bfffffff', '852bacb7fffffff', '842b1ebffffffff', '842b1e5ffffffff', '852ba8a7fffffff', '842bad9ffffffff', '852a36b7fffffff', '852a347bfffffff', '832b13fffffffff', '852ba9c7fffffff', '832b1afffffffff', '842ba91ffffffff', '852bad57fffffff', '852ba8affffffff', '852b1803fffffff', '842b1e7ffffffff', '852bad4ffffffff', '852b102ffffffff', '852b1077fffffff', '852b1237fffffff', '852b1153fffffff', '852a3697fffffff', '852a36b3fffffff', '842bad1ffffffff', '842b1e1ffffffff', '852b186bfffffff', '852b1023fffffff'] # fmt: skip return cells_uncomp, cells_comp, res @@ -262,15 +263,13 @@ def test_get_num_cells(): 15: 569707381193162, } - out = { - k: h3.get_num_cells(k) - for k in expected - } + out = {k: h3.get_num_cells(k) for k in expected} assert expected == out def test_average_hexagon_area(): + # fmt: off expected_in_km2 = { 0: 4357449.416078381, 1: 609788.441794133, @@ -278,11 +277,9 @@ def test_average_hexagon_area(): 9: 0.105332513, 15: 8.95311e-07, } + # fmt: on - out = { - k: h3.average_hexagon_area(k, unit='km^2') - for k in expected_in_km2 - } + out = {k: h3.average_hexagon_area(k, unit='km^2') for k in expected_in_km2} assert out == pytest.approx(expected_in_km2) @@ -297,8 +294,7 @@ def test_average_hexagon_edge_length(): } out = { - res: h3.average_hexagon_edge_length(res, unit='km') - for res in expected_in_km + res: h3.average_hexagon_edge_length(res, unit='km') for res in expected_in_km } assert out == pytest.approx(expected_in_km) @@ -326,10 +322,7 @@ def test_edge(): def test_origin_to_directed_edges(): h = '8928308280fffff' edges = h3.origin_to_directed_edges(h) - destinations = { - h3.get_directed_edge_destination(e) - for e in edges - } + destinations = {h3.get_directed_edge_destination(e) for e in edges} neighbors = h3.grid_ring(h, 1) assert u.same_set(neighbors, destinations) @@ -342,7 +335,7 @@ def test_edge_boundary(): expected = ( (37.77688044840226, -122.41612835779266), - (37.778385004930925, -122.41738797617619) + (37.778385004930925, -122.41738797617619), ) out = h3.directed_edge_to_boundary(e) @@ -436,7 +429,7 @@ def test_line(): expected = [ '8928308280fffff', '89283082873ffff', - '8928308287bffff' + '8928308287bffff', ] assert out == expected @@ -540,10 +533,7 @@ def test_get_res0_cells(): assert all(map(h3.is_valid_cell, out)) # resolution - assert all(map( - lambda h: h3.get_resolution(h) == 0, - out - )) + assert all(map(lambda h: h3.get_resolution(h) == 0, out)) # verify a few concrete cells sub = { @@ -584,10 +574,7 @@ def test_from_local_ij_error(): nb = h3.grid_ring(h, k=1) goodies = {h3.cell_to_local_ij(h, p) for p in nb} - out = { - h3.local_ij_to_cell(h, i, j) - for i, j in goodies - } + out = {h3.local_ij_to_cell(h, i, j) for i, j in goodies} assert u.same_set(out, nb) diff --git a/tests/test_error_codes.py b/tests/test_error_codes.py index 9961178db..2df00e5dc 100644 --- a/tests/test_error_codes.py +++ b/tests/test_error_codes.py @@ -8,11 +8,9 @@ h3_exceptions = { # h3.UnknownH3ErrorCode h3.H3BaseException: None, - h3.H3GridNavigationError: None, h3.H3MemoryError: None, h3.H3ValueError: None, - h3.H3FailedError: 1, h3.H3DomainError: 2, h3.H3LatLngDomainError: 3, diff --git a/tests/test_h3.py b/tests/test_h3.py index 760c3faba..1528637b0 100644 --- a/tests/test_h3.py +++ b/tests/test_h3.py @@ -148,10 +148,7 @@ def test_grid_ring(): } assert u.same_set(out, expected) - assert u.same_set( - out, - set(h3.grid_disk(h, 1)) - set(h3.grid_disk(h, 0)) - ) + assert u.same_set(out, set(h3.grid_disk(h, 1)) - set(h3.grid_disk(h, 0))) def test_grid_ring2(): @@ -174,10 +171,7 @@ def test_grid_ring2(): } assert u.same_set(out, expected) - assert u.same_set( - out, - set(h3.grid_disk(h, 2)) - set(h3.grid_disk(h, 1)) - ) + assert u.same_set(out, set(h3.grid_disk(h, 2)) - set(h3.grid_disk(h, 1))) def test_grid_ring_pentagon(): @@ -328,14 +322,10 @@ def test_directed_edge_to_cells(): def test_origin_to_directed_edges(): - h3_uni_edges = h3.origin_to_directed_edges( - '8928308280fffff' - ) + h3_uni_edges = h3.origin_to_directed_edges('8928308280fffff') assert len(h3_uni_edges) == 6 - h3_uni_edge_pentagon = h3.origin_to_directed_edges( - '821c07fffffffff' - ) + h3_uni_edge_pentagon = h3.origin_to_directed_edges('821c07fffffffff') assert len(h3_uni_edge_pentagon) == 5 @@ -481,10 +471,7 @@ def test_cell_to_children_size2(): for r in range(16): total_cells = 120 * (7**r) + 2 - assert total_cells == sum( - h3.cell_to_children_size(h, r) - for h in cells - ) + assert total_cells == sum(h3.cell_to_children_size(h, r) for h in cells) def test_child_pos3(): diff --git a/tests/test_length_area.py b/tests/test_length_area.py index 1003f5649..ce1e4509f 100644 --- a/tests/test_length_area.py +++ b/tests/test_length_area.py @@ -1,16 +1,14 @@ -import h3 import pytest +import h3 + from . import util as u def cell_perimiter1(h, unit='km'): edges = h3.origin_to_directed_edges(h) - dists = [ - h3.edge_length(e, unit=unit) - for e in edges - ] + dists = [h3.edge_length(e, unit=unit) for e in edges] assert all(d > 0 for d in dists) @@ -23,8 +21,7 @@ def cell_perimiter2(h, unit='km'): verts += (verts[0],) dists = [ - h3.great_circle_distance(verts[i], verts[i + 1], unit=unit) - for i in range(N) + h3.great_circle_distance(verts[i], verts[i + 1], unit=unit) for i in range(N) ] assert all(d > 0 for d in dists) @@ -33,6 +30,7 @@ def cell_perimiter2(h, unit='km'): def test_areas_at_00(): + # fmt: off areas_km2 = [ 2.562182162955495529e+06, 4.476842018179409206e+05, @@ -51,11 +49,9 @@ def test_areas_at_00(): 4.664070326136773890e-06, 6.662957615868890711e-07, ] + # fmt: on - out = [ - h3.cell_area(h3.latlng_to_cell(0, 0, r), unit='km^2') - for r in range(16) - ] + out = [h3.cell_area(h3.latlng_to_cell(0, 0, r), unit='km^2') for r in range(16)] assert u.approx2(out, areas_km2) @@ -78,10 +74,7 @@ def test_areas_at_00(): 1.641537700693487648e-14, ] - out = [ - h3.cell_area(h3.latlng_to_cell(0, 0, r), unit='rads^2') - for r in range(16) - ] + out = [h3.cell_area(h3.latlng_to_cell(0, 0, r), unit='rads^2') for r in range(16)] assert u.approx2(out, areas_rads2) diff --git a/tests/util.py b/tests/util.py index f6d31776c..b82100c09 100644 --- a/tests/util.py +++ b/tests/util.py @@ -15,7 +15,4 @@ def approx2(a, b): if len(a) != len(b): return False - return all( - x == pytest.approx(y) - for x, y in zip(a, b) - ) + return all(x == pytest.approx(y) for x, y in zip(a, b)) From c14d1a6486f9ba9a0076b47fe04059150f97123b Mon Sep 17 00:00:00 2001 From: Jongbin Jung Date: Fri, 11 Oct 2024 16:00:47 -0700 Subject: [PATCH 2/9] Update github actions to use ruff instead of flake8 and pylint --- .github/workflows/coverage-lint-pr.yml | 27 ++++++++++++++++++++------ .github/workflows/coverage-lint.yml | 27 ++++++++++++++++++++------ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/.github/workflows/coverage-lint-pr.yml b/.github/workflows/coverage-lint-pr.yml index eb689e30e..d96c97d1e 100644 --- a/.github/workflows/coverage-lint-pr.yml +++ b/.github/workflows/coverage-lint-pr.yml @@ -23,13 +23,28 @@ jobs: pip install --upgrade pip setuptools wheel pip install .[test] - - name: Lint - run: flake8 src/h3 tests + - name: Install CLI Reviewdog + uses: reviewdog/action-setup@v1 + + # Order is important for these commands + # Run the actual fixes first so that they are picked up by next GH step but + # removed from the final run of the linter. + # Second run of the linter will report unfixable issues via reviewdog + - name: Run Linting + env: + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ruff format . + ruff check . --fix-only + ruff check . | reviewdog -efm="%f:%l:%c: %m" -reporter=github-pr-review -level=warning - - name: Pylint - # As a test for visibility of API bindings, we want to ensure that pylint has no - # `import-error` warnings for h3 imports. - run: pylint --disable=all --enable=import-error tests/ + # Picks up file changes from the previous action + - name: Suggest Fixes + uses: reviewdog/action-suggester@v1 + with: + tool_name: ruff + github_token: ${{ secrets.GITHUB_TOKEN }} + level: warning - name: Coverage run: | diff --git a/.github/workflows/coverage-lint.yml b/.github/workflows/coverage-lint.yml index 72ef8eade..fed0e6585 100644 --- a/.github/workflows/coverage-lint.yml +++ b/.github/workflows/coverage-lint.yml @@ -23,13 +23,28 @@ jobs: pip install --upgrade pip setuptools wheel pip install .[test] - - name: Lint - run: flake8 src/h3 tests + - name: Install CLI Reviewdog + uses: reviewdog/action-setup@v1 + + # Order is important for these commands + # Run the actual fixes first so that they are picked up by next GH step but + # removed from the final run of the linter. + # Second run of the linter will report unfixable issues via reviewdog + - name: Run Linting + env: + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ruff format . + ruff check . --fix-only + ruff check . | reviewdog -efm="%f:%l:%c: %m" -reporter=github-pr-review -level=warning - - name: Pylint - # As a test for visibility of API bindings, we want to ensure that pylint has no - # `import-error` warnings for h3 imports. - run: pylint --disable=all --enable=import-error tests/ + # Picks up file changes from the previous action + - name: Suggest Fixes + uses: reviewdog/action-suggester@v1 + with: + tool_name: ruff + github_token: ${{ secrets.GITHUB_TOKEN }} + level: warning - name: Coverage run: | From e9a1886fd19f9410b142db4318af9d86760b720d Mon Sep 17 00:00:00 2001 From: Jongbin Jung Date: Fri, 11 Oct 2024 16:13:58 -0700 Subject: [PATCH 3/9] Reorder imports --- tests/polyfill/test_polyfill.py | 2 +- tests/polyfill/test_polygon_class.py | 3 ++- tests/polyfill/test_to_multipoly.py | 1 - tests/test_apis/test_basic_int.py | 1 - tests/test_apis/test_basic_str.py | 1 - tests/test_apis/test_collection_inputs.py | 3 ++- tests/test_apis/test_numpy_int.py | 3 ++- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/polyfill/test_polyfill.py b/tests/polyfill/test_polyfill.py index e530f2032..8c8ec855d 100644 --- a/tests/polyfill/test_polyfill.py +++ b/tests/polyfill/test_polyfill.py @@ -1,6 +1,6 @@ -import h3 import pytest +import h3 from h3 import H3ResDomainError from .. import util as u diff --git a/tests/polyfill/test_polygon_class.py b/tests/polyfill/test_polygon_class.py index 3996d3026..cba7d3ecc 100644 --- a/tests/polyfill/test_polygon_class.py +++ b/tests/polyfill/test_polygon_class.py @@ -1,6 +1,7 @@ -import h3 import pytest +import h3 + def test_repr(): a = '8928308280fffff' diff --git a/tests/polyfill/test_to_multipoly.py b/tests/polyfill/test_to_multipoly.py index 5b361f13e..7c2008e79 100644 --- a/tests/polyfill/test_to_multipoly.py +++ b/tests/polyfill/test_to_multipoly.py @@ -1,6 +1,5 @@ import h3 - from .. import util as u diff --git a/tests/test_apis/test_basic_int.py b/tests/test_apis/test_basic_int.py index 466fe1f3c..49209d5e6 100644 --- a/tests/test_apis/test_basic_int.py +++ b/tests/test_apis/test_basic_int.py @@ -1,6 +1,5 @@ import h3.api.basic_int as h3 - from .. import util as u diff --git a/tests/test_apis/test_basic_str.py b/tests/test_apis/test_basic_str.py index 30b426ab6..fdc38bfa8 100644 --- a/tests/test_apis/test_basic_str.py +++ b/tests/test_apis/test_basic_str.py @@ -1,6 +1,5 @@ import h3.api.basic_str as h3 - from .. import util as u diff --git a/tests/test_apis/test_collection_inputs.py b/tests/test_apis/test_collection_inputs.py index 5f0f8ed08..0794dd7ae 100644 --- a/tests/test_apis/test_collection_inputs.py +++ b/tests/test_apis/test_collection_inputs.py @@ -1,9 +1,10 @@ import numpy as np # only run this test suite if numpy is installed import pytest + from h3.api import ( basic_int, - numpy_int, memview_int, + numpy_int, ) # todo: check when a copy is made, and when it isn't diff --git a/tests/test_apis/test_numpy_int.py b/tests/test_apis/test_numpy_int.py index c341b555a..8a02d65fb 100644 --- a/tests/test_apis/test_numpy_int.py +++ b/tests/test_apis/test_numpy_int.py @@ -1,6 +1,7 @@ -import h3.api.numpy_int as h3 import numpy as np # only run this test suite if numpy is installed +import h3.api.numpy_int as h3 + from .. import util as u From 8982df6d5e114965b9e8c7fd4267fd8068b64907 Mon Sep 17 00:00:00 2001 From: Jongbin Jung Date: Fri, 11 Oct 2024 16:22:01 -0700 Subject: [PATCH 4/9] Update make lint target --- makefile | 3 +-- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index a838caa08..fbd2e30fd 100644 --- a/makefile +++ b/makefile @@ -40,8 +40,7 @@ test: ./env/bin/pytest lint: - ./env/bin/flake8 src/h3 tests - ./env/bin/pylint --disable=all --enable=import-error tests/ + ./env/bin/ruff check --fix lab: ./env/bin/pip install .[all] diff --git a/pyproject.toml b/pyproject.toml index 7f4af1e81..46e3f74ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,7 +97,7 @@ respect-gitignore = true indent-style = "space" quote-style = "single" -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] # Do not enforce usage in init files "__init__.py" = [ "E402", From b4983d5170323f954953611cab1d1a44267eb7cd Mon Sep 17 00:00:00 2001 From: Jongbin Jung Date: Fri, 11 Oct 2024 16:22:36 -0700 Subject: [PATCH 5/9] Remove unnecessary flake8 pragma --- src/h3/__init__.py | 33 +++++------ src/h3/_cy/__init__.py | 123 +++++++++++++++++++---------------------- src/h3/api/__init__.py | 7 +-- 3 files changed, 73 insertions(+), 90 deletions(-) diff --git a/src/h3/__init__.py b/src/h3/__init__.py index d5964d1c0..fa21fae58 100644 --- a/src/h3/__init__.py +++ b/src/h3/__init__.py @@ -1,27 +1,24 @@ -# flake8: noqa - -from .api.basic_str import * -from ._version import __version__ - from ._cy import ( - UnknownH3ErrorCode, H3BaseException, - H3GridNavigationError, - H3MemoryError, - H3ValueError, - H3FailedError, - H3DomainError, - H3LatLngDomainError, - H3ResDomainError, H3CellInvalidError, H3DirEdgeInvalidError, - H3UndirEdgeInvalidError, - H3VertexInvalidError, - H3PentagonError, + H3DomainError, H3DuplicateInputError, - H3NotNeighborsError, - H3ResMismatchError, + H3FailedError, + H3GridNavigationError, + H3LatLngDomainError, H3MemoryAllocError, H3MemoryBoundsError, + H3MemoryError, + H3NotNeighborsError, H3OptionInvalidError, + H3PentagonError, + H3ResDomainError, + H3ResMismatchError, + H3UndirEdgeInvalidError, + H3ValueError, + H3VertexInvalidError, + UnknownH3ErrorCode, ) +from ._version import __version__ +from .api.basic_str import * # noqa diff --git a/src/h3/_cy/__init__.py b/src/h3/_cy/__init__.py index 324bc249d..71456a962 100644 --- a/src/h3/_cy/__init__.py +++ b/src/h3/_cy/__init__.py @@ -1,5 +1,3 @@ -# flake8: noqa - """ This module should serve as the interface between the C/Cython code and the Python code. That is, it is an internal API. @@ -14,93 +12,86 @@ """ from .cells import ( - is_valid_cell, - is_pentagon, - get_base_cell_number, - get_resolution, - cell_to_parent, - grid_distance, - grid_disk, - grid_ring, - cell_to_children_size, - cell_to_children, + average_hexagon_area, + cell_area, + cell_to_center_child, cell_to_child_pos, + cell_to_children, + cell_to_children_size, + cell_to_local_ij, + cell_to_parent, child_pos_to_cell, compact_cells, - uncompact_cells, + get_base_cell_number, + get_icosahedron_faces, get_num_cells, - average_hexagon_area, - cell_area, - grid_path_cells, - is_res_class_iii, get_pentagons, get_res0_cells, - cell_to_center_child, - get_icosahedron_faces, - cell_to_local_ij, + get_resolution, + grid_disk, + grid_distance, + grid_path_cells, + grid_ring, + is_pentagon, + is_res_class_iii, + is_valid_cell, local_ij_to_cell, + uncompact_cells, ) - from .edges import ( are_neighbor_cells, + average_hexagon_edge_length, cells_to_directed_edge, - is_valid_directed_edge, - get_directed_edge_origin, - get_directed_edge_destination, directed_edge_to_cells, - origin_to_directed_edges, - average_hexagon_edge_length, edge_length, + get_directed_edge_destination, + get_directed_edge_origin, + is_valid_directed_edge, + origin_to_directed_edges, +) +from .error_system import ( + H3BaseException, + H3CellInvalidError, + H3DirEdgeInvalidError, + H3DomainError, + H3DuplicateInputError, + H3FailedError, + H3GridNavigationError, + H3LatLngDomainError, + H3MemoryAllocError, + H3MemoryBoundsError, + H3MemoryError, + H3NotNeighborsError, + H3OptionInvalidError, + H3PentagonError, + H3ResDomainError, + H3ResMismatchError, + H3UndirEdgeInvalidError, + H3ValueError, + H3VertexInvalidError, + UnknownH3ErrorCode, ) - from .latlng import ( - latlng_to_cell, - cell_to_latlng, - polygon_to_cells, - polygons_to_cells, cell_to_boundary, + cell_to_latlng, directed_edge_to_boundary, great_circle_distance, + latlng_to_cell, + polygon_to_cells, + polygons_to_cells, ) - -from .vertex import ( - cell_to_vertex, - cell_to_vertexes, - vertex_to_latlng, - is_valid_vertex, +from .memory import ( + iter_to_mv, ) - from .to_multipoly import cells_to_multi_polygon - from .util import ( c_version, - str_to_int, int_to_str, + str_to_int, ) - -from .memory import ( - iter_to_mv, -) - -from .error_system import ( - UnknownH3ErrorCode, - H3BaseException, - H3GridNavigationError, - H3MemoryError, - H3ValueError, - H3FailedError, - H3DomainError, - H3LatLngDomainError, - H3ResDomainError, - H3CellInvalidError, - H3DirEdgeInvalidError, - H3UndirEdgeInvalidError, - H3VertexInvalidError, - H3PentagonError, - H3DuplicateInputError, - H3NotNeighborsError, - H3ResMismatchError, - H3MemoryAllocError, - H3MemoryBoundsError, - H3OptionInvalidError, +from .vertex import ( + cell_to_vertex, + cell_to_vertexes, + is_valid_vertex, + vertex_to_latlng, ) diff --git a/src/h3/api/__init__.py b/src/h3/api/__init__.py index 435b13a15..82c4d6fbd 100644 --- a/src/h3/api/__init__.py +++ b/src/h3/api/__init__.py @@ -1,6 +1 @@ -# flake8: noqa - -from . import basic_int -from . import basic_str -from . import memview_int -from . import numpy_int +from . import basic_int, basic_str, memview_int, numpy_int From e1f4d9bfe7e80a50ea2bc540e153537a57458c34 Mon Sep 17 00:00:00 2001 From: Jongbin Jung Date: Fri, 11 Oct 2024 16:23:40 -0700 Subject: [PATCH 6/9] Apply lint to notebook --- docs/polygon_tutorial.ipynb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/polygon_tutorial.ipynb b/docs/polygon_tutorial.ipynb index 7e0a1e934..6044b8eba 100644 --- a/docs/polygon_tutorial.ipynb +++ b/docs/polygon_tutorial.ipynb @@ -34,13 +34,14 @@ "metadata": {}, "outputs": [], "source": [ - "import h3\n", - "\n", - "import geopandas\n", - "import geodatasets\n", "import contextily as cx\n", + "import geodatasets\n", + "import geopandas\n", "import matplotlib.pyplot as plt\n", "\n", + "import h3\n", + "\n", + "\n", "def plot_df(df, column=None, ax=None):\n", " 'Plot based on the `geometry` column of a GeoPandas dataframe'\n", " df = df.copy()\n", @@ -50,12 +51,12 @@ " fig, ax = plt.subplots(figsize=(8,8))\n", " ax.get_xaxis().set_visible(False)\n", " ax.get_yaxis().set_visible(False)\n", - " \n", + "\n", " df.plot(\n", " ax=ax,\n", " alpha=0.5, edgecolor='k',\n", " column=column, categorical=True,\n", - " legend=True, legend_kwds={'loc': 'upper left'}, \n", + " legend=True, legend_kwds={'loc': 'upper left'},\n", " )\n", " cx.add_basemap(ax, crs=df.crs, source=cx.providers.CartoDB.Positron)\n", "\n", From 98b8299bdb5b0c9389089bb50e6cd81afcde8c52 Mon Sep 17 00:00:00 2001 From: Jongbin Jung Date: Fri, 11 Oct 2024 16:33:07 -0700 Subject: [PATCH 7/9] Apply formatting to notebooks --- docs/polygon_tutorial.ipynb | 35 +++++++++++++++--------- makefile | 1 + tests/polyfill/test_polyfill_ordering.py | 2 +- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/docs/polygon_tutorial.ipynb b/docs/polygon_tutorial.ipynb index 6044b8eba..ab8b3a881 100644 --- a/docs/polygon_tutorial.ipynb +++ b/docs/polygon_tutorial.ipynb @@ -43,33 +43,39 @@ "\n", "\n", "def plot_df(df, column=None, ax=None):\n", - " 'Plot based on the `geometry` column of a GeoPandas dataframe'\n", + " \"Plot based on the `geometry` column of a GeoPandas dataframe\"\n", " df = df.copy()\n", - " df = df.to_crs(epsg=3857) # web mercator\n", + " df = df.to_crs(epsg=3857) # web mercator\n", "\n", " if ax is None:\n", - " fig, ax = plt.subplots(figsize=(8,8))\n", + " fig, ax = plt.subplots(figsize=(8, 8))\n", " ax.get_xaxis().set_visible(False)\n", " ax.get_yaxis().set_visible(False)\n", "\n", " df.plot(\n", " ax=ax,\n", - " alpha=0.5, edgecolor='k',\n", - " column=column, categorical=True,\n", - " legend=True, legend_kwds={'loc': 'upper left'},\n", + " alpha=0.5,\n", + " edgecolor='k',\n", + " column=column,\n", + " categorical=True,\n", + " legend=True,\n", + " legend_kwds={'loc': 'upper left'},\n", " )\n", " cx.add_basemap(ax, crs=df.crs, source=cx.providers.CartoDB.Positron)\n", "\n", + "\n", "def plot_shape(shape, ax=None):\n", " df = geopandas.GeoDataFrame({'geometry': [shape]}, crs='EPSG:4326')\n", " plot_df(df, ax=ax)\n", "\n", + "\n", "def plot_cells(cells, ax=None):\n", " shape = h3.cells_to_h3shape(cells)\n", " plot_shape(shape, ax=ax)\n", "\n", + "\n", "def plot_shape_and_cells(shape, res=9):\n", - " fig, axs = plt.subplots(1,2, figsize=(10,5), sharex=True, sharey=True)\n", + " fig, axs = plt.subplots(1, 2, figsize=(10, 5), sharex=True, sharey=True)\n", " plot_shape(shape, ax=axs[0])\n", " plot_cells(h3.h3shape_to_cells(shape, res), ax=axs[1])\n", " fig.tight_layout()" @@ -93,11 +99,7 @@ "metadata": {}, "outputs": [], "source": [ - "outer = [\n", - " (37.804, -122.412),\n", - " (37.778, -122.507),\n", - " (37.733, -122.501)\n", - "]\n", + "outer = [(37.804, -122.412), (37.778, -122.507), (37.733, -122.501)]\n", "\n", "poly = h3.LatLngPoly(outer)\n", "print(poly)\n", @@ -264,6 +266,7 @@ " def __geo_interface__(self):\n", " return self.d\n", "\n", + "\n", "geo = MockGeo(d)\n", "h3.geo_to_h3shape(geo)" ] @@ -430,7 +433,13 @@ "poly1 = h3.LatLngPoly([(37.804, -122.412), (37.778, -122.507), (37.733, -122.501)])\n", "poly2 = h3.LatLngPoly(\n", " [(37.803, -122.408), (37.736, -122.491), (37.738, -122.380), (37.787, -122.39)],\n", - " [(37.760, -122.441), (37.772, -122.427), (37.773, -122.404), (37.758, -122.401), (37.745, -122.428)]\n", + " [\n", + " (37.760, -122.441),\n", + " (37.772, -122.427),\n", + " (37.773, -122.404),\n", + " (37.758, -122.401),\n", + " (37.745, -122.428),\n", + " ],\n", ")\n", "mpoly = h3.LatLngMultiPoly(poly1, poly2)\n", "\n", diff --git a/makefile b/makefile index fbd2e30fd..185536b11 100644 --- a/makefile +++ b/makefile @@ -41,6 +41,7 @@ test: lint: ./env/bin/ruff check --fix + ./env/bin/ruff format lab: ./env/bin/pip install .[all] diff --git a/tests/polyfill/test_polyfill_ordering.py b/tests/polyfill/test_polyfill_ordering.py index 24ef7e4c8..501d9b0a5 100644 --- a/tests/polyfill/test_polyfill_ordering.py +++ b/tests/polyfill/test_polyfill_ordering.py @@ -1,4 +1,4 @@ -""" Test that `h3shape_to_cells` can take in polygon inputs +"""Test that `h3shape_to_cells` can take in polygon inputs where the LinearRings may or may not follow the right hand rule, and they may or may not be closed loops (where the last element is equal to the first). From 1a5dbfee71c2d307506baf88a5c1c95e91e8e2e4 Mon Sep 17 00:00:00 2001 From: Jongbin Jung Date: Thu, 17 Oct 2024 19:31:34 -0700 Subject: [PATCH 8/9] Remove reviewdog --- .github/workflows/coverage-lint-pr.yml | 22 +--------------------- .github/workflows/coverage-lint.yml | 22 +--------------------- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/.github/workflows/coverage-lint-pr.yml b/.github/workflows/coverage-lint-pr.yml index d96c97d1e..1785d09dc 100644 --- a/.github/workflows/coverage-lint-pr.yml +++ b/.github/workflows/coverage-lint-pr.yml @@ -23,28 +23,8 @@ jobs: pip install --upgrade pip setuptools wheel pip install .[test] - - name: Install CLI Reviewdog - uses: reviewdog/action-setup@v1 - - # Order is important for these commands - # Run the actual fixes first so that they are picked up by next GH step but - # removed from the final run of the linter. - # Second run of the linter will report unfixable issues via reviewdog - name: Run Linting - env: - REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - ruff format . - ruff check . --fix-only - ruff check . | reviewdog -efm="%f:%l:%c: %m" -reporter=github-pr-review -level=warning - - # Picks up file changes from the previous action - - name: Suggest Fixes - uses: reviewdog/action-suggester@v1 - with: - tool_name: ruff - github_token: ${{ secrets.GITHUB_TOKEN }} - level: warning + uses: astral-sh/ruff-action@v1 - name: Coverage run: | diff --git a/.github/workflows/coverage-lint.yml b/.github/workflows/coverage-lint.yml index fed0e6585..7dc1e3a77 100644 --- a/.github/workflows/coverage-lint.yml +++ b/.github/workflows/coverage-lint.yml @@ -23,28 +23,8 @@ jobs: pip install --upgrade pip setuptools wheel pip install .[test] - - name: Install CLI Reviewdog - uses: reviewdog/action-setup@v1 - - # Order is important for these commands - # Run the actual fixes first so that they are picked up by next GH step but - # removed from the final run of the linter. - # Second run of the linter will report unfixable issues via reviewdog - name: Run Linting - env: - REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - ruff format . - ruff check . --fix-only - ruff check . | reviewdog -efm="%f:%l:%c: %m" -reporter=github-pr-review -level=warning - - # Picks up file changes from the previous action - - name: Suggest Fixes - uses: reviewdog/action-suggester@v1 - with: - tool_name: ruff - github_token: ${{ secrets.GITHUB_TOKEN }} - level: warning + uses: astral-sh/ruff-action@v1 - name: Coverage run: | From 1b2474ab60e7104efeb5928d0ca9a5b5a7638cdc Mon Sep 17 00:00:00 2001 From: Jongbin Jung Date: Thu, 17 Oct 2024 19:33:57 -0700 Subject: [PATCH 9/9] Allow lower case hexadecimal in tests --- tests/test_apis/test_basic_int.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_apis/test_basic_int.py b/tests/test_apis/test_basic_int.py index 49209d5e6..75c91b76d 100644 --- a/tests/test_apis/test_basic_int.py +++ b/tests/test_apis/test_basic_int.py @@ -8,7 +8,7 @@ def test_int_output(): lng = -122.418307270836 assert h3.latlng_to_cell(lat, lng, 9) == 617700169958293503 - assert h3.latlng_to_cell(lat, lng, 9) == 0x8928308280FFFFF + assert h3.latlng_to_cell(lat, lng, 9) == 0x8928308280fffff # fmt: skip def test_grid_disk():