Skip to content

Commit

Permalink
feat!: compatibility with pydantic v2 (#148)
Browse files Browse the repository at this point in the history
Pydantic v1 is EOL, but some users of this library still use it. Pydantic v2 contains the pydantic v1
in the pydantic.v1 namespace, and pydantic v1.10.17+ also contains this same namespace. So, step one
to migrating to Pydantic v2 is to use the pydantic.v1 namespace throughout. Then, in future, the models
can be updated to true Pydantic v2 when all consumers are ready for it.

I'm marking this as a breaking change since the pydantic library update is not backwards compatible.

Signed-off-by: Daniel Neilson <53624638+ddneilson@users.noreply.github.com>
  • Loading branch information
ddneilson authored Oct 28, 2024
1 parent 7d49e04 commit c359496
Show file tree
Hide file tree
Showing 27 changed files with 53 additions and 53 deletions.
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ classifiers = [
]
dependencies = [
"pyyaml == 6.0.*",
"pydantic ~= 1.10",
"pydantic >= 1.10.17",
]

[project.urls]
Expand Down Expand Up @@ -99,7 +99,7 @@ mypy_path = "src"

# See: https://docs.pydantic.dev/mypy_plugin/
# - Helps mypy understand pydantic typing.
plugins = "pydantic.mypy"
plugins = "pydantic.v1.mypy"

[tool.ruff]
line-length = 100
Expand Down
2 changes: 1 addition & 1 deletion src/openjd/model/_convert_pydantic_error.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

from typing import TypedDict, Union, Type
from pydantic import BaseModel
from pydantic.v1 import BaseModel
from inspect import getmodule

# Calling pydantic's ValidationError.errors() returns a list[ErrorDict], but
Expand Down
2 changes: 1 addition & 1 deletion src/openjd/model/_create_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pathlib import Path
from typing import Optional, cast

from pydantic import ValidationError
from pydantic.v1 import ValidationError

from ._errors import CompatibilityError, DecodeValidationError
from ._symbol_table import SymbolTable
Expand Down
8 changes: 4 additions & 4 deletions src/openjd/model/_format_strings/_dyn_constrained_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import re
from typing import TYPE_CHECKING, Any, Callable, Optional, Pattern, Union

from pydantic.errors import AnyStrMaxLengthError, AnyStrMinLengthError, StrRegexError
from pydantic.utils import update_not_none
from pydantic.validators import strict_str_validator
from pydantic.v1.errors import AnyStrMaxLengthError, AnyStrMinLengthError, StrRegexError
from pydantic.v1.utils import update_not_none
from pydantic.v1.validators import strict_str_validator

if TYPE_CHECKING:
from pydantic.typing import CallableGenerator
from pydantic.v1.typing import CallableGenerator


class DynamicConstrainedStr(str):
Expand Down
2 changes: 1 addition & 1 deletion src/openjd/model/_format_strings/_format_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from ._expression import InterpolationExpression

if TYPE_CHECKING:
from pydantic.typing import CallableGenerator
from pydantic.v1.typing import CallableGenerator


@dataclass
Expand Down
4 changes: 2 additions & 2 deletions src/openjd/model/_internal/_create_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from typing import Any, Union

from pydantic import ValidationError
from pydantic.error_wrappers import ErrorWrapper
from pydantic.v1 import ValidationError
from pydantic.v1.error_wrappers import ErrorWrapper

from .._symbol_table import SymbolTable
from .._format_strings import FormatString, FormatStringError
Expand Down
38 changes: 19 additions & 19 deletions src/openjd/model/_internal/_variable_reference_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
from typing import Any, Optional, Type
from inspect import isclass

from pydantic.error_wrappers import ErrorWrapper
import pydantic.fields
from pydantic.typing import is_literal_type
from pydantic.v1.error_wrappers import ErrorWrapper
import pydantic.v1.fields
from pydantic.v1.typing import is_literal_type

from .._types import OpenJDModel, ResolutionScope
from .._format_strings import FormatString, FormatStringError
Expand Down Expand Up @@ -104,7 +104,7 @@
# 4. Since this validation is a pre-validator, we basically have to re-implement a fragment of Pydantic's model parser for this
# depth first traversal. Thus, you'll need to know the following about Pydantic v1.x's data model and parser to understand this
# implementation:
# a) All models are derived from pydantic.BaseModel
# a) All models are derived from pydantic.v1.BaseModel
# b) pydantic.BaseModel.__fields__: dict[str, pydantic.ModelField] is injected into all BaseModels by pydantic's BaseModel metaclass.
# This member is what gives pydantic information about each of the fields defined in the model class. The key of the dict is the
# name of the field in the model.
Expand Down Expand Up @@ -228,7 +228,7 @@ def _validate_model_template_variable_references(
value_symbols = _collect_variable_definitions(cls, values, current_scope, symbol_prefix)

# Recursively validate the contents of FormatStrings within the model.
# Note: cls.__fields__: dict[str, pydantic.fields.ModelField]
# Note: cls.__fields__: dict[str, pydantic.v1.fields.ModelField]
for field_name, field_model in cls.__fields__.items():
field_value = values.get(field_name, None)
if field_value is None:
Expand All @@ -248,7 +248,7 @@ def _validate_model_template_variable_references(
# Add in all of the symbols passed down from the parent.
validation_symbols.update_self(symbols)

if field_model.shape == pydantic.fields.SHAPE_SINGLETON:
if field_model.shape == pydantic.v1.fields.SHAPE_SINGLETON:
_validate_singleton(
errors,
field_model,
Expand All @@ -258,7 +258,7 @@ def _validate_model_template_variable_references(
validation_symbols,
(*loc, field_name),
)
elif field_model.shape == pydantic.fields.SHAPE_LIST:
elif field_model.shape == pydantic.v1.fields.SHAPE_LIST:
if not isinstance(field_value, list):
continue
assert field_model.sub_fields is not None # For the type checker
Expand All @@ -273,7 +273,7 @@ def _validate_model_template_variable_references(
validation_symbols,
(*loc, field_name, i),
)
elif field_model.shape == pydantic.fields.SHAPE_DICT:
elif field_model.shape == pydantic.v1.fields.SHAPE_DICT:
if not isinstance(field_value, dict):
continue
assert field_model.sub_fields is not None # For the type checker
Expand All @@ -300,7 +300,7 @@ def _validate_model_template_variable_references(

def _validate_singleton(
errors: list[ErrorWrapper],
field_model: pydantic.fields.ModelField,
field_model: pydantic.v1.fields.ModelField,
field_value: Any,
current_scope: ResolutionScope,
symbol_prefix: str,
Expand Down Expand Up @@ -356,7 +356,7 @@ def _validate_singleton(

def _validate_general_union(
errors: list[ErrorWrapper],
field_model: pydantic.fields.ModelField,
field_model: pydantic.v1.fields.ModelField,
field_value: Any,
current_scope: ResolutionScope,
symbol_prefix: str,
Expand All @@ -375,11 +375,11 @@ def _validate_general_union(
# and attempt to process the value as that type.
assert field_model.sub_fields is not None # For the type checker
for sub_field in field_model.sub_fields:
if sub_field.shape == pydantic.fields.SHAPE_SINGLETON:
if sub_field.shape == pydantic.v1.fields.SHAPE_SINGLETON:
_validate_singleton(
errors, sub_field, field_value, current_scope, symbol_prefix, symbols, loc
)
elif sub_field.shape == pydantic.fields.SHAPE_LIST:
elif sub_field.shape == pydantic.v1.fields.SHAPE_LIST:
if not isinstance(field_value, list):
# The given value must be a list in this case.
continue
Expand Down Expand Up @@ -414,8 +414,8 @@ def _check_format_string(


def _get_model_for_singleton_value(
field_model: pydantic.fields.ModelField, value: Any
) -> Optional[pydantic.fields.ModelField]:
field_model: pydantic.v1.fields.ModelField, value: Any
) -> Optional[pydantic.v1.fields.ModelField]:
"""Given a ModelField and the value that we're given for that field, determine
the actual ModelField for the value in the event that the ModelField may be for
a discriminated union."""
Expand Down Expand Up @@ -509,7 +509,7 @@ def _collect_variable_definitions( # noqa: C901 (suppress: too complex)
symbol_name = f"{symbol_prefix}{symbol}"
_add_symbol(symbols["__self__"], current_scope, symbol_name)

# Note: cls.__fields__: dict[str, pydantic.fields.ModelField]
# Note: cls.__fields__: dict[str, pydantic.v1.fields.ModelField]
for field_name, field_model in cls.__fields__.items():
field_value = values.get(field_name, None)
if field_value is None:
Expand All @@ -519,11 +519,11 @@ def _collect_variable_definitions( # noqa: C901 (suppress: too complex)
# Literals cannot define variables, so skip this field.
continue

if field_model.shape == pydantic.fields.SHAPE_SINGLETON:
if field_model.shape == pydantic.v1.fields.SHAPE_SINGLETON:
result = _collect_singleton(field_model, field_value, current_scope, symbol_prefix)
if result:
symbols[field_name] = result
elif field_model.shape == pydantic.fields.SHAPE_LIST:
elif field_model.shape == pydantic.v1.fields.SHAPE_LIST:
# If the shape expects a list, but the value isn't one then we have a validation error.
# The error will get flagged by subsequent passes of the model validation.
if not isinstance(field_value, list):
Expand All @@ -535,7 +535,7 @@ def _collect_variable_definitions( # noqa: C901 (suppress: too complex)
result = _collect_singleton(item_model, item, current_scope, symbol_prefix)
if result:
symbols[field_name].update_self(result)
elif field_model.shape == pydantic.fields.SHAPE_DICT:
elif field_model.shape == pydantic.v1.fields.SHAPE_DICT:
# dict[] fields can't define symbols.
continue
else:
Expand Down Expand Up @@ -566,7 +566,7 @@ def _add_symbol(into: ScopedSymtabs, scope: ResolutionScope, symbol_name: str) -


def _collect_singleton(
model: pydantic.fields.ModelField,
model: pydantic.v1.fields.ModelField,
value: Any,
current_scope: ResolutionScope,
symbol_prefix: str,
Expand Down
6 changes: 3 additions & 3 deletions src/openjd/model/_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
from typing import Any, ClassVar, Optional, Type, TypeVar, Union, cast

import yaml
from pydantic import BaseModel
from pydantic import ValidationError as PydanticValidationError
from pydantic.error_wrappers import ErrorWrapper
from pydantic.v1 import BaseModel
from pydantic.v1 import ValidationError as PydanticValidationError
from pydantic.v1.error_wrappers import ErrorWrapper

from ._errors import DecodeValidationError
from ._types import EnvironmentTemplate, JobTemplate, OpenJDModel, TemplateSpecificationVersion
Expand Down
2 changes: 1 addition & 1 deletion src/openjd/model/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from enum import Enum
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, Type, Union

from pydantic import BaseModel, Extra
from pydantic.v1 import BaseModel, Extra

from ._symbol_table import SymbolTable

Expand Down
4 changes: 2 additions & 2 deletions src/openjd/model/v2023_09/_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from typing import TYPE_CHECKING, Any, ClassVar, Literal, Optional, Type, Union, cast
from typing_extensions import Annotated

from pydantic import (
from pydantic.v1 import (
Field,
PositiveInt,
PositiveFloat,
Expand All @@ -22,7 +22,7 @@
root_validator,
validator,
)
from pydantic.error_wrappers import ErrorWrapper
from pydantic.v1.error_wrappers import ErrorWrapper

from .._format_strings import FormatString
from .._errors import ExpressionError, TokenError
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/_internal/test_create_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import Optional, Union, cast

import pytest
from pydantic import PositiveInt, ValidationError
from pydantic.v1 import PositiveInt, ValidationError

from openjd.model import SymbolTable
from openjd.model._format_strings import FormatString
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any, Literal, Union
from enum import Enum
from typing_extensions import Annotated
from pydantic import Field
from pydantic.v1 import Field

import pytest

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import re

import pytest
from pydantic import BaseModel, ValidationError
from pydantic.v1 import BaseModel, ValidationError

from openjd.model._format_strings._dyn_constrained_str import DynamicConstrainedStr

Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/test_convert_pydantic_error.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

from pydantic import BaseModel, root_validator, Field
from pydantic.v1 import BaseModel, root_validator, Field
from typing import Literal, Union

from openjd.model._convert_pydantic_error import (
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import Action, EnvironmentActions, StepActions
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_definitions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

import pytest
from pydantic import BaseModel
from pydantic.v1 import BaseModel
from typing import Type
import openjd.model.v2023_09 as mod
from inspect import getmembers, getmodule, isclass
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_embedded.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import EmbeddedFileText
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_environment_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import EnvironmentTemplate
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import Environment
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_job_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import Any

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import (
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_job_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import JobTemplate
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_parameter_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import (
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import EnvironmentScript, StepScript
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_step_host_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import string

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import (
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_step_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any

import pytest
from pydantic import ValidationError
from pydantic.v1 import ValidationError

from openjd.model._parse import _parse_model
from openjd.model.v2023_09 import StepTemplate
Expand Down
2 changes: 1 addition & 1 deletion test/openjd/model/v2023_09/test_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import string

import pytest
from pydantic import BaseModel, ValidationError
from pydantic.v1 import BaseModel, ValidationError

from openjd.model.v2023_09 import (
AmountCapabilityName,
Expand Down
Loading

0 comments on commit c359496

Please sign in to comment.