Browse Source

♻️ Add custom FastAPIDeprecationWarning

pull/14605/head
Sebastián Ramírez 7 months ago
parent
commit
a1e5102c55
  1. 4
      fastapi/dependencies/utils.py
  2. 7
      fastapi/exceptions.py
  3. 5
      fastapi/openapi/utils.py
  4. 9
      fastapi/params.py
  5. 5
      fastapi/routing.py
  6. 9
      fastapi/temp_pydantic_v1_params.py
  7. 5
      fastapi/utils.py
  8. 3
      tests/benchmarks/test_general_performance.py

4
fastapi/dependencies/utils.py

@ -51,7 +51,7 @@ from fastapi.concurrency import (
contextmanager_in_threadpool, contextmanager_in_threadpool,
) )
from fastapi.dependencies.models import Dependant from fastapi.dependencies.models import Dependant
from fastapi.exceptions import DependencyScopeError from fastapi.exceptions import DependencyScopeError, FastAPIDeprecationWarning
from fastapi.logger import logger from fastapi.logger import logger
from fastapi.security.oauth2 import SecurityScopes from fastapi.security.oauth2 import SecurityScopes
from fastapi.types import DependencyCacheKey from fastapi.types import DependencyCacheKey
@ -327,7 +327,7 @@ def get_dependant(
warnings.warn( warnings.warn(
"pydantic.v1 is deprecated and will soon stop being supported by FastAPI." "pydantic.v1 is deprecated and will soon stop being supported by FastAPI."
f" Please update the param {param_name}: {param_details.type_annotation!r}.", f" Please update the param {param_name}: {param_details.type_annotation!r}.",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=5, stacklevel=5,
) )
if isinstance( if isinstance(

7
fastapi/exceptions.py

@ -231,3 +231,10 @@ class ResponseValidationError(ValidationException):
) -> None: ) -> None:
super().__init__(errors, endpoint_ctx=endpoint_ctx) super().__init__(errors, endpoint_ctx=endpoint_ctx)
self.body = body self.body = body
class FastAPIDeprecationWarning(UserWarning):
"""
A custom deprecation warning as DeprecationWarning is ignored
Ref: https://sethmlarson.dev/deprecations-via-warnings-dont-work-for-python-libraries
"""

5
fastapi/openapi/utils.py

@ -23,6 +23,7 @@ from fastapi.dependencies.utils import (
get_validation_alias, get_validation_alias,
) )
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX
from fastapi.openapi.models import OpenAPI from fastapi.openapi.models import OpenAPI
from fastapi.params import Body, ParamTypes from fastapi.params import Body, ParamTypes
@ -215,9 +216,9 @@ def generate_operation_id(
*, route: routing.APIRoute, method: str *, route: routing.APIRoute, method: str
) -> str: # pragma: nocover ) -> str: # pragma: nocover
warnings.warn( warnings.warn(
"fastapi.openapi.utils.generate_operation_id() was deprecated, " message="fastapi.openapi.utils.generate_operation_id() was deprecated, "
"it is not used internally, and will be removed soon", "it is not used internally, and will be removed soon",
DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=2, stacklevel=2,
) )
if route.operation_id: if route.operation_id:

9
fastapi/params.py

