Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Use Ruff for linting #5630

Merged
merged 5 commits into from Nov 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 0 additions & 5 deletions .flake8

This file was deleted.

15 changes: 4 additions & 11 deletions .pre-commit-config.yaml
Expand Up @@ -18,19 +18,12 @@ repos:
args:
- --py3-plus
- --keep-runtime-typing
- repo: https://github.com/PyCQA/autoflake
rev: v1.7.7
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.114
hooks:
- id: autoflake
- id: ruff
args:
- --recursive
- --in-place
- --remove-all-unused-imports
- --remove-unused-variables
- --expand-star-imports
- --exclude
- __init__.py
- --remove-duplicate-keys
- --fix
- repo: https://github.com/pycqa/isort
rev: 5.10.1
hooks:
Expand Down
2 changes: 1 addition & 1 deletion docs_src/security/tutorial005.py
Expand Up @@ -107,7 +107,7 @@ async def get_current_user(
if security_scopes.scopes:
authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
else:
authenticate_value = f"Bearer"
authenticate_value = "Bearer"
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
Expand Down
2 changes: 1 addition & 1 deletion docs_src/security/tutorial005_py310.py
Expand Up @@ -106,7 +106,7 @@ async def get_current_user(
if security_scopes.scopes:
authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
else:
authenticate_value = f"Bearer"
authenticate_value = "Bearer"
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
Expand Down
2 changes: 1 addition & 1 deletion docs_src/security/tutorial005_py39.py
Expand Up @@ -107,7 +107,7 @@ async def get_current_user(
if security_scopes.scopes:
authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
else:
authenticate_value = f"Bearer"
authenticate_value = "Bearer"
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
Expand Down
12 changes: 6 additions & 6 deletions fastapi/dependencies/utils.py
Expand Up @@ -426,21 +426,21 @@ def is_coroutine_callable(call: Callable[..., Any]) -> bool:
return inspect.iscoroutinefunction(call)
if inspect.isclass(call):
return False
dunder_call = getattr(call, "__call__", None)
dunder_call = getattr(call, "__call__", None) # noqa: B004
return inspect.iscoroutinefunction(dunder_call)


def is_async_gen_callable(call: Callable[..., Any]) -> bool:
if inspect.isasyncgenfunction(call):
return True
dunder_call = getattr(call, "__call__", None)
dunder_call = getattr(call, "__call__", None) # noqa: B004
return inspect.isasyncgenfunction(dunder_call)


def is_gen_callable(call: Callable[..., Any]) -> bool:
if inspect.isgeneratorfunction(call):
return True
dunder_call = getattr(call, "__call__", None)
dunder_call = getattr(call, "__call__", None) # noqa: B004
return inspect.isgeneratorfunction(dunder_call)


Expand Down Expand Up @@ -724,14 +724,14 @@ def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]:
# in case a sub-dependency is evaluated with a single unique body field
# That is combined (embedded) with other body fields
for param in flat_dependant.body_params:
setattr(param.field_info, "embed", True)
setattr(param.field_info, "embed", True) # noqa: B010
model_name = "Body_" + name
BodyModel: Type[BaseModel] = create_model(model_name)
for f in flat_dependant.body_params:
BodyModel.__fields__[f.name] = f
required = any(True for f in flat_dependant.body_params if f.required)

BodyFieldInfo_kwargs: Dict[str, Any] = dict(default=None)
BodyFieldInfo_kwargs: Dict[str, Any] = {"default": None}
if any(isinstance(f.field_info, params.File) for f in flat_dependant.body_params):
BodyFieldInfo: Type[params.Body] = params.File
elif any(isinstance(f.field_info, params.Form) for f in flat_dependant.body_params):
Expand All @@ -740,7 +740,7 @@ def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]:
BodyFieldInfo = params.Body

body_param_media_types = [
getattr(f.field_info, "media_type")
f.field_info.media_type
for f in flat_dependant.body_params
if isinstance(f.field_info, params.Body)
]
Expand Down
2 changes: 1 addition & 1 deletion fastapi/routing.py
Expand Up @@ -701,7 +701,7 @@ def include_router(
), "A path prefix must not end with '/', as the routes will start with '/'"
else:
for r in router.routes:
path = getattr(r, "path")
path = getattr(r, "path") # noqa: B009
name = getattr(r, "name", "unknown")
if path is not None and not path:
raise Exception(
Expand Down
32 changes: 29 additions & 3 deletions pyproject.toml
Expand Up @@ -53,7 +53,7 @@ test = [
"pytest >=7.1.3,<8.0.0",
"coverage[toml] >= 6.5.0,<7.0",
"mypy ==0.982",
"flake8 >=3.8.3,<6.0.0",
"ruff ==0.0.114",
"black == 22.8.0",
"isort >=5.0.6,<6.0.0",
"httpx >=0.23.0,<0.24.0",
Expand Down Expand Up @@ -87,8 +87,7 @@ doc = [
"pyyaml >=5.3.1,<7.0.0",
]
dev = [
"autoflake >=1.4.0,<2.0.0",
"flake8 >=3.8.3,<6.0.0",
"ruff ==0.0.114",
"uvicorn[standard] >=0.12.0,<0.19.0",
"pre-commit >=2.17.0,<3.0.0",
]
Expand Down Expand Up @@ -156,3 +155,30 @@ source = [
"fastapi"
]
context = '${CONTEXT}'

[tool.ruff]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
# "I", # isort
"C", # flake8-comprehensions
"B", # flake8-bugbear
]
ignore = [
"E501", # line too long, handled by black
"B008", # do not perform function calls in argument defaults
]

[tool.ruff.per-file-ignores]
"__init__.py" = ["F401"]
"docs_src/dependencies/tutorial007.py" = ["F821"]
"docs_src/dependencies/tutorial008.py" = ["F821"]
"docs_src/dependencies/tutorial009.py" = ["F821"]
"docs_src/dependencies/tutorial010.py" = ["F821"]
"docs_src/custom_response/tutorial007.py" = ["B007"]
"docs_src/dataclasses/tutorial003.py" = ["I001"]


[tool.ruff.isort]
known-third-party = ["fastapi", "pydantic", "starlette"]
4 changes: 2 additions & 2 deletions scripts/docs.py
Expand Up @@ -332,7 +332,7 @@ def serve():
os.chdir("site")
server_address = ("", 8008)
server = HTTPServer(server_address, SimpleHTTPRequestHandler)
typer.echo(f"Serving at: http://127.0.0.1:8008")
typer.echo("Serving at: http://127.0.0.1:8008")
server.serve_forever()


Expand Down Expand Up @@ -420,7 +420,7 @@ def get_file_to_nav_map(nav: list) -> Dict[str, Tuple[str, ...]]:
file_to_nav = {}
for item in nav:
if type(item) is str:
file_to_nav[item] = tuple()
file_to_nav[item] = ()
elif type(item) is dict:
item_key = list(item.keys())[0]
sub_nav = item[item_key]
Expand Down
2 changes: 1 addition & 1 deletion scripts/format.sh
@@ -1,6 +1,6 @@
#!/bin/sh -e
set -x

autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place docs_src fastapi tests scripts --exclude=__init__.py
ruff fastapi tests docs_src scripts --fix
black fastapi tests docs_src scripts
isort fastapi tests docs_src scripts
2 changes: 1 addition & 1 deletion scripts/lint.sh
Expand Up @@ -4,6 +4,6 @@ set -e
set -x

mypy fastapi
flake8 fastapi tests
ruff fastapi tests docs_src scripts
black fastapi tests --check
isort fastapi tests docs_src scripts --check-only
6 changes: 3 additions & 3 deletions tests/test_custom_route_class.py
Expand Up @@ -110,6 +110,6 @@ def test_route_classes():
for r in app.router.routes:
assert isinstance(r, Route)
routes[r.path] = r
assert getattr(routes["/a/"], "x_type") == "A"
assert getattr(routes["/a/b/"], "x_type") == "B"
assert getattr(routes["/a/b/c/"], "x_type") == "C"
assert getattr(routes["/a/"], "x_type") == "A" # noqa: B009
assert getattr(routes["/a/b/"], "x_type") == "B" # noqa: B009
assert getattr(routes["/a/b/c/"], "x_type") == "C" # noqa: B009
2 changes: 1 addition & 1 deletion tests/test_ws_router.py
Expand Up @@ -111,7 +111,7 @@ def test_router_ws_depends():

def test_router_ws_depends_with_override():
client = TestClient(app)
app.dependency_overrides[ws_dependency] = lambda: "Override"
app.dependency_overrides[ws_dependency] = lambda: "Override" # noqa: E731
with client.websocket_connect("/router-ws-depends/") as websocket:
assert websocket.receive_text() == "Override"

Expand Down