diff --git a/Makefile b/Makefile index 11ae817..f478ead 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,7 @@ lint: $(INSTALL_STAMP) dist $(POETRY) run isort --profile=black --lines-after-imports=2 ./tests/ $(NAME) $(SYNC_NAME) $(POETRY) run black ./tests/ $(NAME) $(POETRY) run flake8 --ignore=W503,E501,F401,E731 ./tests/ $(NAME) $(SYNC_NAME) - $(POETRY) run mypy ./tests/ $(NAME) $(SYNC_NAME) --ignore-missing-imports --exclude migrate.py + $(POETRY) run mypy ./tests/ $(NAME) $(SYNC_NAME) --ignore-missing-imports --exclude migrate.py --exclude _compat\.py$ $(POETRY) run bandit -r $(NAME) $(SYNC_NAME) -s B608 .PHONY: format diff --git a/aredis_om/_compat.py b/aredis_om/_compat.py new file mode 100644 index 0000000..0246e4f --- /dev/null +++ b/aredis_om/_compat.py @@ -0,0 +1,19 @@ +from pydantic.version import VERSION as PYDANTIC_VERSION + + +PYDANTIC_V2 = PYDANTIC_VERSION.startswith("2.") + +if PYDANTIC_V2: + from pydantic.v1 import BaseModel, validator + from pydantic.v1.fields import FieldInfo, ModelField, Undefined, UndefinedType + from pydantic.v1.json import ENCODERS_BY_TYPE + from pydantic.v1.main import ModelMetaclass, validate_model + from pydantic.v1.typing import NoArgAnyCallable + from pydantic.v1.utils import Representation +else: + from pydantic import BaseModel, validator + from pydantic.fields import FieldInfo, ModelField, Undefined, UndefinedType + from pydantic.json import ENCODERS_BY_TYPE + from pydantic.main import ModelMetaclass, validate_model + from pydantic.typing import NoArgAnyCallable + from pydantic.utils import Representation diff --git a/aredis_om/model/encoders.py b/aredis_om/model/encoders.py index 4007640..2f90e48 100644 --- a/aredis_om/model/encoders.py +++ b/aredis_om/model/encoders.py @@ -31,8 +31,7 @@ from pathlib import PurePath from types import GeneratorType from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union -from pydantic import BaseModel -from pydantic.json import ENCODERS_BY_TYPE +from .._compat import ENCODERS_BY_TYPE, BaseModel SetIntStr = Set[Union[int, str]] diff --git a/aredis_om/model/model.py b/aredis_om/model/model.py index 0ccc5b0..a4c6b9e 100644 --- a/aredis_om/model/model.py +++ b/aredis_om/model/model.py @@ -25,18 +25,24 @@ from typing import ( ) from more_itertools import ichunked -from pydantic import BaseModel, validator -from pydantic.fields import FieldInfo as PydanticFieldInfo -from pydantic.fields import ModelField, Undefined, UndefinedType -from pydantic.main import ModelMetaclass, validate_model -from pydantic.typing import NoArgAnyCallable -from pydantic.utils import Representation from redis.commands.json.path import Path from redis.exceptions import ResponseError from typing_extensions import Protocol, get_args, get_origin from ulid import ULID from .. import redis +from .._compat import BaseModel +from .._compat import FieldInfo as PydanticFieldInfo +from .._compat import ( + ModelField, + ModelMetaclass, + NoArgAnyCallable, + Representation, + Undefined, + UndefinedType, + validate_model, + validator, +) from ..checks import has_redis_json, has_redisearch from ..connections import get_redis_connection from ..util import ASYNC_MODE diff --git a/pyproject.toml b/pyproject.toml index c84e05a..cd774be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ include=[ [tool.poetry.dependencies] python = ">=3.7,<4.0" redis = ">=3.5.3,<5.0.0" -pydantic = "^1.10.2" +pydantic = ">=1.10.2,<2.1.0" click = "^8.0.1" types-redis = ">=3.5.9,<5.0.0" python-ulid = "^1.0.3" diff --git a/tests/_compat.py b/tests/_compat.py new file mode 100644 index 0000000..c21b47d --- /dev/null +++ b/tests/_compat.py @@ -0,0 +1,7 @@ +from aredis_om._compat import PYDANTIC_V2 + + +if PYDANTIC_V2: + from pydantic.v1 import EmailStr, ValidationError +else: + from pydantic import EmailStr, ValidationError diff --git a/tests/test_hash_model.py b/tests/test_hash_model.py index 8fe4a60..38ca18e 100644 --- a/tests/test_hash_model.py +++ b/tests/test_hash_model.py @@ -10,7 +10,6 @@ from unittest import mock import pytest import pytest_asyncio -from pydantic import ValidationError from aredis_om import ( Field, @@ -24,6 +23,7 @@ from aredis_om import ( # We need to run this check as sync code (during tests) even in async mode # because we call it in the top-level module scope. from redis_om import has_redisearch +from tests._compat import ValidationError from .conftest import py_test_mark_asyncio diff --git a/tests/test_json_model.py b/tests/test_json_model.py index ee220bd..8fec6c0 100644 --- a/tests/test_json_model.py +++ b/tests/test_json_model.py @@ -10,7 +10,6 @@ from unittest import mock import pytest import pytest_asyncio -from pydantic import ValidationError from aredis_om import ( EmbeddedJsonModel, @@ -25,6 +24,7 @@ from aredis_om import ( # We need to run this check as sync code (during tests) even in async mode # because we call it in the top-level module scope. from redis_om import has_redis_json +from tests._compat import ValidationError from .conftest import py_test_mark_asyncio diff --git a/tests/test_oss_redis_features.py b/tests/test_oss_redis_features.py index e14f955..4d5b091 100644 --- a/tests/test_oss_redis_features.py +++ b/tests/test_oss_redis_features.py @@ -6,9 +6,9 @@ from typing import Optional import pytest import pytest_asyncio -from pydantic import ValidationError from aredis_om import HashModel, Migrator, NotFoundError, RedisModelError +from tests._compat import ValidationError from .conftest import py_test_mark_asyncio diff --git a/tests/test_pydantic_integrations.py b/tests/test_pydantic_integrations.py index 5ff735f..12d41a9 100644 --- a/tests/test_pydantic_integrations.py +++ b/tests/test_pydantic_integrations.py @@ -4,9 +4,9 @@ from collections import namedtuple import pytest import pytest_asyncio -from pydantic import EmailStr, ValidationError from aredis_om import Field, HashModel, Migrator +from tests._compat import EmailStr, ValidationError today = datetime.date.today()