Skip to content

Commit

Permalink
Add some ruff autofixes to CI (#10458)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexWaygood authored Jul 20, 2023
1 parent a04cb3b commit 79e092e
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ repos:
hooks:
- id: isort
name: isort (python)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.278 # must match requirements-tests.txt
hooks:
- id: ruff
args: [--exit-non-zero-on-fix]
- repo: https://github.com/pycqa/flake8
rev: 6.0.0 # must match requirements-tests.txt
hooks:
Expand Down
7 changes: 4 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ it takes a bit longer. For more details, read below.
Typeshed runs continuous integration (CI) on all pull requests. This means that
if you file a pull request (PR), our full test suite -- including our linter,
`flake8` -- is run on your PR. It also means that bots will automatically apply
changes to your PR (using `pycln`, `black` and `isort`) to fix any formatting issues.
changes to your PR (using `pycln`, `black`, `isort` and `ruff`) to fix any formatting issues.
This frees you up to ignore all local setup on your side, focus on the
code and rely on the CI to fix everything, or point you to the places that
need fixing.
Expand Down Expand Up @@ -85,19 +85,20 @@ terminal to install all non-pytype requirements:
## Code formatting

The code is formatted using `black` and `isort`. Unused imports are also
auto-removed using `pycln`.
auto-removed using `pycln`, and various other autofixes are performed by `ruff`.

The repository is equipped with a [`pre-commit.ci`](https://pre-commit.ci/)
configuration file. This means that you don't *need* to do anything yourself to
run the code formatters. When you push a commit, a bot will run those for you
right away and add a commit to your PR.

That being said, if you *want* to run the checks locally when you commit,
you're free to do so. Either run `pycln`, `black` and `isort` manually...
you're free to do so. Either run `pycln`, `isort`, `black` and `ruff` manually...

```bash
$ pycln --config=pyproject.toml .
$ isort .
$ ruff .
$ black .
```

Expand Down
38 changes: 38 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,44 @@ extra_standard_library = [
]
known_first_party = ["utils", "parse_metadata"]

[tool.ruff]
line-length = 130
target-version = "py37"
fix = true
exclude = [
# We're only interested in autofixes for our stubs
"*.py",
# Ignore generated protobuf stubs
"*_pb2.pyi",
# virtual environment, cache directories, etc.:
"env",
".env",
".venv",
".git",
".mypy_cache",
".pytype",
]

# Only enable rules that have safe autofixes;
# only enable rules that are relevant to stubs
select = [
"UP004", # Remove explicit `object` inheritance
"UP006", # PEP-585 autofixes
"UP007", # PEP-604 autofixes
"UP013", # Class-based syntax for TypedDicts
"UP014", # Class-based syntax for NamedTuples
"UP019", # Use str over typing.Text
"UP035", # import from typing, not typing_extensions, wherever possible
"UP039", # don't use parens after a class definition with no bases
"PYI009", # use `...`, not `pass`, in empty class bodies
"PYI010", # function bodies must be empty
"PYI012", # class bodies must not contain `pass`
"PYI013", # non-empty class bodies must not contain `...`
"PYI020", # quoted annotations are always unnecessary in stubs
"PYI025", # always alias `collections.abc.Set` as `AbstractSet` when importing it
"PYI032", # use `object`, not `Any`, as the second parameter to `__eq__`
]

[tool.pycln]
all = true
disable_all_dunder_policy = true
Expand Down
1 change: 1 addition & 0 deletions requirements-tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mypy==1.4.1
pre-commit-hooks==4.4.0 # must match .pre-commit-config.yaml
pycln==2.1.5 # must match .pre-commit-config.yaml
pytype==2023.6.16; platform_system != "Windows" and python_version < "3.11"
ruff==0.0.278 # must match .pre-commit-config.yaml

# Libraries used by our various scripts.
aiohttp==3.8.4; python_version < "3.12" # aiohttp can't be installed on 3.12 yet
Expand Down
8 changes: 7 additions & 1 deletion scripts/create_baseline_stubs.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ def run_isort(stub_dir: str) -> None:
subprocess.run([sys.executable, "-m", "isort", stub_dir])


def run_ruff(stub_dir: str) -> None:
print(f"Running ruff: ruff {stub_dir}")
subprocess.run([sys.executable, "-m", "ruff", stub_dir])


def create_metadata(stub_dir: str, version: str) -> None:
"""Create a METADATA.toml file."""
match = re.match(r"[0-9]+.[0-9]+", version)
Expand Down Expand Up @@ -110,7 +115,7 @@ def add_pyright_exclusion(stub_dir: str) -> None:
def main() -> None:
parser = argparse.ArgumentParser(
description="""Generate baseline stubs automatically for an installed pip package
using stubgen. Also run black and isort. If the name of
using stubgen. Also run black, isort and ruff. If the name of
the project is different from the runtime Python package name, you may
need to use --package (example: --package yaml PyYAML)."""
)
Expand Down Expand Up @@ -159,6 +164,7 @@ def main() -> None:
run_stubgen(package, stub_dir)
run_stubdefaulter(stub_dir)

run_ruff(stub_dir)
run_isort(stub_dir)
run_black(stub_dir)

Expand Down
2 changes: 2 additions & 0 deletions scripts/runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ def main() -> None:
# Run formatters first. Order matters.
print("\nRunning pycln...")
subprocess.run([sys.executable, "-m", "pycln", path, "--config=pyproject.toml"])
print("\nRunning ruff...")
subprocess.run([sys.executable, "-m", "ruff", path])
print("\nRunning isort...")
subprocess.run([sys.executable, "-m", "isort", path])
print("\nRunning Black...")
Expand Down
2 changes: 1 addition & 1 deletion stdlib/typing_extensions.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ __all__ = [

_T = typing.TypeVar("_T")
_F = typing.TypeVar("_F", bound=Callable[..., Any])
_TC = typing.TypeVar("_TC", bound=Type[object])
_TC = typing.TypeVar("_TC", bound=type[object])

# unfortunately we have to duplicate this class definition from typing.pyi or we break pytype
class _SpecialForm:
Expand Down
5 changes: 4 additions & 1 deletion tests/check_consistent.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

# These type checkers and linters must have exact versions in the requirements file to ensure
# consistent CI runs.
linters = {"black", "flake8", "flake8-bugbear", "flake8-noqa", "flake8-pyi", "isort", "mypy", "pycln", "pytype"}
linters = {"black", "flake8", "flake8-bugbear", "flake8-noqa", "flake8-pyi", "isort", "ruff", "mypy", "pycln", "pytype"}


def assert_consistent_filetypes(
Expand Down Expand Up @@ -191,6 +191,9 @@ def check_precommit_requirements() -> None:
precommit_requirements = get_precommit_requirements()
no_txt_entry_msg = "All pre-commit requirements must also be listed in `requirements-tests.txt` (missing {requirement!r})"
for requirement, specifier in precommit_requirements.items():
# annoying: the ruff repo for pre-commit is different to the name in requirements-tests.txt
if requirement == "ruff-pre-commit":
requirement = "ruff"
assert requirement in requirements_txt_requirements, no_txt_entry_msg.format(requirement=requirement)
specifier_mismatch = (
f'Specifier "{specifier}" for {requirement!r} in `.pre-commit-config.yaml` '
Expand Down

0 comments on commit 79e092e

Please sign in to comment.