@ -4,6 +4,7 @@ from dataclasses import dataclass
from enum import Enum from enum import Enum
from typing import Annotated, Any, Callable, Optional, Union from typing import Annotated, Any, Callable, Optional, Union
from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.openapi.models import Example from fastapi.openapi.models import Example
from pydantic.fields import FieldInfo from pydantic.fields import FieldInfo
from typing_extensions import Literal, deprecated from typing_extensions import Literal, deprecated
@ -75,7 +76,7 @@ class Param(FieldInfo): # type: ignore[misc]
if example is not _Unset: if example is not _Unset:
warnings.warn( warnings.warn(
"`example` has been deprecated, please use `examples` instead", "`example` has been deprecated, please use `examples` instead",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
self.example = example self.example = example
@ -105,7 +106,7 @@ class Param(FieldInfo): # type: ignore[misc]
if regex is not None: if regex is not None:
warnings.warn( warnings.warn(
"`regex` has been deprecated, please use `pattern` instead", "`regex` has been deprecated, please use `pattern` instead",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
current_json_schema_extra = json_schema_extra or extra current_json_schema_extra = json_schema_extra or extra
@ -530,7 +531,7 @@ class Body(FieldInfo): # type: ignore[misc]
if example is not _Unset: if example is not _Unset:
warnings.warn( warnings.warn(
"`example` has been deprecated, please use `examples` instead", "`example` has been deprecated, please use `examples` instead",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
self.example = example self.example = example
@ -560,7 +561,7 @@ class Body(FieldInfo): # type: ignore[misc]
if regex is not None: if regex is not None:
warnings.warn( warnings.warn(
"`regex` has been deprecated, please use `pattern` instead", "`regex` has been deprecated, please use `pattern` instead",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
current_json_schema_extra = json_schema_extra or extra current_json_schema_extra = json_schema_extra or extra

5
fastapi/routing.py

@ -47,6 +47,7 @@ from fastapi.dependencies.utils import (
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import ( from fastapi.exceptions import (
EndpointContext, EndpointContext,
FastAPIDeprecationWarning,
FastAPIError, FastAPIError,
RequestValidationError, RequestValidationError,
ResponseValidationError, ResponseValidationError,
@ -640,7 +641,7 @@ class APIRoute(routing.Route):
warnings.warn( warnings.warn(
"pydantic.v1 is deprecated and will soon stop being supported by FastAPI." "pydantic.v1 is deprecated and will soon stop being supported by FastAPI."
f" Please update the response model {self.response_model!r}.", f" Please update the response model {self.response_model!r}.",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
self.response_field = create_model_field( self.response_field = create_model_field(
@ -680,7 +681,7 @@ class APIRoute(routing.Route):
warnings.warn( warnings.warn(
"pydantic.v1 is deprecated and will soon stop being supported by FastAPI." "pydantic.v1 is deprecated and will soon stop being supported by FastAPI."
f" In responses={{}}, please update {model}.", f" In responses={{}}, please update {model}.",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
response_field = create_model_field( response_field = create_model_field(

9
fastapi/temp_pydantic_v1_params.py

@ -1,6 +1,7 @@
import warnings import warnings
from typing import Annotated, Any, Callable, Optional, Union from typing import Annotated, Any, Callable, Optional, Union
from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.openapi.models import Example from fastapi.openapi.models import Example
from fastapi.params import ParamTypes from fastapi.params import ParamTypes
from typing_extensions import deprecated from typing_extensions import deprecated
@ -63,7 +64,7 @@ class Param(FieldInfo):
if example is not _Unset: if example is not _Unset:
warnings.warn( warnings.warn(
"`example` has been deprecated, please use `examples` instead", "`example` has been deprecated, please use `examples` instead",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
self.example = example self.example = example
@ -93,7 +94,7 @@ class Param(FieldInfo):
if regex is not None: if regex is not None:
warnings.warn( warnings.warn(
"`regex` has been deprecated, please use `pattern` instead", "`regex` has been deprecated, please use `pattern` instead",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
current_json_schema_extra = json_schema_extra or extra current_json_schema_extra = json_schema_extra or extra
@ -503,7 +504,7 @@ class Body(FieldInfo):
if example is not _Unset: if example is not _Unset:
warnings.warn( warnings.warn(
"`example` has been deprecated, please use `examples` instead", "`example` has been deprecated, please use `examples` instead",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
self.example = example self.example = example
@ -533,7 +534,7 @@ class Body(FieldInfo):
if regex is not None: if regex is not None:
warnings.warn( warnings.warn(
"`regex` has been deprecated, please use `pattern` instead", "`regex` has been deprecated, please use `pattern` instead",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=4, stacklevel=4,
) )
current_json_schema_extra = json_schema_extra or extra current_json_schema_extra = json_schema_extra or extra

5
fastapi/utils.py

@ -23,6 +23,7 @@ from fastapi._compat import (
may_v1, may_v1,
) )
from fastapi.datastructures import DefaultPlaceholder, DefaultType from fastapi.datastructures import DefaultPlaceholder, DefaultType
from fastapi.exceptions import FastAPIDeprecationWarning
from pydantic import BaseModel from pydantic import BaseModel
from pydantic.fields import FieldInfo from pydantic.fields import FieldInfo
from typing_extensions import Literal from typing_extensions import Literal
@ -195,9 +196,9 @@ def generate_operation_id_for_path(
*, name: str, path: str, method: str *, name: str, path: str, method: str
) -> str: # pragma: nocover ) -> str: # pragma: nocover
warnings.warn( warnings.warn(
"fastapi.utils.generate_operation_id_for_path() was deprecated, " message="fastapi.utils.generate_operation_id_for_path() was deprecated, "
"it is not used internally, and will be removed soon", "it is not used internally, and will be removed soon",
DeprecationWarning, category=FastAPIDeprecationWarning,
stacklevel=2, stacklevel=2,
) )
operation_id = f"{name}{path}" operation_id = f"{name}{path}"

3
tests/benchmarks/test_general_performance.py

@ -6,6 +6,7 @@ from typing import Annotated, Any
import pytest import pytest
from fastapi import Depends, FastAPI from fastapi import Depends, FastAPI
from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
if "--codspeed" not in sys.argv: if "--codspeed" not in sys.argv:
@ -89,7 +90,7 @@ def app(basemodel_class: type[Any]) -> FastAPI:
warnings.filterwarnings( warnings.filterwarnings(
"ignore", "ignore",
message=r"pydantic\.v1 is deprecated and will soon stop being supported by FastAPI\..*", message=r"pydantic\.v1 is deprecated and will soon stop being supported by FastAPI\..*",
category=DeprecationWarning, category=FastAPIDeprecationWarning,
) )
@app.post("/sync/validated", response_model=ItemOut) @app.post("/sync/validated", response_model=ItemOut)

Loading…
Cancel
Save