Skip to content

Commit

Permalink
Merge pull request #256 from lsst-sqre/tickets/DM-38425
Browse files Browse the repository at this point in the history
DM-38425: Switch to Ruff for linting
  • Loading branch information
rra authored May 12, 2023
2 parents 092d825 + f9289ca commit 19645d4
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 106 deletions.
7 changes: 0 additions & 7 deletions .flake8

This file was deleted.

20 changes: 4 additions & 16 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ repos:
- id: check-yaml
- id: check-toml

- 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
additional_dependencies: [toml]
- id: ruff
args: [--fix, --exit-non-zero-on-fix]

- repo: https://github.com/psf/black
rev: 23.3.0
Expand All @@ -23,15 +23,3 @@ repos:
- id: blacken-docs
additional_dependencies: [black==23.3.0]
args: [-l, '79', -t, py311]

- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8

- repo: https://github.com/pycqa/pydocstyle
rev: 6.3.0
hooks:
- id: pydocstyle
additional_dependencies: [toml]
files: ^src/
94 changes: 40 additions & 54 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,6 @@ build-backend = "setuptools.build_meta"

[tool.setuptools_scm]

[tool.coverage.run]
parallel = true
branch = true
source = ["mobu"]

[tool.coverage.paths]
source = ["src", ".tox/*/site-packages"]

[tool.coverage.report]
show_missing = true
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:"
]

