From dfc2570aba7395e07a2d2c664660211b4c18376a Mon Sep 17 00:00:00 2001 From: Wang Boyu Date: Fri, 5 Jan 2024 09:07:33 +0800 Subject: [PATCH 1/2] update pre-commit and ga workflows to be consistent with mesa --- .codespellignore | 8 ++++++ .github/workflows/build_lint.yml | 17 ++++++------ .github/workflows/codespell.yml | 18 +++++++++++++ .github/workflows/release.yml | 44 ++++++++++++++++++++++++++++++++ .pre-commit-config.yaml | 16 ++++++++---- 5 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 .codespellignore create mode 100644 .github/workflows/codespell.yml create mode 100644 .github/workflows/release.yml diff --git a/.codespellignore b/.codespellignore new file mode 100644 index 00000000..0ce71b7b --- /dev/null +++ b/.codespellignore @@ -0,0 +1,8 @@ +hist +hart +mutch +ist +inactivate +ue +fpr +falsy \ No newline at end of file diff --git a/.github/workflows/build_lint.yml b/.github/workflows/build_lint.yml index 2e048888..64f2f822 100644 --- a/.github/workflows/build_lint.yml +++ b/.github/workflows/build_lint.yml @@ -20,8 +20,10 @@ jobs: fail-fast: False matrix: os: [windows, ubuntu, macos] - python-version: ["3.11"] + python-version: ["3.12"] include: + - os: ubuntu + python-version: "3.11" - os: ubuntu python-version: "3.10" - os: ubuntu @@ -54,24 +56,23 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up Python 3.10 + - name: Set up Python 3.12 uses: actions/setup-python@v5 with: - python-version: "3.10" - - run: pip install ruff==0.0.254 + python-version: "3.12" + - run: pip install ruff==0.1.5 - name: Lint with ruff - # Include `--format=github` to enable automatic inline annotations. # Use settings from pyproject.toml. - run: ruff . --format=github + run: ruff . lint-black: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up Python 3.10 + - name: Set up Python 3.12 uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.12" - run: pip install black[jupyter] - name: Lint with black run: black --check . diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 00000000..575809a4 --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,18 @@ +name: build + +on: + push: + branches: + - main + - release** + pull_request: + +jobs: + codespell: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: codespell-project/actions-codespell@master + with: + ignore_words_file: .codespellignore + skip: .*bootstrap.*,*.js,.*bootstrap-theme.css.map \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..aa145dc0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,44 @@ +name: Release +on: + push: + branches: + - main + - release** + paths-ignore: + - '**.md' + - '**.rst' + pull_request: + paths-ignore: + - '**.md' + - '**.rst' + workflow_dispatch: + +permissions: + id-token: write + +jobs: + release: + name: Deploy release to PyPI + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout source + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + - name: Install dependencies + run: pip install -U pip build wheel setuptools + - name: Build distributions + run: python -m build + - name: Upload package as artifact to GitHub + if: github.repository == 'projectmesa/mesa-geo' && startsWith(github.ref, 'refs/tags') + uses: actions/upload-artifact@v3 + with: + name: package + path: dist/ + - name: Publish package to PyPI + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@release/v1 \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 843d3227..4facb013 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,10 +3,16 @@ ci: autofix_prs: false repos: -- repo: https://github.com/psf/black - rev: 23.12.1 - hooks: - - id: black-jupyter +- repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.1.5 + hooks: + # Run the linter. + - id: ruff + types_or: [ python, pyi, jupyter ] + # Run the formatter. + - id: ruff-format + types_or: [ python, pyi, jupyter ] - repo: https://github.com/asottile/pyupgrade rev: v3.15.0 hooks: @@ -17,4 +23,4 @@ repos: hooks: - id: trailing-whitespace - id: check-toml - - id: check-yaml + - id: check-yaml \ No newline at end of file From 110b6c02a46c7ab24c6903c28d0b5c80158a8983 Mon Sep 17 00:00:00 2001 From: Wang Boyu Date: Fri, 5 Jan 2024 09:39:11 +0800 Subject: [PATCH 2/2] fix ruff errors --- mesa_geo/geoagent.py | 11 ++++++++--- mesa_geo/geospace.py | 8 ++++++-- mesa_geo/raster_layers.py | 2 +- pyproject.toml | 6 +++++- tests/test_GeoSpace.py | 14 +++++++------- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/mesa_geo/geoagent.py b/mesa_geo/geoagent.py index f514b615..73887cd2 100644 --- a/mesa_geo/geoagent.py +++ b/mesa_geo/geoagent.py @@ -110,7 +110,9 @@ def __init__(self, agent_class, model=None, crs=None, agent_kwargs=None): if agent_kwargs and "unique_id" in agent_kwargs: agent_kwargs.remove("unique_id") - warnings.warn("Unique_id should not be in the agent_kwargs") + warnings.warn( + "Unique_id should not be in the agent_kwargs", UserWarning, stacklevel=2 + ) self.agent_class = agent_class self.model = model @@ -219,7 +221,10 @@ def from_file(self, filename, unique_id="index", set_attributes=True): return agents def from_GeoJSON( - self, GeoJSON, unique_id="index", set_attributes=True # noqa: N803 + self, + GeoJSON, # noqa: N803 + unique_id="index", + set_attributes=True, ): """ Create agents from a GeoJSON object or string. CRS is set to epsg:4326. @@ -230,7 +235,7 @@ def from_GeoJSON( :param set_attributes: Set agent attributes from GeoDataFrame columns. Default True. """ - gj = json.loads(GeoJSON) if type(GeoJSON) is str else GeoJSON + gj = json.loads(GeoJSON) if isinstance(GeoJSON, str) else GeoJSON gdf = gpd.GeoDataFrame.from_features(gj) # epsg:4326 is the CRS for all GeoJSON: https://datatracker.ietf.org/doc/html/rfc7946#section-4 diff --git a/mesa_geo/geospace.py b/mesa_geo/geospace.py index 44e3c8d8..83d6ab20 100644 --- a/mesa_geo/geospace.py +++ b/mesa_geo/geospace.py @@ -131,7 +131,9 @@ def add_layer(self, layer: ImageLayer | RasterLayer | gpd.GeoDataFrame) -> None: f"Converting {layer.__class__.__name__} from crs {layer.crs.to_string()} " f"to the crs of {self.__class__.__name__} - {self.crs.to_string()}. " "Please check your crs settings if this is unintended, or set `GeoSpace.warn_crs_conversion` " - "to `False` to suppress this warning message." + "to `False` to suppress this warning message.", + UserWarning, + stacklevel=2, ) layer.to_crs(self.crs, inplace=True) self._total_bounds = None @@ -145,7 +147,9 @@ def _check_agent(self, agent): f"Converting {agent.__class__.__name__} from crs {agent.crs.to_string()} " f"to the crs of {self.__class__.__name__} - {self.crs.to_string()}. " "Please check your crs settings if this is unintended, or set `GeoSpace.warn_crs_conversion` " - "to `False` to suppress this warning message." + "to `False` to suppress this warning message.", + UserWarning, + stacklevel=2, ) agent.to_crs(self.crs, inplace=True) else: diff --git a/mesa_geo/raster_layers.py b/mesa_geo/raster_layers.py index 9b66e8e6..9ccb2238 100644 --- a/mesa_geo/raster_layers.py +++ b/mesa_geo/raster_layers.py @@ -694,4 +694,4 @@ def from_file(cls, image_file) -> ImageLayer: return obj def __repr__(self) -> str: - return f"{self.__class__.__name__}(crs={self.crs}, total_bounds={self.total_bounds}, values={repr(self.values)})" + return f"{self.__class__.__name__}(crs={self.crs}, total_bounds={self.total_bounds}, values={self.values!r})" diff --git a/pyproject.toml b/pyproject.toml index 88bfa0a5..1252b212 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,11 @@ extend-ignore = [ "PGH004", # Use specific rule codes when using `noqa` TODO "B905", # `zip()` without an explicit `strict=` parameter "N802", # Function name should be lowercase - "N999", # Invalid module name + "N999", # Invalid module name. We should revisit this in the future, TODO + "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` TODO + "S310", # Audit URL open for permitted schemes. Allowing use of `file:` or custom schemes is often unexpected. + "S603", # `subprocess` call: check for execution of untrusted input + "ISC001", # ruff format asks to disable this feature ] extend-exclude = ["docs", "build"] # Hardcode to Python 3.8. diff --git a/tests/test_GeoSpace.py b/tests/test_GeoSpace.py index f18c36d1..9e338d7a 100644 --- a/tests/test_GeoSpace.py +++ b/tests/test_GeoSpace.py @@ -88,7 +88,7 @@ def test_add_agents_with_different_crs(self): def test_remove_agent(self): self.geo_space.add_agents(self.agents) - agent_to_remove = random.choice(self.agents) + agent_to_remove = random.choice(self.agents) # noqa: S311 self.geo_space.remove_agent(agent_to_remove) remaining_agent_idx = {agent.unique_id for agent in self.geo_space.agents} @@ -121,7 +121,7 @@ def test_add_vector_layer(self): def test_get_neighbors_within_distance(self): self.geo_space.add_agents(self.agents) - agent_to_check = random.choice(self.agents) + agent_to_check = random.choice(self.agents) # noqa: S311 neighbors = list( self.geo_space.get_neighbors_within_distance( @@ -175,9 +175,9 @@ def test_get_relation_within(self): list(self.geo_space.get_relation(self.agents[0], relation="within")), [] ) self.geo_space.add_agents(self.polygon_agent) - within_agent = list( + within_agent = next( self.geo_space.get_relation(self.agents[0], relation="within") - )[0] + ) self.assertEqual(within_agent.unique_id, self.polygon_agent.unique_id) def test_get_relation_touches(self): @@ -196,9 +196,9 @@ def test_get_relation_touches(self): 1, ) self.assertEqual( - list(self.geo_space.get_relation(self.polygon_agent, relation="touches"))[ - 0 - ].unique_id, + next( + self.geo_space.get_relation(self.polygon_agent, relation="touches") + ).unique_id, self.touching_agent.unique_id, )