Skip to content

Commit 4d240d4

Browse files
committed
Migrate from black, flake8 and isort to ruff
Re-formatted and improved style to comply with additional rules.
1 parent 0c93b84 commit 4d240d4

File tree

249 files changed

+2449
-2474
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

249 files changed

+2449
-2474
lines changed

.bandit

Lines changed: 0 additions & 4 deletions
This file was deleted.

.flake8

Lines changed: 0 additions & 7 deletions
This file was deleted.

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ jobs:
2222
- name: Run code quality tests with tox
2323
run: tox
2424
env:
25-
TOXENV: black,flake8,isort,mypy,docs
25+
TOXENV: ruff,mypy,docs

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- name: Install dependencies
2222
run: |
2323
python -m pip install --upgrade pip
24-
pip install "tox>=4.4,<5" "tox-gh-actions>=3.1,<4"
24+
pip install "tox>=4.12,<5" "tox-gh-actions>=3.2,<4"
2525
2626
- name: Run unit tests with tox
2727
run: tox

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# GraphQL-core 3
22

3-
GraphQL-core 3 is a Python 3.6+ port of [GraphQL.js](https://github.com/graphql/graphql-js),
3+
GraphQL-core 3 is a Python 3.7+ port of [GraphQL.js](https://github.com/graphql/graphql-js),
44
the JavaScript reference implementation for [GraphQL](https://graphql.org/),
55
a query language for APIs created by Facebook.
66

@@ -15,7 +15,7 @@ replication of the complete test suite of GraphQL.js, making sure this port is
1515
reliable and compatible with GraphQL.js.
1616

1717
The current stable version 3.2.3 of GraphQL-core is up-to-date with GraphQL.js
18-
version 16.6.0 and supports Python version 3.6 and newer.
18+
version 16.6.0 and supports Python version 3.7 and newer.
1919

2020
You can also try out the latest alpha version 3.3.0a3 of GraphQL-core
2121
which is up-to-date with GraphQL.js version 17.0.0a2.
@@ -196,13 +196,14 @@ Design goals for the GraphQL-core 3 library were:
196196
(and is now using TypeScript)
197197
* to use [black](https://github.com/ambv/black) to achieve a consistent code style
198198
while saving time and mental energy for more important matters
199+
(we are now using [ruff](https://github.com/astral-sh/ruff) instead)
199200
* to replicate the complete Mocha-based test suite of GraphQL.js
200201
using [pytest](https://docs.pytest.org/)
201202
with [pytest-describe](https://pypi.org/project/pytest-describe/)
202203

203204
Some restrictions (mostly in line with the design goals):
204205

205-
* requires Python 3.6 or newer
206+
* requires Python 3.7 or newer
206207
* does not support some already deprecated methods and options of GraphQL.js
207208
* supports asynchronous operations only via async.io
208209
(does not support the additional executors in GraphQL-core)

poetry.lock

Lines changed: 365 additions & 786 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 142 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ packages = [
2828
{ include = "docs", format = "sdist" },
2929
{ include = ".bumpversion.cfg", format = "sdist" },
3030
{ include = ".editorconfig", format = "sdist" },
31-
{ include = ".flake8", format = "sdist" },
3231
{ include = ".readthedocs.yaml", format = "sdist" },
3332
{ include = "poetry.lock", format = "sdist" },
3433
{ include = "tox.ini", format = "sdist" },
@@ -56,28 +55,15 @@ pytest-cov = "^4.1"
5655
pytest-describe = "^2.1"
5756
pytest-timeout = "^2.1"
5857
tox = [
59-
{ version = ">=4.5,<5", python = ">=3.8" },
58+
{ version = ">=4.12,<5", python = ">=3.8" },
6059
{ version = ">=3.28,<4", python = "<3.8" }
6160
]
6261

6362
[tool.poetry.group.lint]
6463
optional = true
6564

6665
[tool.poetry.group.lint.dependencies]
67-
black = "23.3.0"
68-
flake8 = [
69-
{ version = ">=5,<7", python = ">=3.8.1" },
70-
{ version = ">=5,<6", python = "<3.8.1" }
71-
]
72-
flake8-bandit = "^4.1"
73-
flake8-bugbear = [
74-
{ version = "23.5.9", python = ">=3.8.1" },
75-
{ version = "23.3.12", python = "<3.8.1" },
76-
]
77-
isort = [
78-
{ version = "^5.12", python = ">=3.8" },
79-
{ version = "^5.11", python = "<3.8" }
80-
]
66+
ruff = ">=0.2,<0.3"
8167
mypy = "1.3.0"
8268
bump2version = ">=1.0,<2"
8369

@@ -91,11 +77,147 @@ sphinx = [
9177
]
9278
sphinx_rtd_theme = ">=1,<2"
9379

94-
[tool.bandit]
95-
exclude_dirs = ["tests"]
80+
[tool.ruff]
81+
line-length = 88
82+
target-version = "py37"
83+
84+
[tool.ruff.lint]
85+
select = [
86+
"A", # flake8-builtins
87+
"ANN", # flake8-annotations
88+
"ARG", # flake8-unused-arguments
89+
"B", # flake8-bugbear
90+
"BLE", # flake8-blind-except
91+
"C4", # flake8-comprehensions
92+
"C90", # McCabe cyclomatic complexity
93+
"COM", # flake8-commas
94+
"D", # pydocstyle
95+
"DTZ", # flake8-datetimez
96+
"E", # pycodestyle
97+
"EM", # flake8-errmsg
98+
"ERA", # eradicate
99+
"EXE", # flake8-executable
100+
"F", # Pyflakes
101+
"FBT", # flake8-boolean-trap
102+
"G", # flake8-logging-format
103+
"I", # isort
104+
"ICN", # flake8-import-conventions
105+
"INP", # flake8-no-pep420
106+
"INT", # flake8-gettext
107+
"ISC", # flake8-implicit-str-concat
108+
"N", # pep8-naming
109+
"PGH", # pygrep-hooks
110+
"PIE", # flake8-pie
111+
"PL", # Pylint
112+
"PT", # flake8-pytest-style
113+
"PTH", # flake8-use-pathlib
114+
"PYI", # flake8-pyi
115+
"Q", # flake8-quotes
116+
"RET", # flake8-return
117+
"RSE", # flake8-raise
118+
"RUF", # Ruff-specific rules
119+
"S", # flake8-bandit
120+
"SLF", # flake8-self
121+
"SIM", # flake8-simplify
122+
"T10", # flake8-debugger
123+
"T20", # flake8-print
124+
"TCH", # flake8-type-checking
125+
"TID", # flake8-tidy-imports
126+
"TRY", # tryceratops
127+
"UP", # pyupgrade
128+
"W", # pycodestyle
129+
"YTT", # flake8-2020
130+
]
131+
ignore = [
132+
"ANN101", "ANN102", # no type annotation for self and cls needed
133+
"ANN401", # allow explicit Any
134+
"COM812", # allow trailing commas for auto-formatting
135+
"D105", "D107", # no docstring needed for magic methods
136+
"D203", # no blank line before class docstring
137+
"D213", # multi-line docstrings should not start at second line
138+
"D400", "D415", # first line in docstring does not need to be a sentence
139+
"D401", # do not always require imperative mood in first line
140+
"FBT001", "FBT002", "FBT003", # allow boolean parameters
141+
"ISC001", # allow string literal concatenation for auto-formatting
142+
"PGH003", # type ignores do not need to be specific
143+
"PLR2004", # allow some "magic" values
144+
"PYI034", # do not check return value of new method
145+
"TID252", # allow relative imports
146+
"UP006", "UP007", # use old type annotations (for now)
147+
"TRY003", # allow specific messages outside the exception class
148+
]
149+
150+
[tool.ruff.lint.per-file-ignores]
151+
"*/__init__.py" = [
152+
"I001", # imports do not need to be sorted
153+
]
154+
"src/graphql/execution/*" = [
155+
"BLE001", # allow catching blind exception
156+
]
157+
"src/graphql/language/ast.py" = [
158+
"D101", # do not require docstrings
159+
]
160+
"src/graphql/language/parser.py" = [
161+
"RSE102", # raised exception may need to be called
162+
]
163+
"src/graphql/type/introspection.py" = [
164+
"ANN001", "ANN003", "ANN204", "ANN205", # allow missing type annotations
165+
"N803", # allow JavaScript style arguments
166+
]
167+
"src/graphql/utilities/get_introspection_query.py" = [
168+
"D101", # allow missing class docstrings
169+
"N815", # allow JavaScript style class attributes
170+
]
171+
"src/graphql/utilities/type_info.py" = [
172+
"D102", # allow missing method docstrings
173+
]
174+
"src/graphql/validation/rules/*" = [
175+
"D102", # allow missing method docstrings
176+
]
177+
"src/graphql/validation/validation_context.py" = [
178+
"D102", # allow missing method docstrings
179+
]
180+
"tests/*" = [
181+
"ANN001", "ANN002", "ANN003", # allow missing type annotations
182+
"ANN201", "ANN202", "ANN204", "ANN205", # allow missing type annotations
183+
"B011", # allow always failing assertions
184+
"B904", # allow raising exceptions without context
185+
"C901", # allow complex functions
186+
"D100", "D101", "D102", "D103", # allow missing docstrings
187+
"EM101", "EM102", # allow passing literal strings to exceptions
188+
"N802", "N803", "N806", "N815", "N816", # allow JavaScript style names
189+
"PLR0915", # allow many statements
190+
"PT015", # allow always failing assertions
191+
"RUF012", # allow mutable class attributes
192+
"S101", # allow assertions
193+
"S301", # allow pickling
194+
"TRY002", "TRY301", # less strict handling of exceptions
195+
]
196+
"tests/star_wars_schema.py" = [
197+
"A002", # allow shadowin builtins
198+
"ERA001", # allow commented-out code
199+
]
200+
"tests/test_docs.py" = [
201+
"S102", # allow use of exec
202+
]
203+
204+
205+
[tool.ruff.lint.flake8-quotes]
206+
inline-quotes = "double"
96207

97-
[tool.black]
98-
target-version = ["py37", "py38", "py39", "py310", "py311"]
208+
[tool.ruff.lint.mccabe]
209+
max-complexity = 50
210+
211+
[tool.ruff.lint.pylint]
212+
max-args = 15
213+
max-branches = 50
214+
max-returns = 25
215+
max-statements = 125
216+
217+
[tool.ruff.format]
218+
indent-style = "space"
219+
quote-style = "double"
220+
skip-magic-trailing-comma = false
99221

100222
[tool.coverage.run]
101223
branch = true
@@ -116,7 +238,6 @@ exclude_lines = [
116238
"except ImportError:",
117239
"# Python <",
118240
"raise NotImplementedError",
119-
'raise TypeError\(f?"Unexpected',
120241
"assert False,",
121242
'\s+next\($',
122243
"if MYPY:",
@@ -126,13 +247,6 @@ exclude_lines = [
126247
]
127248
ignore_errors = true
128249

129-
[tool.isort]
130-
src_paths = ["src", "tests"]
131-
skip_glob = ["src/**/__init__.py"]
132-
profile = "black"
133-
force_single_line = false
134-
lines_after_imports = 2
135-
136250
[tool.mypy]
137251
python_version = "3.11"
138252
check_untyped_defs = true

src/graphql/error/graphql_error.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
"""GraphQL Error"""
2+
13
from sys import exc_info
24
from typing import TYPE_CHECKING, Any, Collection, Dict, List, Optional, Union
35

4-
56
try:
67
from typing import TypedDict
78
except ImportError: # Python < 3.8
@@ -12,12 +13,12 @@
1213
from typing_extensions import TypeAlias
1314

1415
if TYPE_CHECKING:
15-
from ..language.ast import Node # noqa: F401
16-
from ..language.location import ( # noqa: F401
16+
from ..language.ast import Node
17+
from ..language.location import (
1718
FormattedSourceLocation,
1819
SourceLocation,
1920
)
20-
from ..language.source import Source # noqa: F401
21+
from ..language.source import Source
2122

2223
__all__ = ["GraphQLError", "GraphQLErrorExtensions", "GraphQLFormattedError"]
2324

@@ -127,6 +128,7 @@ def __init__(
127128
original_error: Optional[Exception] = None,
128129
extensions: Optional[GraphQLErrorExtensions] = None,
129130
) -> None:
131+
"""Initialize a GraphQLError."""
130132
super().__init__(message)
131133
self.message = message
132134

@@ -201,7 +203,7 @@ def __repr__(self) -> str:
201203
args.append(f"extensions={self.extensions!r}")
202204
return f"{self.__class__.__name__}({', '.join(args)})"
203205

204-
def __eq__(self, other: Any) -> bool:
206+
def __eq__(self, other: object) -> bool:
205207
return (
206208
isinstance(other, GraphQLError)
207209
and self.__class__ == other.__class__
@@ -220,7 +222,7 @@ def __eq__(self, other: Any) -> bool:
220222
)
221223
)
222224

223-
def __ne__(self, other: Any) -> bool:
225+
def __ne__(self, other: object) -> bool:
224226
return not self == other
225227

226228
@property

src/graphql/error/located_error.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
"""Located GraphQL Error"""
2+
3+
from contextlib import suppress
14
from typing import TYPE_CHECKING, Collection, Optional, Union
25

36
from ..pyutils import inspect
47
from .graphql_error import GraphQLError
58

6-
79
if TYPE_CHECKING:
8-
from ..language.ast import Node # noqa: F401
10+
from ..language.ast import Node
911

1012
__all__ = ["located_error"]
1113

@@ -29,23 +31,18 @@ def located_error(
2931
if isinstance(original_error, GraphQLError) and original_error.path is not None:
3032
return original_error
3133
try:
32-
# noinspection PyUnresolvedReferences
3334
message = str(original_error.message) # type: ignore
3435
except AttributeError:
3536
message = str(original_error)
3637
try:
37-
# noinspection PyUnresolvedReferences
3838
source = original_error.source # type: ignore
3939
except AttributeError:
4040
source = None
4141
try:
42-
# noinspection PyUnresolvedReferences
4342
positions = original_error.positions # type: ignore
4443
except AttributeError:
4544
positions = None
46-
try:
47-
# noinspection PyUnresolvedReferences
45+
46+
with suppress(AttributeError):
4847
nodes = original_error.nodes or nodes # type: ignore
49-
except AttributeError:
50-
pass
5148
return GraphQLError(message, nodes, source, positions, path, original_error)

src/graphql/error/syntax_error.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1+
"""GraphQL Syntax Error"""
2+
13
from __future__ import annotations # Python < 3.10
24

35
from typing import TYPE_CHECKING
46

57
from .graphql_error import GraphQLError
68

7-
89
if TYPE_CHECKING:
9-
from ..language.source import Source # noqa: F401
10+
from ..language.source import Source
1011

1112
__all__ = ["GraphQLSyntaxError"]
1213

1314

1415
class GraphQLSyntaxError(GraphQLError):
1516
"""A GraphQLError representing a syntax error."""
1617

17-
def __init__(self, source: "Source", position: int, description: str) -> None:
18+
def __init__(self, source: Source, position: int, description: str) -> None:
19+
"""Initialize the GraphQLSyntaxError"""
1820
super().__init__(
1921
f"Syntax Error: {description}", source=source, positions=[position]
2022
)

0 commit comments

Comments
 (0)