-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable the rest of the ruff rulesets.
Bring the rest of the scaffolding up to date.
- Loading branch information
Showing
7 changed files
with
259 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,159 @@ | ||
from pathlib import Path | ||
from tempfile import TemporaryDirectory | ||
import os | ||
|
||
import nox | ||
|
||
ROOT = Path(__file__).parent | ||
TESTS = ROOT / "tests" | ||
PYPROJECT = ROOT / "pyproject.toml" | ||
DOCS = ROOT / "docs" | ||
|
||
REQUIREMENTS = dict( | ||
docs=DOCS / "requirements.txt", | ||
tests=TESTS / "requirements.txt", | ||
) | ||
REQUIREMENTS_IN = [ # this is actually ordered, as files depend on each other | ||
path.parent / f"{path.stem}.in" for path in REQUIREMENTS.values() | ||
] | ||
|
||
SUPPORTED = ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3.10"] | ||
LATEST = "3.12" | ||
|
||
nox.options.sessions = [] | ||
|
||
|
||
def session(default=True, **kwargs): | ||
def session(default=True, python=LATEST, **kwargs): # noqa: D103 | ||
def _session(fn): | ||
if default: | ||
nox.options.sessions.append(kwargs.get("name", fn.__name__)) | ||
return nox.session(**kwargs)(fn) | ||
return nox.session(python=python, **kwargs)(fn) | ||
|
||
return _session | ||
|
||
|
||
@session(python=["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3"]) | ||
@session(python=SUPPORTED) | ||
def tests(session): | ||
session.install(ROOT, "-r", TESTS / "requirements.txt") | ||
if session.posargs == ["coverage"]: | ||
""" | ||
Run the test suite with a corresponding Python version. | ||
""" | ||
session.install("-r", REQUIREMENTS["tests"]) | ||
|
||
if session.posargs and session.posargs[0] == "coverage": | ||
if len(session.posargs) > 1 and session.posargs[1] == "github": | ||
github = Path(os.environ["GITHUB_STEP_SUMMARY"]) | ||
else: | ||
github = None | ||
|
||
session.install("coverage[toml]") | ||
session.run("coverage", "run", "-m", "pytest") | ||
session.run("coverage", "report") | ||
session.run("coverage", "run", "-m", "pytest", TESTS) | ||
if github is None: | ||
session.run("coverage", "report") | ||
else: | ||
with github.open("a") as summary: | ||
summary.write("### Coverage\n\n") | ||
summary.flush() # without a flush, output seems out of order. | ||
session.run( | ||
"coverage", | ||
"report", | ||
"--format=markdown", | ||
stdout=summary, | ||
) | ||
else: | ||
session.run("pytest", *session.posargs, TESTS) | ||
|
||
|
||
@session() | ||
def audit(session): | ||
""" | ||
Audit dependencies for vulnerabilities. | ||
""" | ||
session.install("pip-audit", ROOT) | ||
session.run("python", "-m", "pip_audit") | ||
|
||
|
||
@session(tags=["build"]) | ||
def build(session): | ||
""" | ||
Build a distribution suitable for PyPI and check its validity. | ||
""" | ||
session.install("build", "twine") | ||
with TemporaryDirectory() as tmpdir: | ||
session.run("python", "-m", "build", ROOT, "--outdir", tmpdir) | ||
session.run("twine", "check", "--strict", tmpdir + "/*") | ||
|
||
|
||
@session(tags=["style"]) | ||
def style(session): | ||
""" | ||
Check Python code style. | ||
""" | ||
session.install("ruff") | ||
session.run("ruff", "check", ROOT) | ||
|
||
|
||
@session(tags=["docs"]) | ||
@nox.parametrize( | ||
"builder", | ||
[ | ||
nox.param(name, id=name) | ||
for name in [ | ||
"dirhtml", | ||
"doctest", | ||
"linkcheck", | ||
"man", | ||
"spelling", | ||
] | ||
], | ||
) | ||
def docs(session, builder): | ||
""" | ||
Build the documentation using a specific Sphinx builder. | ||
""" | ||
session.install("-r", REQUIREMENTS["docs"]) | ||
with TemporaryDirectory() as tmpdir_str: | ||
tmpdir = Path(tmpdir_str) | ||
argv = ["-n", "-T", "-W"] | ||
if builder != "spelling": | ||
argv += ["-q"] | ||
posargs = session.posargs or [tmpdir / builder] | ||
session.run( | ||
"python", | ||
"-m", | ||
"sphinx", | ||
"-b", | ||
builder, | ||
DOCS, | ||
*argv, | ||
*posargs, | ||
) | ||
|
||
|
||
@session(tags=["docs", "style"], name="docs(style)") | ||
def docs_style(session): | ||
""" | ||
Check the documentation style. | ||
""" | ||
session.install( | ||
"doc8", | ||
"pygments", | ||
"pygments-github-lexers", | ||
) | ||
session.run("python", "-m", "doc8", "--config", PYPROJECT, DOCS) | ||
|
||
|
||
@session(default=False) | ||
def requirements(session): | ||
""" | ||
Update the project's pinned requirements. Commit the result. | ||
""" | ||
session.install("pip-tools") | ||
for each in [TESTS / "requirements.in"]: | ||
for each in REQUIREMENTS_IN: | ||
session.run( | ||
"pip-compile", | ||
"--resolver", | ||
"backtracking", | ||
"--strip-extras", | ||
"-U", | ||
each.relative_to(ROOT), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,9 +5,9 @@ build-backend = "maturin" | |
[project] | ||
name = "rpds-py" | ||
description = "Python bindings to Rust's persistent data structures (rpds)" | ||
requires-python = ">=3.8" | ||
readme = "README.rst" | ||
license = {text = "MIT"} | ||
requires-python = ">=3.8" | ||
keywords = ["data structures", "rust", "persistent"] | ||
authors = [ | ||
{email = "[email protected]"}, | ||
|
@@ -31,6 +31,7 @@ classifiers = [ | |
dynamic = ["version"] | ||
|
||
[project.urls] | ||
Documentation = "https://rpds.readthedocs.io/" | ||
Homepage = "https://github.com/crate-py/rpds" | ||
Issues = "https://github.com/crate-py/rpds/issues/" | ||
Funding = "https://github.com/sponsors/Julian" | ||
|
@@ -40,12 +41,106 @@ Source = "https://github.com/crate-py/rpds" | |
[tool.black] | ||
line-length = 79 | ||
|
||
[tool.coverage.html] | ||
show_contexts = true | ||
skip_covered = false | ||
|
||
[tool.coverage.run] | ||
branch = true | ||
dynamic_context = "test_function" | ||
|
||
[tool.coverage.report] | ||
exclude_also = [ | ||
"if TYPE_CHECKING:", | ||
"\\s*\\.\\.\\.\\s*", | ||
] | ||
fail_under = 100 | ||
show_missing = true | ||
skip_covered = true | ||
|
||
[tool.doc8] | ||
ignore = [ | ||
"D000", # see PyCQA/doc8#125 | ||
"D001", # one sentence per line, so max length doesn't make sense | ||
] | ||
|
||
[tool.isort] | ||
combine_as_imports = true | ||
ensure_newline_before_comments = true | ||
from_first = true | ||
include_trailing_comma = true | ||
multi_line_output = 3 | ||
known_first_party = ["rpds"] | ||
use_parentheses = true | ||
|
||
[tool.maturin] | ||
features = ["pyo3/extension-module"] | ||
|
||
[tool.pyright] | ||
reportUnnecessaryTypeIgnoreComment = true | ||
strict = ["**/*"] | ||
exclude = [ | ||
"**/tests/__init__.py", | ||
"**/tests/test_*.py", | ||
] | ||
|
||
[tool.ruff] | ||
line-length = 79 | ||
select = ["ALL"] | ||
ignore = [ | ||
"A001", # It's fine to shadow builtins | ||
"A002", | ||
"A003", | ||
"ARG", # This is all wrong whenever an interface is involved | ||
"ANN", # Just let the type checker do this | ||
"B008", # It's totally OK to call functions for default arguments. | ||
"B904", # raise SomeException(...) is fine. | ||
"B905", # No need for explicit strict, this is simply zip's default behavior | ||
"C408", # Calling dict is fine when it saves quoting the keys | ||
"C901", # Not really something to focus on | ||
"D105", # It's fine to not have docstrings for magic methods. | ||
"D107", # __init__ especially doesn't need a docstring | ||
"D200", # This rule makes diffs uglier when expanding docstrings | ||
"D203", # No blank lines before docstrings. | ||
"D212", # Start docstrings on the second line. | ||
"D400", # This rule misses sassy docstrings ending with ! or ? | ||
"D401", # This rule is too flaky. | ||
"D406", # Section headers should end with a colon not a newline | ||
"D407", # Underlines aren't needed | ||
"D412", # Plz spaces after section headers | ||
"EM101", # These don't bother me, it's fine there's some duplication. | ||
"EM102", | ||
"FBT", # It's worth avoiding boolean args but I don't care to enforce it | ||
"FIX", # Yes thanks, if I could it wouldn't be there | ||
"I001", # We can't yet use ruff's isort | ||
"N", # These naming rules are silly | ||
"PLR0912", # These metrics are fine to be aware of but not to enforce | ||
"PLR0913", | ||
"PLR0915", | ||
"PLW2901", # Shadowing for loop variables is occasionally fine. | ||
"PT006", # pytest parametrize takes strings as well | ||
"PYI025", # wat, I'm not confused, thanks. | ||
"RET502", # Returning None implicitly is fine | ||
"RET503", | ||
"RET505", # These push you to use `if` instead of `elif`, but for no reason | ||
"RET506", | ||
"RSE102", # Ha, what, who even knew you could leave the parens off. But no. | ||
"SIM300", # Not sure what heuristic this uses, but it's easily incorrect | ||
"SLF001", # Private usage within this package itself is fine | ||
"TD", # These TODO style rules are also silly | ||
"UP007", # We support 3.8 + 3.9 | ||
] | ||
[tool.ruff.lint.flake8-pytest-style] | ||
mark-parentheses = false | ||
|
||
[tool.ruff.flake8-quotes] | ||
docstring-quotes = "double" | ||
|
||
[tool.ruff.lint.isort] | ||
combine-as-imports = true | ||
from-first = true | ||
|
||
[tool.ruff.per-file-ignores] | ||
"noxfile.py" = ["ANN", "D100", "S101", "T201"] | ||
"docs/*" = ["ANN", "D", "INP001"] | ||
"tests/*" = ["ANN", "B018", "D", "PLR", "RUF012", "S", "SIM", "TRY"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.