Skip to content

Commit

Permalink
Use ruff for pre-commit checks; replaces isort and flake8 (#549)
Browse files Browse the repository at this point in the history
* Use ruff for pre-commit checks; replaces isort and flake8

* Update changelog to include link to this PR

* feat: switch to ruff

* feat: apply formatting changes

* deps: pre-commit autoupdate

* fixup some black formatting

* fixup, docs: changelog

* fix: add I to ruff rules

---------

Co-authored-by: Pete Gadomski <pete.gadomski@gmail.com>
  • Loading branch information
jpolchlo and gadomski authored May 16, 2023
1 parent 74a7909 commit ced2e43
Show file tree
Hide file tree
Showing 37 changed files with 185 additions and 182 deletions.
54 changes: 5 additions & 49 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,54 +1,10 @@
repos:
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: "v0.0.267"
hooks:
- id: isort
language_version: python3.8
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/psf/black
rev: 22.12.0
rev: 23.3.0
hooks:
- id: black
args: ["--safe"]
language_version: python3.8
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
language_version: python3.8
args: [
# E501 let black handle all line length decisions
# W503 black conflicts with "line break before operator" rule
# E203 black conflicts with "whitespace before ':'" rule
"--ignore=E501,W503,E203,C901",
]
- repo: https://github.com/chewse/pre-commit-mirrors-pydocstyle
# 2.1.1
rev: v2.1.1
hooks:
- id: pydocstyle
language_version: python3.8
exclude: ".*(test|alembic|scripts).*"
args:
[
# Check for docstring presence only
"--select=D1",
]
# Don't require docstrings for tests
# '--match=(?!test).*\.py']
# -
# repo: https://github.com/pre-commit/mirrors-mypy
# rev: v0.770
# hooks:
# - id: mypy
# language_version: python3.8
# args: [--no-strict-optional, --ignore-missing-imports]
- repo: https://github.com/PyCQA/pydocstyle
rev: 6.3.0
hooks:
- id: pydocstyle
language_version: python3.8
exclude: ".*(test|alembic|scripts).*"
#args: [
# Don't require docstrings for tests
#'--match=(?!test|alembic|scripts).*\.py',
#]
6 changes: 5 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

### Added

* Add support for POSTing ItemCollections to the /items endpoint of the Transaction Extension ([#547](https://github.com/stac-utils/stac-fastapi/pull/574)
* Add support for POSTing ItemCollections to the /items endpoint of the Transaction Extension ([#547](https://github.com/stac-utils/stac-fastapi/pull/574))

### Changed

* flake8, isort, and pydocstyle replaced by ruff for pre-commit checks ([#549](https://github.com/stac-utils/stac-fastapi/pull/549))

## [2.4.6] - 2023-05-09

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ $ pip install -e stac_fastapi/api[dev]

**Python3.8 only**

This repo is set to use `pre-commit` to run *isort*, *flake8*, *pydocstring*, *black* ("uncompromising Python code formatter") and mypy when committing new code.
This repo is set to use `pre-commit` to run *ruff*, *pydocstring*, *black* ("uncompromising Python code formatter") and mypy when committing new code.

```bash
$ pre-commit install
Expand Down
30 changes: 20 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
[flake8]
ignore = "D203"
exclude = [".git", "__pycache__", "docs/source/conf.py", "build", "dist"]
max-complexity = 12
max-line-length = 90
[tool.ruff]
line-length = 90
select = [
"C9",
"D1",
"E",
"F",
"I",
"W",
]

[tool.isort]
profile = "black"
known_first_party = "stac_fastapi"
known_third_party = ["stac-pydantic", "fastapi"]
sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
[tool.ruff.per-file-ignores]
"**/tests/**/*.py" = ["D1"]

[tool.ruff.isort]
known-first-party = ["stac_fastapi"]
known-third-party = ["stac_pydantic", "fastapi"]
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]

[tool.black]
target-version = ["py38", "py39", "py310", "py311"]
2 changes: 1 addition & 1 deletion stac_fastapi/api/stac_fastapi/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""api submodule."""
"""Api submodule."""
35 changes: 24 additions & 11 deletions stac_fastapi/api/stac_fastapi/api/app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""fastapi app creation."""
"""Fastapi app creation."""
from typing import Any, Dict, List, Optional, Tuple, Type, Union

import attr
Expand Down Expand Up @@ -37,22 +37,32 @@
class StacApi:
"""StacApi factory.
Factory for creating a STAC-compliant FastAPI application. After instantation, the application is accessible from
the `StacApi.app` attribute.
Factory for creating a STAC-compliant FastAPI application. After
instantation, the application is accessible from the `StacApi.app` attribute.
Attributes:
settings:
API settings and configuration, potentially using environment variables. See https://pydantic-docs.helpmanual.io/usage/settings/.
API settings and configuration, potentially using environment
variables. See https://pydantic-docs.helpmanual.io/usage/settings/.
client:
A subclass of `stac_api.clients.BaseCoreClient`. Defines the application logic which is injected into the API.
A subclass of `stac_api.clients.BaseCoreClient`. Defines the
application logic which is injected into the API.
extensions:
API extensions to include with the application. This may include official STAC extensions as well as third-party add ons.
API extensions to include with the application. This may include
official STAC extensions as well as third-party add ons.
exceptions:
Defines a global mapping between exceptions and status codes, allowing configuration of response behavior on certain exceptions (https://fastapi.tiangolo.com/tutorial/handling-errors/#install-custom-exception-handlers).
Defines a global mapping between exceptions and status codes,
allowing configuration of response behavior on certain exceptions
(https://fastapi.tiangolo.com/tutorial/handling-errors/#install-custom-exception-handlers).
app:
The FastAPI application, defaults to a fresh application.
route_dependencies (list of tuples of route scope dicts (eg `{'path': '/collections', 'method': 'POST'}`) and list of dependencies (e.g. `[Depends(oauth2_scheme)]`)):
Applies specified dependencies to specified routes. This is useful for applying custom auth requirements to routes defined elsewhere in the application.
route_dependencies:
List of tuples of route scope dicts (eg `{'path':
'/collections', 'method': 'POST'}`) and list of dependencies (e.g.
`[Depends(oauth2_scheme)]`)). Applies specified dependencies to
specified routes. This is useful
for applying custom auth requirements to routes defined elsewhere in
the application.
"""

settings: ApiSettings = attr.ib()
Expand Down Expand Up @@ -341,8 +351,11 @@ def add_route_dependencies(
"""Add custom dependencies to routes.
Args:
scopes: list of scopes. Each scope should be a dict with a `path` and `method` property.
dependencies: list of [FastAPI dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/) to apply to each scope.
scopes: list of scopes. Each scope should be a dict with a `path`
and `method` property.
dependencies: list of [FastAPI
dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/)
to apply to each scope.
Returns:
None
Expand Down
3 changes: 2 additions & 1 deletion stac_fastapi/api/stac_fastapi/api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@


# TODO: Move to stac-pydantic
# Does that make sense now? The shift to json schema rather than a well-known enumeration makes that less obvious.
# Does that make sense now? The shift to json schema rather than a well-known
# enumeration makes that less obvious.
class ApiExtensions(enum.Enum):
"""Enumeration of available stac api extensions.
Expand Down
5 changes: 3 additions & 2 deletions stac_fastapi/api/stac_fastapi/api/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
class ErrorResponse(TypedDict):
"""A JSON error response returned by the API.
The STAC API spec expects that `code` and `description` are both present in the payload.
The STAC API spec expects that `code` and `description` are both present in
the payload.
Attributes:
code: A code representing the error, semantics are up to implementor.
Expand Down Expand Up @@ -77,7 +78,7 @@ def add_exception_handlers(
Returns:
None
"""
for (exc, code) in status_codes.items():
for exc, code in status_codes.items():
app.add_exception_handler(exc, exception_handler_factory(code))

# By default FastAPI will return 422 status codes for invalid requests
Expand Down
13 changes: 6 additions & 7 deletions stac_fastapi/api/stac_fastapi/api/middleware.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""api middleware."""
"""Api middleware."""
import re
import typing
from http.client import HTTP_PORT, HTTPS_PORT
Expand All @@ -9,8 +9,8 @@


class CORSMiddleware(_CORSMiddleware):
"""
Subclass of Starlette's standard CORS middleware with default values set to those reccomended by the STAC API spec.
"""Subclass of Starlette's standard CORS middleware with default values set to those
reccomended by the STAC API spec.
https://github.com/radiantearth/stac-api-spec/blob/914cf8108302e2ec734340080a45aaae4859bb63/implementation.md#cors
"""
Expand Down Expand Up @@ -44,12 +44,11 @@ def __init__(


class ProxyHeaderMiddleware:
"""
Account for forwarding headers when deriving base URL.
"""Account for forwarding headers when deriving base URL.
Prioritise standard Forwarded header, look for non-standard X-Forwarded-* if missing.
Default to what can be derived from the URL if no headers provided.
Middleware updates the host header that is interpreted by starlette when deriving Request.base_url.
Default to what can be derived from the URL if no headers provided. Middleware updates
the host header that is interpreted by starlette when deriving Request.base_url.
"""

def __init__(self, app: ASGIApp):
Expand Down
4 changes: 2 additions & 2 deletions stac_fastapi/api/stac_fastapi/api/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""api request/response models."""
"""Api request/response models."""

import importlib.util
from typing import Optional, Type, Union
Expand Down Expand Up @@ -44,7 +44,7 @@ def create_request_model(
# Handle POST requests
elif all([issubclass(m, BaseModel) for m in models]):
for model in models:
for (k, v) in model.__fields__.items():
for k, v in model.__fields__.items():
field_info = v.field_info
body = Body(
None
Expand Down
4 changes: 2 additions & 2 deletions stac_fastapi/api/stac_fastapi/api/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ def __init__(self, *args, **kwargs):
def update_openapi(app: FastAPI) -> FastAPI:
"""Update OpenAPI response content-type.
This function modifies the openapi route to comply with the STAC API spec's
required content-type response header.
This function modifies the openapi route to comply with the STAC API spec's required
content-type response header.
"""
# Find the route for the openapi_url in the app
openapi_route: Route = next(
Expand Down
6 changes: 3 additions & 3 deletions stac_fastapi/api/stac_fastapi/api/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""route factories."""
"""Route factories."""
import functools
import inspect
from typing import Any, Callable, Dict, List, Optional, Type, TypedDict, Union
Expand Down Expand Up @@ -104,7 +104,6 @@ def add_route_dependencies(
"""
for scope in scopes:
for route in routes:

match, _ = route.matches({"type": "http", **scope})
if match != Match.FULL:
continue
Expand All @@ -120,7 +119,8 @@ def add_route_dependencies(
)

# Register dependencies directly on route so that they aren't ignored if
# the routes are later associated with an app (e.g. app.include_router(router))
# the routes are later associated with an app (e.g.
# app.include_router(router))
# https://github.com/tiangolo/fastapi/blob/58ab733f19846b4875c5b79bfb1f4d1cb7f4823f/fastapi/applications.py#L337-L360
# https://github.com/tiangolo/fastapi/blob/58ab733f19846b4875c5b79bfb1f4d1cb7f4823f/fastapi/routing.py#L677-L678
route.dependencies.extend(dependencies)
2 changes: 1 addition & 1 deletion stac_fastapi/api/stac_fastapi/api/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""library version."""
"""Library version."""
__version__ = "2.4.6"
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""extensions submodule."""
"""Extensions submodule."""
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""context extension."""
"""Context extension."""
from typing import List, Optional

import attr
Expand All @@ -11,9 +11,9 @@
class ContextExtension(ApiExtension):
"""Context Extension.
The Context extension adds a JSON object to ItemCollection responses (`/search`, `/collections/{collection_id}/items`)
which includes the number of items matched, returned, and the limit requested.
The Context extension adds a JSON object to ItemCollection responses (`/search`,
`/collections/{collection_id}/items`) which includes the number of items matched,
returned, and the limit requested.
https://github.com/radiantearth/stac-api-spec/blob/master/item-search/README.md#context
"""

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""fields extension."""
"""Fields extension."""
from typing import List, Optional, Set

import attr
Expand All @@ -13,17 +13,19 @@
class FieldsExtension(ApiExtension):
"""Fields Extension.
The Fields extension adds functionality to the `/search` endpoint which allows the caller to include or exclude
specific from the API response. Registering this extension with the application has the added effect of removing
the `ItemCollection` response model from the `/search` endpoint, as the Fields extension allows the API to return
potentially invalid responses by excluding fields which are required by the STAC spec, such as geometry.
The Fields extension adds functionality to the `/search` endpoint which
allows the caller to include or exclude specific from the API response.
Registering this extension with the application has the added effect of
removing the `ItemCollection` response model from the `/search` endpoint, as
the Fields extension allows the API to return potentially invalid responses
by excluding fields which are required by the STAC spec, such as geometry.
https://github.com/radiantearth/stac-api-spec/blob/master/item-search/README.md#fields
Attributes:
default_includes (set): defines the default set of included fields.
conformance_classes (list): Defines the list of conformance classes for the extension
conformance_classes (list): Defines the list of conformance classes for
the extension
"""

GET = FieldsExtensionGetRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class PostFieldsExtension(BaseModel):
def _get_field_dict(fields: Optional[Set[str]]) -> Dict:
"""Pydantic include/excludes notation.
Internal method to create a dictionary for advanced include or exclude of pydantic fields on model export
Internal method to create a dictionary for advanced include or exclude
of pydantic fields on model export
Ref: https://pydantic-docs.helpmanual.io/usage/exporting_models/#advanced-include-and-exclude
"""
field_dict = {}
Expand All @@ -44,8 +45,8 @@ def _get_field_dict(fields: Optional[Set[str]]) -> Dict:
def filter_fields(self) -> Dict:
"""Create pydantic include/exclude expression.
Create dictionary of fields to include/exclude on model export based on the included and excluded fields passed
to the API
Create dictionary of fields to include/exclude on model export based on
the included and excluded fields passed to the API
Ref: https://pydantic-docs.helpmanual.io/usage/exporting_models/#advanced-include-and-exclude
"""
# Always include default_includes, even if they
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
class FilterConformanceClasses(str, Enum):
"""Conformance classes for the Filter extension.
See https://github.com/radiantearth/stac-api-spec/tree/v1.0.0-rc.1/fragments/filter
See
https://github.com/radiantearth/stac-api-spec/tree/v1.0.0-rc.1/fragments/filter
"""

FILTER = "http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/filter"
Expand Down Expand Up @@ -50,8 +51,9 @@ class FilterConformanceClasses(str, Enum):
class FilterExtension(ApiExtension):
"""Filter Extension.
The filter extension adds several endpoints which allow the retrieval of queryables and
provides an expressive mechanism for searching based on Item Attributes:
The filter extension adds several endpoints which allow the retrieval of
queryables and provides an expressive mechanism for searching based on Item
Attributes:
GET /queryables
GET /collections/{collection_id}/queryables
Expand All @@ -60,7 +62,6 @@ class FilterExtension(ApiExtension):
Attributes:
client: Queryables endpoint logic
conformance_classes: Conformance classes provided by the extension
"""

GET = FilterExtensionGetRequest
Expand Down
Loading

0 comments on commit ced2e43

Please sign in to comment.