Use ruff instead of black+isort (#644)

* Use ruff

* Update .gitignore

* Format code

* Use Ruff on generated code

* Update pre-commit hook

* Wrong commit

* Remove wrong imports

* Update hook

* Format code

* Target Python 3.8

* Reformat

* Pin ruff version
This commit is contained in:
Adrien 2025-01-03 02:59:43 +01:00 committed by GitHub
parent 37fa3abbac
commit f41934a0e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 539 additions and 559 deletions

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ output
.asv
venv
.devcontainer
.ruff_cache

View File

@ -2,16 +2,13 @@ ci:
autofix_prs: false
repos:
- repo: https://github.com/pycqa/isort
rev: 5.11.5
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.4
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black
args: ["--target-version", "py310"]
- id: ruff-format
args: ["--diff", "src", "tests"]
- id: ruff
args: ["--select", "I", "src", "tests"]
- repo: https://github.com/PyCQA/doc8
rev: 0.10.1

941
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -13,11 +13,11 @@ packages = [
[tool.poetry.dependencies]
python = "^3.8"
black = { version = ">=23.1.0", optional = true }
# The Ruff version is pinned. To update it, also update it in .pre-commit-config.yaml
ruff = { version = "~0.7.4", optional = true }
grpclib = "^0.4.1"
jinja2 = { version = ">=3.0.3", optional = true }
python-dateutil = "^2.8"
isort = { version = "^5.11.5", optional = true }
typing-extensions = "^4.7.1"
betterproto-rust-codec = { version = "0.1.1", optional = true }
@ -47,9 +47,16 @@ tomlkit = ">=0.7.0"
protoc-gen-python_betterproto = "betterproto.plugin:main"
[tool.poetry.extras]
compiler = ["black", "isort", "jinja2"]
compiler = ["ruff", "jinja2"]
rust-codec = ["betterproto-rust-codec"]
[tool.ruff]
extend-exclude = ["tests/output_*"]
target-version = "py38"
[tool.ruff.lint.isort]
combine-as-imports = true
lines-after-imports = 2
# Dev workflow tasks
@ -65,13 +72,29 @@ help = "Run tests"
cmd = "mypy src --ignore-missing-imports"
help = "Check types with mypy"
[tool.poe.tasks]
_black = "black . --exclude tests/output_ --target-version py310"
_isort = "isort . --extend-skip-glob 'tests/output_*/**/*'"
[tool.poe.tasks.format]
sequence = ["_black", "_isort"]
help = "Apply black and isort formatting to source code"
sequence = ["_format", "_sort-imports"]
help = "Format the source code, and sort the imports"
[tool.poe.tasks.check]
sequence = ["_check-format", "_check-imports"]
help = "Check that the source code is formatted and the imports sorted"
[tool.poe.tasks._format]
cmd = "ruff format src tests"
help = "Format the source code without sorting the imports"
[tool.poe.tasks._sort-imports]
cmd = "ruff check --select I --fix src tests"
help = "Sort the imports"
[tool.poe.tasks._check-format]
cmd = "ruff format --diff src tests"
help = "Check that the source code is formatted"
[tool.poe.tasks._check-imports]
cmd = "ruff check --select I src tests"
help = "Check that the imports are sorted"
[tool.poe.tasks.docs]
cmd = "sphinx-build docs docs/build"
@ -106,23 +129,6 @@ help = "Regenerate the types in betterproto.lib.std.google"
shell = "poe generate && tox"
help = "Run tests with multiple pythons"
[tool.poe.tasks.check-style]
cmd = "black . --check --diff"
help = "Check if code style is correct"
[tool.isort]
py_version = 37
profile = "black"
force_single_line = false
combine_as_imports = true
lines_after_imports = 2
include_trailing_comma = true
force_grid_wrap = 2
src_paths = ["src", "tests"]
[tool.black]
target-version = ['py37']
[tool.doc8]
paths = ["docs"]
max_line_length = 88

View File

@ -66,8 +66,7 @@ if sys.version_info >= (3, 10):
from types import UnionType as _types_UnionType
else:
class _types_UnionType:
...
class _types_UnionType: ...
# Proto 3 data types

View File

@ -1204,9 +1204,9 @@ class EnumDescriptorProto(betterproto.Message):
name: str = betterproto.string_field(1)
value: List["EnumValueDescriptorProto"] = betterproto.message_field(2)
options: "EnumOptions" = betterproto.message_field(3)
reserved_range: List[
"EnumDescriptorProtoEnumReservedRange"
] = betterproto.message_field(4)
reserved_range: List["EnumDescriptorProtoEnumReservedRange"] = (
betterproto.message_field(4)
)
"""
Range of reserved numeric values. Reserved numeric values may not be used
by enum values in the same enum declaration. Reserved ranges may not
@ -1792,9 +1792,9 @@ class FeatureSetDefaults(betterproto.Message):
for the closest matching edition, followed by proto merges.
"""
defaults: List[
"FeatureSetDefaultsFeatureSetEditionDefault"
] = betterproto.message_field(1)
defaults: List["FeatureSetDefaultsFeatureSetEditionDefault"] = (
betterproto.message_field(1)
)
minimum_edition: "Edition" = betterproto.enum_field(4)
"""
The minimum supported edition (inclusive) when this was constructed.

View File

@ -53,9 +53,9 @@ class CodeGeneratorRequest(betterproto.Message):
parameter: str = betterproto.string_field(2)
"""The generator parameter passed on the command-line."""
proto_file: List[
"betterproto_lib_pydantic_google_protobuf.FileDescriptorProto"
] = betterproto.message_field(15)
proto_file: List["betterproto_lib_pydantic_google_protobuf.FileDescriptorProto"] = (
betterproto.message_field(15)
)
"""
FileDescriptorProtos for all files in files_to_generate and everything
they import. The files will appear in topological order, so each file
@ -195,9 +195,9 @@ class CodeGeneratorResponseFile(betterproto.Message):
content: str = betterproto.string_field(15)
"""The file contents."""
generated_code_info: (
"betterproto_lib_pydantic_google_protobuf.GeneratedCodeInfo"
) = betterproto.message_field(16)
generated_code_info: "betterproto_lib_pydantic_google_protobuf.GeneratedCodeInfo" = betterproto.message_field(
16
)
"""
Information describing the file content being inserted. If an insertion
point is used, this information will be appropriately offset and inserted

View File

@ -1064,9 +1064,9 @@ class EnumDescriptorProto(betterproto.Message):
name: str = betterproto.string_field(1)
value: List["EnumValueDescriptorProto"] = betterproto.message_field(2)
options: "EnumOptions" = betterproto.message_field(3)
reserved_range: List[
"EnumDescriptorProtoEnumReservedRange"
] = betterproto.message_field(4)
reserved_range: List["EnumDescriptorProtoEnumReservedRange"] = (
betterproto.message_field(4)
)
"""
Range of reserved numeric values. Reserved numeric values may not be used
by enum values in the same enum declaration. Reserved ranges may not
@ -1688,9 +1688,9 @@ class FeatureSetDefaults(betterproto.Message):
for the closest matching edition, followed by proto merges.
"""
defaults: List[
"FeatureSetDefaultsFeatureSetEditionDefault"
] = betterproto.message_field(1)
defaults: List["FeatureSetDefaultsFeatureSetEditionDefault"] = (
betterproto.message_field(1)
)
minimum_edition: "Edition" = betterproto.enum_field(4)
"""
The minimum supported edition (inclusive) when this was constructed.

View File

@ -46,9 +46,9 @@ class CodeGeneratorRequest(betterproto.Message):
parameter: str = betterproto.string_field(2)
"""The generator parameter passed on the command-line."""
proto_file: List[
"betterproto_lib_google_protobuf.FileDescriptorProto"
] = betterproto.message_field(15)
proto_file: List["betterproto_lib_google_protobuf.FileDescriptorProto"] = (
betterproto.message_field(15)
)
"""
FileDescriptorProtos for all files in files_to_generate and everything
they import. The files will appear in topological order, so each file

View File

@ -1,4 +1,5 @@
import os.path
import subprocess
import sys
from .module_validation import ModuleValidator
@ -6,8 +7,6 @@ from .module_validation import ModuleValidator
try:
# betterproto[compiler] specific dependencies
import black
import isort.api
import jinja2
except ImportError as err:
print(
@ -40,20 +39,17 @@ def outputfile_compiler(output_file: OutputTemplate) -> str:
code = body_template.render(output_file=output_file)
code = header_template.render(output_file=output_file) + code
code = isort.api.sort_code_string(
code=code,
show_diff=False,
py_version=37,
profile="black",
combine_as_imports=True,
lines_after_imports=2,
quiet=True,
force_grid_wrap=2,
known_third_party=["grpclib", "betterproto"],
# Sort imports, delete unused ones
code = subprocess.check_output(
["ruff", "check", "--select", "I,F401", "--fix", "--silent", "-"],
input=code,
encoding="utf-8",
)
code = black.format_str(
src_contents=code,
mode=black.Mode(),
# Format the code
code = subprocess.check_output(
["ruff", "format", "-"], input=code, encoding="utf-8"
)
# Validate the generated code.

View File

@ -621,9 +621,7 @@ iso_candidates = """2009-12-12T12:34
2010-02-18T16:00:00.23334444
2010-02-18T16:00:00,2283
2009-05-19 143922
2009-05-19 1439""".split(
"\n"
)
2009-05-19 1439""".split("\n")
def test_iso_datetime():

View File

@ -62,7 +62,7 @@ def test_load_varint_file():
stream.read(2) # Skip until first multi-byte
assert betterproto.load_varint(stream) == (
123456789,
b"\x95\x9A\xEF\x3A",
b"\x95\x9a\xef\x3a",
) # Multi-byte varint
@ -338,7 +338,7 @@ def run_java_single_varint(value: int, tmp_path) -> int:
def test_single_varint(compile_jar, tmp_path):
single_byte = (1, b"\x01")
multi_byte = (123456789, b"\x95\x9A\xEF\x3A")
multi_byte = (123456789, b"\x95\x9a\xef\x3a")
# Write a single-byte varint to a file and have Java read it back
returned = run_java_single_varint(single_byte[0], tmp_path)
@ -351,8 +351,8 @@ def test_single_varint(compile_jar, tmp_path):
def test_multiple_varints(compile_jar, tmp_path):
single_byte = (1, b"\x01")
multi_byte = (123456789, b"\x95\x9A\xEF\x3A")
over32 = (3000000000, b"\x80\xBC\xC1\x96\x0B")
multi_byte = (123456789, b"\x95\x9a\xef\x3a")
over32 = (3000000000, b"\x80\xbc\xc1\x96\x0b")
# Write two varints to the same file
with open(tmp_path / "py_multiple_varints.out", "wb") as stream: