Skip to content

Commit f751925

Browse files
committed
Switch to ruff. Fully typed project now.
Signed-off-by: Pedro Algarvio <[email protected]>
1 parent 54652be commit f751925

File tree

10 files changed

+526
-309
lines changed

10 files changed

+526
-309
lines changed

.pre-commit-config.yaml

Lines changed: 9 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,14 @@ repos:
1616
# ----- Local Hooks --------------------------------------------------------------------------->
1717
# <---- Local Hooks ----------------------------------------------------------------------------
1818

19-
# ----- Formatting ---------------------------------------------------------------------------->
20-
- repo: https://github.com/asottile/reorder_python_imports
21-
rev: v3.9.0
19+
# ----- Code Formatting and Analysis ---------------------------------------------------------->
20+
- repo: https://github.com/charliermarsh/ruff-pre-commit
21+
rev: "v0.0.270"
2222
hooks:
23-
- id: reorder-python-imports
24-
args: [
25-
--py39-plus,
26-
--application-directories=.:src,
27-
--add-import=from __future__ import annotations
28-
]
29-
exclude: (?x)^(
30-
setup
31-
|
32-
noxfile
33-
|
34-
demo/.*
35-
|
36-
.pre-commit-hooks/.*
37-
|
38-
src/ptscripts/version
39-
)\.py$
40-
41-
- repo: https://github.com/asottile/pyupgrade
42-
rev: v3.3.1
43-
hooks:
44-
- id: pyupgrade
45-
name: Rewrite Code to be Py3.9+
46-
args: [
47-
--py39-plus
48-
]
49-
files: ^((setup|noxfile)|(src|tests)/.*)\.py$
50-
exclude: (?x)^(
51-
demo/.*
52-
|
53-
.pre-commit-hooks/.*
54-
|
55-
src/ptscripts/version
56-
)\.py
23+
- id: ruff
24+
args:
25+
- --fix
26+
exclude: (.pre-commit-hooks/.*|docs/.*)\.py
5727

5828
- repo: https://github.com/psf/black
5929
rev: 23.1.0
@@ -69,39 +39,7 @@ repos:
6939
args: [--skip-errors]
7040
files: ^(docs/.*\.rst|src/ptscripts/.*\.py)$
7141
additional_dependencies:
72-
- black==23.1.0.
73-
# <---- Formatting -----------------------------------------------------------------------------
74-
75-
# ----- Security ------------------------------------------------------------------------------>
76-
- repo: https://github.com/PyCQA/bandit
77-
rev: "1.7.4"
78-
hooks:
79-
- id: bandit
80-
alias: bandit-salt
81-
name: Run bandit against the code base
82-
args: [--silent, -lll, --skip, B701]
83-
files: ^(?!tests/).*\.py$
84-
exclude: src/ptscripts/version.py
85-
- repo: https://github.com/PyCQA/bandit
86-
rev: "1.7.4"
87-
hooks:
88-
- id: bandit
89-
alias: bandit-tests
90-
name: Run bandit against the test suite
91-
args: [--silent, -lll, --skip, B701]
92-
files: ^tests/.*
93-
# <---- Security -------------------------------------------------------------------------------
94-
95-
# ----- Code Analysis ------------------------------------------------------------------------->
96-
- repo: https://github.com/pycqa/flake8
97-
rev: '6.0.0'
98-
hooks:
99-
- id: flake8
100-
exclude: ^(demo/.*|src/ptscripts/version\.py|\.pre-commit-hooks/.*\.py)$
101-
additional_dependencies:
102-
- flake8-mypy-fork
103-
- flake8-docstrings
104-
- flake8-typing-imports
42+
- black==23.1.0
10543

10644
- repo: https://github.com/pre-commit/mirrors-mypy
10745
rev: v1.3.0
@@ -114,4 +52,4 @@ repos:
11452
- types-attrs
11553
- types-setuptools
11654
- types-requests
117-
# <---- Code Analysis --------------------------------------------------------------------------
55+
# <---- Code Formatting and Analysis -----------------------------------------------------------

