Browse Source

⬆ Bump ruff to 0.9.4 (#13299)

* ⬆ Bump ruff from 0.6.4 to 0.9.4

Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.4 to 0.9.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.4...0.9.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>

* update pre-commit accordingly and make formatting changes

* 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Alejandra <[email protected]>
Co-authored-by: svlandeg <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
pull/13463/head
dependabot[bot] 4 weeks ago
committed by GitHub
parent
commit
8c94e97c89
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      .pre-commit-config.yaml
  2. 42
      fastapi/dependencies/utils.py
  3. 12
      fastapi/openapi/utils.py
  4. 24
      fastapi/routing.py
  5. 2
      requirements-docs-tests.txt
  6. 12
      scripts/translate.py
  7. 6
      tests/test_enforce_once_required_parameter.py
  8. 4
      tests/test_generic_parameterless_depends.py
  9. 6
      tests/test_repeated_dependency_schema.py
  10. 48
      tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py
  11. 54
      tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py
  12. 54
      tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py
  13. 6
      tests/test_tutorial/test_sql_databases/test_tutorial002.py

2
.pre-commit-config.yaml

@ -14,7 +14,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.4
rev: v0.9.4
hooks:
- id: ruff
args:

42
fastapi/dependencies/utils.py

@ -133,9 +133,9 @@ def get_param_sub_dependant(
def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> Dependant:
assert callable(
depends.dependency
), "A parameter-less dependency must have a callable dependency"
assert callable(depends.dependency), (
"A parameter-less dependency must have a callable dependency"
)
return get_sub_dependant(depends=depends, dependency=depends.dependency, path=path)
@ -302,9 +302,9 @@ def get_dependant(
type_annotation=param_details.type_annotation,
dependant=dependant,
):
assert (
param_details.field is None
), f"Cannot specify multiple FastAPI annotations for {param_name!r}"
assert param_details.field is None, (
f"Cannot specify multiple FastAPI annotations for {param_name!r}"
)
continue
assert param_details.field is not None
if isinstance(param_details.field.field_info, params.Body):
@ -439,9 +439,9 @@ def analyze_param(
),
):
assert depends is None, f"Cannot specify `Depends` for type {type_annotation!r}"
assert (
field_info is None
), f"Cannot specify FastAPI annotation for type {type_annotation!r}"
assert field_info is None, (
f"Cannot specify FastAPI annotation for type {type_annotation!r}"
)
# Handle default assignations, neither field_info nor depends was not found in Annotated nor default value
elif field_info is None and depends is None:
default_value = value if value is not inspect.Signature.empty else RequiredParam
@ -494,9 +494,9 @@ def analyze_param(
field_info=field_info,
)
if is_path_param:
assert is_scalar_field(
field=field
), "Path params must be of one of the supported types"
assert is_scalar_field(field=field), (
"Path params must be of one of the supported types"
)
elif isinstance(field_info, params.Query):
assert (
is_scalar_field(field)
@ -521,9 +521,9 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None:
elif field_info_in == params.ParamTypes.header:
dependant.header_params.append(field)
else:
assert (
field_info_in == params.ParamTypes.cookie
), f"non-body parameters must be in path, query, header or cookie: {field.name}"
assert field_info_in == params.ParamTypes.cookie, (
f"non-body parameters must be in path, query, header or cookie: {field.name}"
)
dependant.cookie_params.append(field)
@ -782,9 +782,9 @@ def request_params_to_args(
if single_not_embedded_field:
field_info = first_field.field_info
assert isinstance(
field_info, params.Param
), "Params must be subclasses of Param"
assert isinstance(field_info, params.Param), (
"Params must be subclasses of Param"
)
loc: Tuple[str, ...] = (field_info.in_.value,)
v_, errors_ = _validate_value_with_model_field(
field=first_field, value=params_to_process, values=values, loc=loc
@ -794,9 +794,9 @@ def request_params_to_args(
for field in fields:
value = _get_multidict_value(field, received_params)
field_info = field.field_info
assert isinstance(
field_info, params.Param
), "Params must be subclasses of Param"
assert isinstance(field_info, params.Param), (
"Params must be subclasses of Param"
)
loc = (field_info.in_.value, field.alias)
v_, errors_ = _validate_value_with_model_field(
field=field, value=value, values=values, loc=loc

12
fastapi/openapi/utils.py

@ -364,9 +364,9 @@ def get_openapi_path(
openapi_response = operation_responses.setdefault(
status_code_key, {}
)
assert isinstance(
process_response, dict
), "An additional response must be a dict"
assert isinstance(process_response, dict), (
"An additional response must be a dict"
)
field = route.response_fields.get(additional_status_code)
additional_field_schema: Optional[Dict[str, Any]] = None
if field:
@ -434,9 +434,9 @@ def get_fields_from_routes(
route, routing.APIRoute
):
if route.body_field:
assert isinstance(
route.body_field, ModelField
), "A request body must be a Pydantic Field"
assert isinstance(route.body_field, ModelField), (
"A request body must be a Pydantic Field"
)
body_fields_from_routes.append(route.body_field)
if route.response_field:
responses_from_routes.append(route.response_field)

24
fastapi/routing.py

@ -504,9 +504,9 @@ class APIRoute(routing.Route):
status_code = int(status_code)
self.status_code = status_code
if self.response_model:
assert is_body_allowed_for_status_code(
status_code
), f"Status code {status_code} must not have a response body"
assert is_body_allowed_for_status_code(status_code), (
f"Status code {status_code} must not have a response body"
)
response_name = "Response_" + self.unique_id
self.response_field = create_model_field(
name=response_name,
@ -537,9 +537,9 @@ class APIRoute(routing.Route):
assert isinstance(response, dict), "An additional response must be a dict"
model = response.get("model")
if model:
assert is_body_allowed_for_status_code(
additional_status_code
), f"Status code {additional_status_code} must not have a response body"
assert is_body_allowed_for_status_code(additional_status_code), (
f"Status code {additional_status_code} must not have a response body"
)
response_name = f"Response_{additional_status_code}_{self.unique_id}"
response_field = create_model_field(
name=response_name, type_=model, mode="serialization"
@ -844,9 +844,9 @@ class APIRouter(routing.Router):
)
if prefix:
assert prefix.startswith("/"), "A path prefix must start with '/'"
assert not prefix.endswith(
"/"
), "A path prefix must not end with '/', as the routes will start with '/'"
assert not prefix.endswith("/"), (
"A path prefix must not end with '/', as the routes will start with '/'"
)
self.prefix = prefix
self.tags: List[Union[str, Enum]] = tags or []
self.dependencies = list(dependencies or [])
@ -1256,9 +1256,9 @@ class APIRouter(routing.Router):
"""
if prefix:
assert prefix.startswith("/"), "A path prefix must start with '/'"
assert not prefix.endswith(
"/"
), "A path prefix must not end with '/', as the routes will start with '/'"
assert not prefix.endswith("/"), (
"A path prefix must not end with '/', as the routes will start with '/'"
)
else:
for r in router.routes:
path = getattr(r, "path") # noqa: B009

2
requirements-docs-tests.txt

@ -1,4 +1,4 @@
# For mkdocstrings and tests
httpx >=0.23.0,<0.28.0
# For linting and generating docs versions
ruff ==0.6.4
ruff ==0.9.4

12
scripts/translate.py

@ -38,9 +38,9 @@ def get_langs() -> dict[str, str]:
def generate_lang_path(*, lang: str, path: Path) -> Path:
en_docs_path = Path("docs/en/docs")
assert str(path).startswith(
str(en_docs_path)
), f"Path must be inside {en_docs_path}"
assert str(path).startswith(str(en_docs_path)), (
f"Path must be inside {en_docs_path}"
)
lang_docs_path = Path(f"docs/{lang}/docs")
out_path = Path(str(path).replace(str(en_docs_path), str(lang_docs_path)))
return out_path
@ -56,9 +56,9 @@ def translate_page(*, lang: str, path: Path) -> None:
lang_prompt_content = lang_prompt_path.read_text()
en_docs_path = Path("docs/en/docs")
assert str(path).startswith(
str(en_docs_path)
), f"Path must be inside {en_docs_path}"
assert str(path).startswith(str(en_docs_path)), (
f"Path must be inside {en_docs_path}"
)
out_path = generate_lang_path(lang=lang, path=path)
out_path.parent.mkdir(parents=True, exist_ok=True)
original_content = path.read_text()

6
tests/test_enforce_once_required_parameter.py

@ -48,7 +48,7 @@ expected_schema = {
"type": "array",
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error " "Type", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
"required": ["loc", "msg", "type"],
"title": "ValidationError",
@ -73,7 +73,7 @@ expected_schema = {
"responses": {
"200": {
"content": {"application/json": {"schema": {}}},
"description": "Successful " "Response",
"description": "Successful Response",
},
"422": {
"content": {
@ -83,7 +83,7 @@ expected_schema = {
}
}
},
"description": "Validation " "Error",
"description": "Validation Error",
},
},
"summary": "Foo Handler",

4
tests/test_generic_parameterless_depends.py

@ -55,7 +55,7 @@ def test_openapi_schema():
"responses": {
"200": {
"content": {"application/json": {"schema": {}}},
"description": "Successful " "Response",
"description": "Successful Response",
}
},
"summary": "A",
@ -67,7 +67,7 @@ def test_openapi_schema():
"responses": {
"200": {
"content": {"application/json": {"schema": {}}},
"description": "Successful " "Response",
"description": "Successful Response",
}
},
"summary": "B",

6
tests/test_repeated_dependency_schema.py

@ -41,7 +41,7 @@ schema = {
"type": "array",
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error " "Type", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
"required": ["loc", "msg", "type"],
"title": "ValidationError",
@ -66,7 +66,7 @@ schema = {
"responses": {
"200": {
"content": {"application/json": {"schema": {}}},
"description": "Successful " "Response",
"description": "Successful Response",
},
"422": {
"content": {
@ -76,7 +76,7 @@ schema = {
}
}
},
"description": "Validation " "Error",
"description": "Validation Error",
},
},
"summary": "Get Deps",

48
tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py

@ -8,31 +8,31 @@ client = TestClient(app)
def test_swagger_ui():
response = client.get("/docs")
assert response.status_code == 200, response.text
assert (
'"syntaxHighlight": false' in response.text
), "syntaxHighlight should be included and converted to JSON"
assert (
'"dom_id": "#swagger-ui"' in response.text
), "default configs should be preserved"
assert '"syntaxHighlight": false' in response.text, (
"syntaxHighlight should be included and converted to JSON"
)
assert '"dom_id": "#swagger-ui"' in response.text, (
"default configs should be preserved"
)
assert "presets: [" in response.text, "default configs should be preserved"
assert (
"SwaggerUIBundle.presets.apis," in response.text
), "default configs should be preserved"
assert (
"SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text
), "default configs should be preserved"
assert (
'"layout": "BaseLayout",' in response.text
), "default configs should be preserved"
assert (
'"deepLinking": true,' in response.text
), "default configs should be preserved"
assert (
'"showExtensions": true,' in response.text
), "default configs should be preserved"
assert (
'"showCommonExtensions": true,' in response.text
), "default configs should be preserved"
assert "SwaggerUIBundle.presets.apis," in response.text, (
"default configs should be preserved"
)
assert "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text, (
"default configs should be preserved"
)
assert '"layout": "BaseLayout",' in response.text, (
"default configs should be preserved"
)
assert '"deepLinking": true,' in response.text, (
"default configs should be preserved"
)
assert '"showExtensions": true,' in response.text, (
"default configs should be preserved"
)
assert '"showCommonExtensions": true,' in response.text, (
"default configs should be preserved"
)
def test_get_users():

54
tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py

@ -8,34 +8,34 @@ client = TestClient(app)
def test_swagger_ui():
response = client.get("/docs")
assert response.status_code == 200, response.text
assert (
'"syntaxHighlight": false' not in response.text
), "not used parameters should not be included"
assert (
'"syntaxHighlight": {"theme": "obsidian"}' in response.text
), "parameters with middle dots should be included in a JSON compatible way"
assert (
'"dom_id": "#swagger-ui"' in response.text
), "default configs should be preserved"
assert '"syntaxHighlight": false' not in response.text, (
"not used parameters should not be included"
)
assert '"syntaxHighlight": {"theme": "obsidian"}' in response.text, (
"parameters with middle dots should be included in a JSON compatible way"
)
assert '"dom_id": "#swagger-ui"' in response.text, (
"default configs should be preserved"
)
assert "presets: [" in response.text, "default configs should be preserved"
assert (
"SwaggerUIBundle.presets.apis," in response.text
), "default configs should be preserved"
assert (
"SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text
), "default configs should be preserved"
assert (
'"layout": "BaseLayout",' in response.text
), "default configs should be preserved"
assert (
'"deepLinking": true,' in response.text
), "default configs should be preserved"
assert (
'"showExtensions": true,' in response.text
), "default configs should be preserved"
assert (
'"showCommonExtensions": true,' in response.text
), "default configs should be preserved"
assert "SwaggerUIBundle.presets.apis," in response.text, (
"default configs should be preserved"
)
assert "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text, (
"default configs should be preserved"
)
assert '"layout": "BaseLayout",' in response.text, (
"default configs should be preserved"
)
assert '"deepLinking": true,' in response.text, (
"default configs should be preserved"
)
assert '"showExtensions": true,' in response.text, (
"default configs should be preserved"
)
assert '"showCommonExtensions": true,' in response.text, (
"default configs should be preserved"
)
def test_get_users():

54
tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py

@ -8,34 +8,34 @@ client = TestClient(app)
def test_swagger_ui():
response = client.get("/docs")
assert response.status_code == 200, response.text
assert (
'"deepLinking": false,' in response.text
), "overridden configs should be preserved"
assert (
'"deepLinking": true' not in response.text
), "overridden configs should not include the old value"
assert (
'"syntaxHighlight": false' not in response.text
), "not used parameters should not be included"
assert (
'"dom_id": "#swagger-ui"' in response.text
), "default configs should be preserved"
assert '"deepLinking": false,' in response.text, (
"overridden configs should be preserved"
)
assert '"deepLinking": true' not in response.text, (
"overridden configs should not include the old value"
)
assert '"syntaxHighlight": false' not in response.text, (
"not used parameters should not be included"
)
assert '"dom_id": "#swagger-ui"' in response.text, (
"default configs should be preserved"
)
assert "presets: [" in response.text, "default configs should be preserved"
assert (
"SwaggerUIBundle.presets.apis," in response.text
), "default configs should be preserved"
assert (
"SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text
), "default configs should be preserved"
assert (
'"layout": "BaseLayout",' in response.text
), "default configs should be preserved"
assert (
'"showExtensions": true,' in response.text
), "default configs should be preserved"
assert (
'"showCommonExtensions": true,' in response.text
), "default configs should be preserved"
assert "SwaggerUIBundle.presets.apis," in response.text, (
"default configs should be preserved"
)
assert "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text, (
"default configs should be preserved"
)
assert '"layout": "BaseLayout",' in response.text, (
"default configs should be preserved"
)
assert '"showExtensions": true,' in response.text, (
"default configs should be preserved"
)
assert '"showCommonExtensions": true,' in response.text, (
"default configs should be preserved"
)
def test_get_users():

6
tests/test_tutorial/test_sql_databases/test_tutorial002.py

@ -71,9 +71,9 @@ def test_crud_app(client: TestClient):
assert response.json() == snapshot(
{"age": 30, "id": IsInt(), "name": "Dead Pond"}
)
assert (
response.json()["id"] != 9000
), "The ID should be generated by the database"
assert response.json()["id"] != 9000, (
"The ID should be generated by the database"
)
# Read a hero
hero_id = response.json()["id"]

Loading…
Cancel
Save