Skip to content

Commit

Permalink
Support Pydantic v2 with v1 backport (#326)
Browse files Browse the repository at this point in the history
Simpler migration to pydantic v2
  • Loading branch information
jaykv authored Jul 18, 2023
1 parent e1e0228 commit 5c27305
Show file tree
Hide file tree
Showing 17 changed files with 57 additions and 22 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.DEFAULT_GOAL:=install

SOURCE_FILES=spectree tests examples
MYPY_SOURCE_FILES=spectree tests # temporary

install:
pip install -U -e .[email,quart,flask,falcon,starlette,dev]
Expand Down Expand Up @@ -43,6 +44,6 @@ lint:
isort --check --diff --project=spectree ${SOURCE_FILES}
black --check --diff ${SOURCE_FILES}
flake8 ${SOURCE_FILES} --count --show-source --statistics --ignore=D203,E203,W503 --max-line-length=88 --max-complexity=15
mypy --install-types --non-interactive ${SOURCE_FILES}
mypy --install-types --non-interactive ${MYPY_SOURCE_FILES}

.PHONY: test doc
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
]
dependencies = [
"pydantic>=1.2,<2",
"pydantic>=1.2,<3",
]

[project.optional-dependencies]
Expand All @@ -37,7 +37,7 @@ dev = [
"syrupy>=4.0",
]
email = [
"pydantic[email]>=1.2,<2",
"pydantic[email]>=1.2,<3",
]
falcon = [
"falcon>=3.0.0",
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
setup(
name="spectree",
install_requires=[
"pydantic>=1.2,<2",
"pydantic>=1.2,<3",
],
extras_require={
"email": ["pydantic[email]>=1.2,<2"],
"email": ["pydantic[email]>=1.2,<3"],
"flask": ["flask"],
"quart": ["quart"],
"falcon": ["falcon>=3.0.0"],
Expand Down
37 changes: 37 additions & 0 deletions spectree/_pydantic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from pydantic.version import VERSION as PYDANTIC_VERSION

PYDANTIC2 = PYDANTIC_VERSION.startswith("2")

__all__ = [
"BaseModel",
"ValidationError",
"Field",
"root_validator",
"AnyUrl",
"BaseSettings",
"EmailStr",
"validator",
]

if PYDANTIC2:
from pydantic.v1 import (
AnyUrl,
BaseModel,
BaseSettings,
EmailStr,
Field,
ValidationError,
root_validator,
validator,
)
else:
from pydantic import ( # type: ignore[no-redef,assignment]
AnyUrl,
BaseModel,
BaseSettings,
EmailStr,
Field,
ValidationError,
root_validator,
validator,
)
3 changes: 2 additions & 1 deletion spectree/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
Union,
)

from pydantic import BaseModel
from typing_extensions import Protocol

from ._pydantic import BaseModel

ModelType = Type[BaseModel]
OptionalModelType = Optional[ModelType]
NamingStrategy = Callable[[ModelType], str]
Expand Down
3 changes: 1 addition & 2 deletions spectree/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
from enum import Enum
from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Union

from pydantic import AnyUrl, BaseModel, BaseSettings, EmailStr, root_validator

from ._pydantic import AnyUrl, BaseModel, BaseSettings, EmailStr, root_validator
from .models import SecurityScheme, Server
from .page import DEFAULT_PAGE_TEMPLATES

Expand Down
2 changes: 1 addition & 1 deletion spectree/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from enum import Enum
from typing import Any, Dict, Optional, Sequence

from pydantic import BaseModel, Field, root_validator, validator
from ._pydantic import BaseModel, Field, root_validator, validator

# OpenAPI names validation regexp
OpenAPI_NAME_RE = re.compile(r"^[A-Za-z0-9-._]+")
Expand Down
2 changes: 1 addition & 1 deletion spectree/plugins/falcon_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

from falcon import HTTP_400, HTTP_415, HTTPError
from falcon.routing.compiled import _FIELD_PATTERN as FALCON_FIELD_PATTERN
from pydantic import ValidationError

from .._pydantic import ValidationError
from .._types import ModelType
from ..response import Response
from .base import BasePlugin
Expand Down
2 changes: 1 addition & 1 deletion spectree/plugins/flask_plugin.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from typing import Any, Callable, Mapping, Optional, Tuple, get_type_hints

from flask import Blueprint, abort, current_app, jsonify, make_response, request
from pydantic import BaseModel, ValidationError
from werkzeug.routing import parse_converter_args

from .._pydantic import BaseModel, ValidationError
from .._types import ModelType
from ..response import Response
from ..utils import get_multidict_items, werkzeug_parse_rule
Expand Down
2 changes: 1 addition & 1 deletion spectree/plugins/quart_plugin.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import inspect
from typing import Any, Callable, Mapping, Optional, Tuple, get_type_hints

from pydantic import BaseModel, ValidationError
from quart import Blueprint, abort, current_app, jsonify, make_response, request
from werkzeug.routing import parse_converter_args

from .._pydantic import BaseModel, ValidationError
from .._types import ModelType
from ..response import Response
from ..utils import get_multidict_items, werkzeug_parse_rule
Expand Down
2 changes: 1 addition & 1 deletion spectree/plugins/starlette_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
from json import JSONDecodeError
from typing import Any, Callable, Optional, get_type_hints

from pydantic import ValidationError
from starlette.convertors import CONVERTOR_TYPES
from starlette.requests import Request
from starlette.responses import HTMLResponse, JSONResponse
from starlette.routing import compile_path

from .._pydantic import ValidationError
from .._types import ModelType
from ..response import Response
from .base import BasePlugin, Context
Expand Down
3 changes: 1 addition & 2 deletions spectree/response.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from http import HTTPStatus
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union

from pydantic import BaseModel

from ._pydantic import BaseModel
from ._types import ModelType, NamingStrategy, OptionalModelType
from .utils import gen_list_model, get_model_key, parse_code

Expand Down
3 changes: 1 addition & 2 deletions spectree/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
Union,
)

from pydantic import BaseModel, ValidationError

from ._pydantic import BaseModel, ValidationError
from ._types import ModelType, MultiDict, NamingStrategy, NestedNamingStrategy

# parse HTTP status code to get the code
Expand Down
3 changes: 1 addition & 2 deletions tests/common.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from enum import Enum, IntEnum
from typing import Dict, List

from pydantic import BaseModel, Field, root_validator

from spectree import BaseFile, ExternalDocs, SecurityScheme, SecuritySchemeData, Tag
from spectree._pydantic import BaseModel, Field, root_validator
from spectree.utils import hash_module_path

api_tag = Tag(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
from typing import Type

import pytest
from pydantic import ValidationError

from spectree import SecurityScheme
from spectree._pydantic import ValidationError
from spectree.config import Configuration, EmailFieldType

from .common import SECURITY_SCHEMAS, WRONG_SECURITY_SCHEMAS_DATA
Expand Down
2 changes: 1 addition & 1 deletion tests/test_response.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from typing import List, get_type_hints

import pytest
from pydantic import BaseModel

from spectree._pydantic import BaseModel
from spectree.models import ValidationError
from spectree.response import DEFAULT_CODE_DESC, Response
from spectree.utils import gen_list_model
Expand Down
2 changes: 1 addition & 1 deletion tests/test_spec.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import pytest
from falcon import App as FalconApp
from flask import Flask
from pydantic import BaseModel
from starlette.applications import Starlette

from spectree import Response
from spectree._pydantic import BaseModel
from spectree.config import Configuration
from spectree.models import Server, ValidationError
from spectree.plugins.flask_plugin import FlaskPlugin
Expand Down

0 comments on commit 5c27305

Please sign in to comment.