[tool.black]
line-length = 79
target-version = ["py311"]
Expand All @@ -75,40 +53,27 @@ exclude = '''
# Use single-quoted strings so TOML treats the string like a Python r-string
# Multi-line strings are implicitly treated by black as regular expressions

[tool.isort]
profile = "black"
line_length = 79
known_first_party = ["mobu", "tests"]
skip = ["docs/conf.py"]
[tool.coverage.run]
parallel = true
branch = true
source = ["mobu"]

[tool.pydocstyle]
# Reference: https://www.pydocstyle.org/en/stable/error_codes.html
convention = "numpy"
add-ignore = [
"D105", # Missing docstring in magic method
"D104", # Missing docstring in public package
"D102", # Missing docstring in public method (docstring inheritance)
"D100", # Missing docstring in public module
# Nested classes named Config are used by Pydantic for configuration, and
# don't have a meaningful docstring.
"D106",
]
[tool.coverage.paths]
source = ["src", ".tox/*/site-packages"]

[tool.pytest.ini_options]
asyncio_mode = "strict"
filterwarnings = [
# Bug in aiojobs
"ignore:with timeout\\(\\) is deprecated:DeprecationWarning"
[tool.coverage.report]
show_missing = true
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:"
]
# The python_files setting is not for test detection (pytest will pick up any
# test files named *_test.py without this setting) but to enable special
# assert processing in any non-test supporting files under tests. We
# conventionally put test support functions under tests.support and may
# sometimes use assert in test fixtures in conftest.py, and pytest only
# enables magical assert processing (showing a full diff on assert failures
# with complex data structures rather than only the assert message) in files
# listed in python_files.
python_files = ["tests/*.py", "tests/*/*.py"]

[tool.mypy]
disallow_untyped_defs = true
Expand All @@ -129,6 +94,22 @@ init_typed = true
warn_required_dynamic_aliases = true
warn_untyped_fields = true

[tool.pytest.ini_options]
asyncio_mode = "strict"
filterwarnings = [
# Bug in aiojobs
"ignore:with timeout\\(\\) is deprecated:DeprecationWarning"
]
# The python_files setting is not for test detection (pytest will pick up any
# test files named *_test.py without this setting) but to enable special
# assert processing in any non-test supporting files under tests. We
# conventionally put test support functions under tests.support and may
# sometimes use assert in test fixtures in conftest.py, and pytest only
# enables magical assert processing (showing a full diff on assert failures
# with complex data structures rather than only the assert message) in files
# listed in python_files.
python_files = ["tests/*.py", "tests/*/*.py"]

# The rule used with Ruff configuration is to disable every lint that has
# legitimate exceptions that are not dodgy code, rather than cluttering code
# with noqa markers. This is therefore a reiatively relaxed configuration that
Expand All @@ -147,7 +128,6 @@ ignore = [
"BLE001", # we want to catch and report Exception in background tasks
"COM812", # omitting trailing commas allows black autoreformatting
"D102", # sometimes we use docstring inheritence
"D103", # FastAPI handlers should not have docstrings
"D104", # don't see the point of documenting every package
"D105", # our style doesn't require docstrings for magic methods
"D106", # Pydantic uses a nested Config class that doesn't warrant docs
Expand All @@ -156,8 +136,10 @@ ignore = [
"FBT003", # positional booleans are normal for Pydantic field defaults
"G004", # forbidding logging f-strings is appealing, but not our style
"RET505", # disagree that omitting else always makes code more readable
"PLR0913", # factory pattern uses constructors with many arguments
"PLR2004", # too aggressive about magic values
"SIM102", # sometimes the formatting of nested if statements is clearer
"SIM117", # sometimes nested with contexts are clearer
"TCH001", # we decided to not maintain separate TYPE_CHECKING blocks
"TCH002", # we decided to not maintain separate TYPE_CHECKING blocks
"TCH003", # we decided to not maintain separate TYPE_CHECKING blocks
Expand All @@ -168,7 +150,11 @@ select = ["ALL"]
target-version = "py311"

[tool.ruff.per-file-ignores]
"src/mobu/handlers/**" = [
"D103", # FastAPI handlers should not have docstrings
]
"tests/**" = [
"D103", # tests don't need docstrings
"PLR0915", # tests are allowed to be long, sometimes that's convenient
"PT012", # way too aggressive about limiting pytest.raises blocks
"S101", # tests should use assert
Expand Down
36 changes: 18 additions & 18 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -416,24 +416,24 @@ respx==0.20.1 \
--hash=sha256:372f06991c03d1f7f480a420a2199d01f1815b6ed5a802f4e4628043a93bd03e \
--hash=sha256:cc47a86d7010806ab65abdcf3b634c56337a737bb5c4d74c19a0dfca83b3bc73
# via -r requirements/dev.in
ruff==0.0.266 \
--hash=sha256:1c9d52820a4744e9cfb4bc2492c8ecd6329147366a7e86cf198c0b2f7f4532af \
--hash=sha256:422da2da16fd1a38f9731c2f54320e2550a1ae51f9f494b6c11002acd8b53b43 \
--hash=sha256:5a80e6279d2af09d0827804356c6c73b0f47b9ee116dfd0a225aa2a203839a17 \
--hash=sha256:6722812b8a5e5ca57f20983dfa4eed4b379ce2c5648e8a4462c43dc90a6f7ab0 \
--hash=sha256:75b6c78a1b9d4eb4146a110949a9530f788438b813351bddcdcf373e46b33910 \
--hash=sha256:784cb211de2a67a1374e9936db9de8923c922e64efc5f4ddc37511dd464459a1 \
--hash=sha256:7ad7b69b40e009aa96551971bea740bf2332c1739085cf7a79fee6ef11105d29 \
--hash=sha256:86d931303fb5c43945ab5774d53a28167f4c9b40712553b52329f16a79e9ff10 \
--hash=sha256:8a80b5641572c76a77be69d063ee7b408b1aa9ef583b97862a1d8b2dfac41a15 \
--hash=sha256:8afe32e66ecd18f7f169587ea86260ce0666a026c83370dc50ba2a7eca8acd40 \
--hash=sha256:94304a0c65219e5156caa0846b2b9dd35eb508aa79f470a7a4a6363681a6ee0a \
--hash=sha256:a358e036c6c797c32986e2c6a1dc258a83439c8283c4520d029e505a4d2fd9a1 \
--hash=sha256:a53dc7d99937305519072e390714fab9d6ccffc57c1f04e81eb95d6549c333df \
--hash=sha256:c543bcf4d55f244816e00811dc3a00a122ba14cc0c0ba636dbaf3a765eaeba81 \
--hash=sha256:e9a89114336a2d2ad5fd237381dfbaf1d8e7e8b34f01eba283549e3e8802f6f8 \
--hash=sha256:fbc094bc88893e43b506343b7643f46d0ee58b8726cb0521cf72caa95730cfe1 \
--hash=sha256:ff892ed9108ee888c6a8f2b8efec47c40dd7dac1977d575e2b4d69ef9363af25
ruff==0.0.267 \
--hash=sha256:0afca3633c8e2b6c0a48ad0061180b641b3b404d68d7e6736aab301c8024c424 \
--hash=sha256:20c594eb56c19063ef5a57f89340e64c6550e169d6a29408a45130a8c3068adc \
--hash=sha256:2107cec3699ca4d7bd41543dc1d475c97ae3a21ea9212238b5c2088fa8ee7722 \
--hash=sha256:2972241065b1c911bce3db808837ed10f4f6f8a8e15520a4242d291083605ab6 \
--hash=sha256:45d61a2b01bdf61581a2ee039503a08aa603dc74a6bbe6fb5d1ce3052f5370e5 \
--hash=sha256:4adbbbe314d8fcc539a245065bad89446a3cef2e0c9cf70bf7bb9ed6fe31856d \
--hash=sha256:5a898953949e37c109dd242cfcf9841e065319995ebb7cdfd213b446094a942f \
--hash=sha256:632cec7bbaf3c06fcf0a72a1dd029b7d8b7f424ba95a574aaa135f5d20a00af7 \
--hash=sha256:67254ae34c38cba109fdc52e4a70887de1f850fb3971e5eeef343db67305d1c1 \
--hash=sha256:786de30723c71fc46b80a173c3313fc0dbe73c96bd9da8dd1212cbc2f84cdfb2 \
--hash=sha256:7df7eb5f8d791566ba97cc0b144981b9c080a5b861abaf4bb35a26c8a77b83e9 \
--hash=sha256:9adf1307fa9d840d1acaa477eb04f9702032a483214c409fca9dc46f5f157fe3 \
--hash=sha256:bbe104f21a429b77eb5ac276bd5352fd8c0e1fbb580b4c772f77ee8c76825654 \
--hash=sha256:d09aecc9f5845586ba90911d815f9772c5a6dcf2e34be58c6017ecb124534ac4 \
--hash=sha256:d12ab329474c46b96d962e2bdb92e3ad2144981fe41b89c7770f370646c0101f \
--hash=sha256:db33deef2a5e1cf528ca51cc59dd764122a48a19a6c776283b223d147041153f \
--hash=sha256:f731d81cb939e757b0335b0090f18ca2e9ff8bcc8e6a1cf909245958949b6e11
# via -r requirements/dev.in
scriv[toml]==1.3.1 \
--hash=sha256:4df597ee0a7b3dcc0d5315d7649df091efcb1b3ff08f0b51a698340727d17118 \
Expand Down
8 changes: 4 additions & 4 deletions src/mobu/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def from_exception(
GafaelfawrParseError
Constructed exception.
"""
error = f"{type(exc).__name__}: {str(exc)}"
error = f"{type(exc).__name__}: {exc!s}"
return cls("Unable to parse reply from Gafalefawr", error, user)

def __init__(
Expand Down Expand Up @@ -339,7 +339,7 @@ def from_exception(cls, log: str, exc: Exception, user: str) -> Self:
JupyterSpawnError
Converted exception.
"""
return cls(log, user, f"{type(exc).__name__}: {str(exc)}")
return cls(log, user, f"{type(exc).__name__}: {exc!s}")

def __init__(
self, log: str, user: str, message: str | None = None
Expand Down Expand Up @@ -398,7 +398,7 @@ def from_exception(cls, exc: WebSocketException, user: str) -> Self:
JupyterWebSocketError
Newly-created exception.
"""
error = f"{type(exc).__name__}: {str(exc)}"
error = f"{type(exc).__name__}: {exc!s}"
if isinstance(exc, InvalidStatus):
status = exc.response.status_code
return cls(
Expand Down Expand Up @@ -459,5 +459,5 @@ class TAPClientError(MobuSlackException):
"""Creating a TAP client failed."""

def __init__(self, exc: Exception, *, user: str) -> None:
msg = f"Unable to create TAP client: {type(exc).__name__}: {str(exc)}"
msg = f"Unable to create TAP client: {type(exc).__name__}: {exc!s}"
super().__init__(msg, user)
2 changes: 1 addition & 1 deletion src/mobu/services/business/notebookrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def read_notebook(self, notebook: Path) -> list[dict[str, Any]]:
notebook_text = notebook.read_text()
cells = json.loads(notebook_text)["cells"]
except Exception as e:
msg = f"Invalid notebook {notebook.name}: {str(e)}"
msg = f"Invalid notebook {notebook.name}: {e!s}"
raise NotebookRepositoryError(msg, self.user.username) from e

# Add cell numbers to all the cells, which we'll use in exception
Expand Down
2 changes: 1 addition & 1 deletion src/mobu/services/business/tapqueryrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ async def execute(self) -> None:
user=self.user.username,
code=query,
code_type="TAP query",
error=f"{type(e).__name__}: {str(e)}",
error=f"{type(e).__name__}: {e!s}",
) from e

self._running_query = None
Expand Down
2 changes: 1 addition & 1 deletion src/mobu/services/monkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ async def alert(self, exc: Exception) -> None:
else:
now = current_datetime(microseconds=True)
date = format_datetime_for_logging(now)
error = f"{type(exc).__name__}: {str(exc)}"
error = f"{type(exc).__name__}: {exc!s}"
message = SlackMessage(
message=f"Unexpected exception {error}",
fields=[
Expand Down
4 changes: 2 additions & 2 deletions src/mobu/storage/cachemachine.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ async def _get_images(self) -> list[JupyterCachemachineImage]:
msg = f"Cannot get image status: {e.response.status_code}"
raise CachemachineError(self._username, msg) from e
except HTTPError as e:
msg = f"Cannot get image status: {type(e).__name__}: {str(e)}"
msg = f"Cannot get image status: {type(e).__name__}: {e!s}"
raise CachemachineError(self._username, msg) from e

try:
Expand All @@ -156,5 +156,5 @@ async def _get_images(self) -> list[JupyterCachemachineImage]:
JupyterCachemachineImage.from_dict(i) for i in data["images"]
]
except Exception as e:
msg = f"Invalid response: {type(e).__name__}: {str(e)}"
msg = f"Invalid response: {type(e).__name__}: {e!s}"
raise CachemachineError(self._username, msg) from e
4 changes: 2 additions & 2 deletions src/mobu/storage/jupyter.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async def __aiter__(self) -> AsyncIterator[SpawnProgressMessage]:
ready=event_dict.get("ready", False),
)
except Exception as e:
err = f"{type(e).__name__}: {str(e)}"
err = f"{type(e).__name__}: {e!s}"
msg = f"Error parsing progress event, ignoring: {err}"
self._logger.warning(msg, type=sse.event, data=sse.data)
continue
Expand Down Expand Up @@ -330,7 +330,7 @@ async def run_python(self, code: str) -> str:
e.code = code
raise
except Exception as e:
error = f"{type(e).__name__}: {str(e)}"
error = f"{type(e).__name__}: {e!s}"
msg = "Ignoring unparsable web socket message"
self._logger.warning(msg, error=error, message=message)

Expand Down

0 comments on commit 19645d4

Please sign in to comment.