changelog/36.improvement.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Switch to [ruff](https://github.com/charliermarsh/ruff)

noxfile.py

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import os
2-
import shutil
31
import gzip
2+
import os
43
import pathlib
5-
import tempfile
4+
import shutil
65
import tarfile
6+
import tempfile
7+
78
import nox
89
from nox.command import CommandFailed
910

@@ -128,27 +129,25 @@ def recompress(self, targz):
128129
d_src.mkdir()
129130
d_tar = tempd.joinpath(targz.stem)
130131
d_targz = tempd.joinpath(targz.name)
131-
with tarfile.open(d_tar, "w|") as wfile:
132-
with tarfile.open(targz, "r:gz") as rfile:
133-
rfile.extractall(d_src)
134-
extracted_dir = next(pathlib.Path(d_src).iterdir())
135-
for name in sorted(extracted_dir.rglob("*")):
136-
wfile.add(
137-
str(name),
138-
filter=self.tar_reset,
139-
recursive=False,
140-
arcname=str(name.relative_to(d_src)),
141-
)
142-
143-
with open(d_tar, "rb") as rfh:
144-
with gzip.GzipFile(
145-
fileobj=open(d_targz, "wb"), mode="wb", filename="", mtime=self.mtime
146-
) as gz:
147-
while True:
148-
chunk = rfh.read(1024)
149-
if not chunk:
150-
break
151-
gz.write(chunk)
132+
with tarfile.open(d_tar, "w|") as wfile, tarfile.open(targz, "r:gz") as rfile:
133+
rfile.extractall(d_src)
134+
extracted_dir = next(pathlib.Path(d_src).iterdir())
135+
for name in sorted(extracted_dir.rglob("*")):
136+
wfile.add(
137+
str(name),
138+
filter=self.tar_reset,
139+
recursive=False,
140+
arcname=str(name.relative_to(d_src)),
141+
)
142+
143+
with open(d_tar, "rb") as rfh, gzip.GzipFile(
144+
fileobj=open(d_targz, "wb"), mode="wb", filename="", mtime=self.mtime
145+
) as gz:
146+
while True:
147+
chunk = rfh.read(1024)
148+
if not chunk:
149+
break
150+
gz.write(chunk)
152151
targz.unlink()
153152
shutil.move(str(d_targz), str(targz))
154153

pyproject.toml

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,129 @@ issue_format = "`#{issue} <https://github.com/s0undt3ch/python-tools-scripts/iss
4747
directory = "trivial"
4848
name = "Trivial/Internal Changes"
4949
showcontent = true
50+
51+
[tool.ruff]
52+
line-length = 120
53+
select = ["ALL"]
54+
show-fixes = true
55+
show-source = true
56+
target-version = "py39"
57+
respect-gitignore = true
58+
src = [
59+
"src",
60+
]
61+
extend-exclude = [
62+
".nox/**",
63+
]
64+
extend-include = [
65+
"setup.py",
66+
"noxfile.py",
67+
"src/**/*.pyi",
68+
]
69+
ignore = [
70+
# D* pydocstyle
71+
"D200", # Reformat to one line
72+
"D212", # Remove whitespace after opening quotes
73+
"COM", # flake8-commas - Black takes care of this
74+
"ERA", # eradicate
75+
"SIM108", # Use ternary operator `A = X if Y else Z` instead of `if`-`else`-block
76+
"FBT", # Boolean traps
77+
"ANN002", # Missing type annotation for `*args`
78+
"ANN003", # Missing type annotation for `**kwargs`
79+
"ANN102", # Missing type annotation for `cls` in classmethod
80+
]
81+
ignore-init-module-imports = true
82+
# Group violations by containing file.
83+
format = "grouped"
84+
85+
[tool.ruff.per-file-ignores]
86+
"src/**/*.py" = [
87+
"ANN101", # Missing type annotation for `self` in method
88+
"D100", # Missing docstring in public module
89+
"D104", # Missing docstring in public package
90+
"D107", # Missing docstring in `__init__`
91+
]
92+
"src/ptscripts/__init__.py" = [
93+
"E402", # Module level import not at top of file
94+
"F401", # * imported but unused; consider adding to `__all__` or using a redundant alias
95+
]
96+
"src/ptscripts/logs.py" = [
97+
"D101", # Missing docstring in public class
98+
"D102", # Missing docstring in public method
99+
"N802", # Function name should be lowercase
100+
"ANN002", # Missing type annotation for `*args`
101+
"ANN003", # Missing type annotation for `**kwargs`
102+
]
103+
"src/ptscripts/virtualenv.py" = [
104+
"PTH110", # `os.path.exists()` should be replaced by `Path.exists()`
105+
"PTH118", # `os.path.join()` should be replaced by `Path` with `/` operator
106+
"PTH119", # `os.path.basename()` should be replaced by `Path.name`
107+
"ANN002", # Missing type annotation for `*args`
108+
"ANN003", # Missing type annotation for `**kwargs`
109+
]
110+
"src/ptscripts/parser.py" = [
111+
"SLF001", # Private member accessed
112+
"A001", # Variable `*` is shadowing a Python builtin
113+
"A002", # Argument `*` is shadowing a Python builtin
114+
"A003", # Class attribute `*` is shadowing a Python builtin
115+
]
116+
"src/ptscripts/process.py" = [
117+
"SLF001", # Private member accessed
118+
]
119+
"setup.py" = [
120+
"D",
121+
"EXE001", # Shebang is present but file is not executable
122+
]
123+
"noxfile.py" = [
124+
"D",
125+
"ANN",
126+
"PTH",
127+
"SLF001",
128+
"C901",
129+
"PLR0912",
130+
"DTZ005",
131+
"FBT002",
132+
"PLR0915", # Too many statements
133+
]
134+
"tests/**/*.py" = [
135+
"ANN", # Ignore missing type annotations in tests
136+
"ARG001", # Unused function argument
137+
"D100", # Missing docstring in public module
138+
"D103", # Missing docstring in public function
139+
"D104", # Missing docstring in public package
140+
"DTZ003", # The use of `datetime.datetime.utcnow()` is not allowed, use `datetime.datetime.now(tz=)` instead
141+
"PLR2004", # Magic value used in comparison, consider replacing 3 with a constant variable
142+
"PT001", # use @pytest.fixture() over @pytest.fixture
143+
"PT023", # use @pytest.mark.<blah>() over @pytest.mark.<blah>
144+
"RET504", # Unnecessary variable assignment before `return` statement"
145+
"S101", # Ignore the use of 'assert ...' in tests
146+
"S603", # `subprocess` call: check for execution of untrusted input
147+
"SIM117", # Use a single `with` statement with multiple contexts instead of nested `with` statements
148+
"TCH002", # Move third-party import into a type-checking block
149+
"TCH003", # Move standard library import `pathlib` into a type-checking block
150+
]
151+
152+
[tool.ruff.pydocstyle]
153+
# Use Google-style docstrings.
154+
convention = "google"
155+
156+
[tool.ruff.isort]
157+
combine-as-imports = false
158+
force-single-line = true
159+
known-first-party = ["src"]
160+
forced-separate = ["tests"]
161+
162+
[tool.ruff.flake8-quotes]
163+
docstring-quotes = "double"
164+
165+
#[tool.ruff.pep8-naming]
166+
#ignore-names = [
167+
# "__virtual__",
168+
#]
169+
170+
[tool.ruff.mccabe]
171+
max-complexity = 20
172+
173+
[tool.ruff.pylint]
174+
max-args = 8
175+
max-branches = 25

src/ptscripts/__init__.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
from __future__ import annotations
22

3+
import os
34
import pathlib
5+
import sys
6+
from typing import TYPE_CHECKING
47

5-
CWD = pathlib.Path.cwd()
8+
CWD: pathlib.Path = pathlib.Path.cwd()
69

710
import ptscripts.logs
11+
from ptscripts.parser import Context
12+
from ptscripts.parser import DefaultToolsPythonRequirements
13+
from ptscripts.parser import RegisteredImports
814
from ptscripts.parser import command_group
9-
from ptscripts.parser import Context, RegisteredImports, DefaultVirtualenvConfig
10-
from ptscripts.virtualenv import VirtualEnvConfig
15+
16+
if TYPE_CHECKING:
17+
from ptscripts.parser import DefaultRequirementsConfig
18+
from ptscripts.virtualenv import VirtualEnvConfig
1119

1220
__all__ = ["command_group", "register_tools_module", "Context", "CWD"]
1321

@@ -19,11 +27,8 @@ def register_tools_module(import_module: str, venv_config: VirtualEnvConfig | No
1927
RegisteredImports.register_import(import_module, venv_config=venv_config)
2028

2129

22-
def set_default_venv_config(venv_config: VirtualEnvConfig) -> None:
30+
def set_default_requirements_config(reqs_config: DefaultRequirementsConfig) -> None:
2331
"""
24-
Define the default virtualenv configuration.
25-
26-
This virtualenv will be available to all commands, and it's ``site-packages``
27-
dir(s) will be added to the current python interpreter site.
32+
Define the default tools requirements configuration.
2833
"""
29-
DefaultVirtualenvConfig.set_default_venv_config(venv_config)
34+
DefaultToolsPythonRequirements.set_default_requirements_config(reqs_config)

src/ptscripts/__main__.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,37 @@
11
from __future__ import annotations
22

33
import logging
4+
import os
45
import sys
6+
from typing import NoReturn
57

8+
from ptscripts.parser import TOOLS_DEPS_PATH
69
from ptscripts.parser import Parser
710

11+
if str(TOOLS_DEPS_PATH) in sys.path and sys.path[0] != str(TOOLS_DEPS_PATH):
12+
sys.path.remove(str(TOOLS_DEPS_PATH))
13+
if TOOLS_DEPS_PATH not in sys.path:
14+
sys.path.insert(0, str(TOOLS_DEPS_PATH))
15+
816
log = logging.getLogger(__name__)
917

1018

11-
def main():
19+
def main() -> NoReturn: # type: ignore[misc]
1220
"""
1321
Main CLI entry-point for python tools scripts.
1422
"""
1523
parser = Parser()
1624
cwd = str(parser.repo_root)
17-
log.debug(f"Searching for tools in {cwd}")
25+
log.debug("Searching for tools in %s", cwd)
1826
if cwd in sys.path:
1927
sys.path.remove(cwd)
2028
sys.path.insert(0, cwd)
2129
try:
2230
import tools # noqa: F401
23-
except ImportError:
24-
# No tools/ directory in the current CWD
25-
pass
31+
except ImportError as exc:
32+
if os.environ.get("TOOLS_DEBUG_IMPORTS", "0") == "1":
33+
raise exc from None
34+
2635
parser.parse_args()
2736

2837

0 commit comments

Comments
 (0)