Merging upstream version 2.10.2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
a51a0b430d
commit
9865822c70
20 changed files with 176 additions and 49 deletions
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: astral-sh/setup-uv@v4
|
||||
- uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
|
@ -39,7 +39,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
|
||||
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
|
||||
|
||||
env:
|
||||
UV_PYTHON: ${{ matrix.python-version }}
|
||||
|
@ -47,7 +47,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: astral-sh/setup-uv@v4
|
||||
- uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
|
@ -74,7 +74,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: astral-sh/setup-uv@v4
|
||||
- uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
|
@ -111,7 +111,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: astral-sh/setup-uv@v4
|
||||
- uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: no-commit-to-branch # prevent direct commits to the `main` branch
|
||||
- id: check-yaml
|
||||
|
@ -24,3 +24,10 @@ repos:
|
|||
types: [python]
|
||||
language: system
|
||||
pass_filenames: false
|
||||
- id: Typecheck
|
||||
name: Typecheck
|
||||
entry: make
|
||||
args: [typecheck]
|
||||
types: [python]
|
||||
language: system
|
||||
pass_filenames: false
|
||||
|
|
44
HISTORY.md
44
HISTORY.md
|
@ -2,6 +2,50 @@
|
|||
|
||||
## Latest Changes
|
||||
|
||||
## 2.10.2
|
||||
|
||||
* Add back Python 3.8 support by @Viicos in https://github.com/pydantic/pydantic-extra-types/pull/249
|
||||
* ⬆ Bump astral-sh/setup-uv from 4 to 5 by @dependabot in https://github.com/pydantic/pydantic-extra-types/pull/282
|
||||
* Preserve months when using the Pendulum Duration type by @gareththackeray in https://github.com/pydantic/pydantic-extra-types/pull/283
|
||||
* ✨ Add type checking support and improve type hints across the codebase by @yezz123 in https://github.com/pydantic/pydantic-extra-types/pull/285
|
||||
* 📝 Add additional installation information to README by @oakhan3 in https://github.com/pydantic/pydantic-extra-types/pull/233
|
||||
|
||||
## 2.10.1
|
||||
|
||||
* Allow build with python-ulid 3.0.0 by @sunpoet in https://github.com/pydantic/pydantic-extra-types/pull/225
|
||||
* 🔨 added automatic syntax-upgrade hook ~ pyupgrade by @janas-adam in https://github.com/pydantic/pydantic-extra-types/pull/229
|
||||
* :fire: Revert adding pyupgrade as a hook in pre-commit by @yezz123 in https://github.com/pydantic/pydantic-extra-types/pull/230
|
||||
* isolate url in Currency by @edasubert in https://github.com/pydantic/pydantic-extra-types/pull/235
|
||||
* lower case currency is valid by @edasubert in https://github.com/pydantic/pydantic-extra-types/pull/236
|
||||
* Update SemanticVersion by @viccie30 in https://github.com/pydantic/pydantic-extra-types/pull/237
|
||||
* Epoch - unix timestamp by @commonism in https://github.com/pydantic/pydantic-extra-types/pull/240
|
||||
* :recycle: Migrate Pydantic Extra Types to use uv by @yezz123 in https://github.com/pydantic/pydantic-extra-types/pull/241
|
||||
* ⬆ Bump astral-sh/setup-uv from 3 to 4 by @dependabot in https://github.com/pydantic/pydantic-extra-types/pull/245
|
||||
* ⬆ Bump pre-commit/action from 3.0.0 to 3.0.1 by @dependabot in https://github.com/pydantic/pydantic-extra-types/pull/244
|
||||
* 🔖 Release version 2.10.1 by @yezz123 in https://github.com/pydantic/pydantic-extra-types/pull/246
|
||||
* Fix check python version for release by @hramezani in https://github.com/pydantic/pydantic-extra-types/pull/247
|
||||
|
||||
## 2.10.0
|
||||
|
||||
### Types
|
||||
|
||||
* Add semantic version type by @jbkroner in https://github.com/pydantic/pydantic-extra-types/pull/199
|
||||
* feat: add S3Path by @lucianosrp in https://github.com/pydantic/pydantic-extra-types/pull/206
|
||||
|
||||
### Refactor
|
||||
|
||||
* feature: Improve phone number validator by @mZbZ in https://github.com/pydantic/pydantic-extra-types/pull/202
|
||||
* Feature: Add phone number validator by @mZbZ in https://github.com/pydantic/pydantic-extra-types/pull/203
|
||||
* Domain name string type by @matter1-git in https://github.com/pydantic/pydantic-extra-types/pull/212
|
||||
* Adjust test_json_schema() for Pydantic 2.9 by @musicinmybrain in https://github.com/pydantic/pydantic-extra-types/pull/215
|
||||
* Allow python-ulid 3.0 by @musicinmybrain in https://github.com/pydantic/pydantic-extra-types/pull/222
|
||||
|
||||
### Dependencies
|
||||
|
||||
* ⬆ Bump the python-packages group with 5 updates by @dependabot in https://github.com/pydantic/pydantic-extra-types/pull/201
|
||||
* ✨ deprecate `semver` in favor of `semantic_version` by @07pepa in https://github.com/pydantic/pydantic-extra-types/pull/209
|
||||
* 🔖 Release version 2.10.0 by @yezz123 in https://github.com/pydantic/pydantic-extra-types/pull/224
|
||||
|
||||
## 2.9.0
|
||||
|
||||
### Types
|
||||
|
|
4
Makefile
4
Makefile
|
@ -25,6 +25,10 @@ lint:
|
|||
uv run ruff format --check
|
||||
uv run ruff check
|
||||
|
||||
.PHONY: typecheck # Typecheck the code
|
||||
typecheck:
|
||||
uv run mypy pydantic_extra_types
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
uv run pytest
|
||||
|
|
14
README.md
14
README.md
|
@ -8,3 +8,17 @@
|
|||
A place for pydantic types that probably shouldn't exist in the main pydantic lib.
|
||||
|
||||
See [pydantic/pydantic#5012](https://github.com/pydantic/pydantic/issues/5012) for more info.
|
||||
|
||||
## Installation
|
||||
|
||||
Install this library with the desired extras dependencies as listed in [project.optional-dependencies](./pyproject.toml).
|
||||
|
||||
For example, if pendulum support was desired:
|
||||
|
||||
```shell
|
||||
# via uv
|
||||
$ uv add "pydantic-extra-types[pendulum]"
|
||||
|
||||
# via pip
|
||||
$ pip install -U "pydantic-extra-types[pendulum]"
|
||||
```
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__ = '2.10.1'
|
||||
__version__ = '2.10.2'
|
||||
|
|
|
@ -12,16 +12,16 @@ from __future__ import annotations
|
|||
import math
|
||||
import re
|
||||
from colorsys import hls_to_rgb, rgb_to_hls
|
||||
from typing import Any, Callable, Literal, Union, cast
|
||||
from typing import Any, Callable, Literal, Tuple, Union, cast
|
||||
|
||||
from pydantic import GetJsonSchemaHandler
|
||||
from pydantic._internal import _repr
|
||||
from pydantic.json_schema import JsonSchemaValue
|
||||
from pydantic_core import CoreSchema, PydanticCustomError, core_schema
|
||||
|
||||
ColorTuple = Union[tuple[int, int, int], tuple[int, int, int, float]]
|
||||
ColorTuple = Union[Tuple[int, int, int], Tuple[int, int, int, float]]
|
||||
ColorType = Union[ColorTuple, str, 'Color']
|
||||
HslColorTuple = Union[tuple[float, float, float], tuple[float, float, float, float]]
|
||||
HslColorTuple = Union[Tuple[float, float, float], Tuple[float, float, float, float]]
|
||||
|
||||
|
||||
class RGBA:
|
||||
|
@ -115,7 +115,7 @@ class Color(_repr.Representation):
|
|||
"""
|
||||
if self._rgba.alpha is not None:
|
||||
return self.as_hex()
|
||||
rgb = cast(tuple[int, int, int], self.as_rgb_tuple())
|
||||
rgb = cast('tuple[int, int, int]', self.as_rgb_tuple())
|
||||
|
||||
if rgb in COLORS_BY_VALUE:
|
||||
return COLORS_BY_VALUE[rgb]
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
[`Coordinate`][pydantic_extra_types.coordinate.Coordinate] data types.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any, ClassVar, Tuple
|
||||
|
||||
from pydantic import GetCoreSchemaHandler
|
||||
from pydantic._internal import _repr
|
||||
|
@ -89,7 +91,7 @@ class Coordinate(_repr.Representation):
|
|||
```
|
||||
"""
|
||||
|
||||
_NULL_ISLAND: ClassVar[tuple[float, float]] = (0.0, 0.0)
|
||||
_NULL_ISLAND: ClassVar[Tuple[float, float]] = (0.0, 0.0)
|
||||
|
||||
latitude: Latitude
|
||||
longitude: Longitude
|
||||
|
@ -100,7 +102,7 @@ class Coordinate(_repr.Representation):
|
|||
core_schema.no_info_wrap_validator_function(cls._parse_str, core_schema.str_schema()),
|
||||
core_schema.no_info_wrap_validator_function(
|
||||
cls._parse_tuple,
|
||||
handler.generate_schema(tuple[float, float]),
|
||||
handler.generate_schema(Tuple[float, float]),
|
||||
),
|
||||
handler(source),
|
||||
]
|
||||
|
|
|
@ -5,7 +5,6 @@ This class depends on the `pydantic` package and implements custom validation fo
|
|||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
|
||||
from pydantic import GetCoreSchemaHandler
|
||||
|
@ -54,5 +53,6 @@ class DomainStr(str):
|
|||
@classmethod
|
||||
def __get_pydantic_json_schema__(
|
||||
cls, schema: core_schema.CoreSchema, handler: GetCoreSchemaHandler
|
||||
) -> Mapping[str, Any]:
|
||||
return handler(schema)
|
||||
) -> dict[str, Any]:
|
||||
# Cast the return value to dict[str, Any]
|
||||
return dict(handler(schema))
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
CoreSchema implementation. This allows Pydantic to validate the DateTime object.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
try:
|
||||
from pendulum import Date as _Date
|
||||
from pendulum import DateTime as _DateTime
|
||||
|
@ -63,7 +65,7 @@ class DateTime(_DateTime, metaclass=DateTimeSettings):
|
|||
return core_schema.no_info_wrap_validator_function(cls._validate, core_schema.datetime_schema())
|
||||
|
||||
@classmethod
|
||||
def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler) -> 'DateTime':
|
||||
def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler) -> DateTime:
|
||||
"""Validate the datetime object and return it.
|
||||
|
||||
Args:
|
||||
|
@ -128,7 +130,7 @@ class Date(_Date):
|
|||
return core_schema.no_info_wrap_validator_function(cls._validate, core_schema.date_schema())
|
||||
|
||||
@classmethod
|
||||
def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler) -> 'Date':
|
||||
def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler) -> Date:
|
||||
"""Validate the date object and return it.
|
||||
|
||||
Args:
|
||||
|
@ -187,7 +189,7 @@ class Duration(_Duration):
|
|||
return core_schema.no_info_wrap_validator_function(cls._validate, core_schema.timedelta_schema())
|
||||
|
||||
@classmethod
|
||||
def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler) -> 'Duration':
|
||||
def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler) -> Duration:
|
||||
"""Validate the Duration object and return it.
|
||||
|
||||
Args:
|
||||
|
@ -197,9 +199,25 @@ class Duration(_Duration):
|
|||
Returns:
|
||||
The validated value or raises a PydanticCustomError.
|
||||
"""
|
||||
# if we are passed an existing instance, pass it straight through.
|
||||
if isinstance(value, (_Duration, timedelta)):
|
||||
return Duration(seconds=value.total_seconds())
|
||||
|
||||
if isinstance(value, _Duration):
|
||||
return Duration(
|
||||
years=value.years,
|
||||
months=value.months,
|
||||
weeks=value.weeks,
|
||||
days=value.remaining_days,
|
||||
hours=value.hours,
|
||||
minutes=value.minutes,
|
||||
seconds=value.remaining_seconds,
|
||||
microseconds=value.microseconds,
|
||||
)
|
||||
|
||||
if isinstance(value, timedelta):
|
||||
return Duration(
|
||||
days=value.days,
|
||||
seconds=value.seconds,
|
||||
microseconds=value.microseconds,
|
||||
)
|
||||
|
||||
try:
|
||||
parsed = parse(value, exact=True)
|
||||
|
|
|
@ -9,7 +9,7 @@ from __future__ import annotations
|
|||
from collections.abc import Sequence
|
||||
from dataclasses import dataclass
|
||||
from functools import partial
|
||||
from typing import Any, ClassVar, Optional
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from pydantic import GetCoreSchemaHandler, GetJsonSchemaHandler
|
||||
from pydantic_core import PydanticCustomError, core_schema
|
||||
|
@ -90,7 +90,7 @@ class PhoneNumberValidator:
|
|||
supported_regions (list[str]): The supported regions. If empty, all regions are supported (default).
|
||||
|
||||
Returns:
|
||||
str: The formatted phone number.
|
||||
The formatted phone number.
|
||||
|
||||
Example:
|
||||
MyNumberType = Annotated[
|
||||
|
@ -107,9 +107,9 @@ class PhoneNumberValidator:
|
|||
us_number: USNumberType
|
||||
"""
|
||||
|
||||
default_region: Optional[str] = None
|
||||
default_region: str | None = None
|
||||
number_format: str = 'RFC3966'
|
||||
supported_regions: Optional[Sequence[str]] = None
|
||||
supported_regions: Sequence[str] | None = None
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self.default_region and self.default_region not in phonenumbers.SUPPORTED_REGIONS:
|
||||
|
@ -131,7 +131,7 @@ class PhoneNumberValidator:
|
|||
def _parse(
|
||||
region: str | None,
|
||||
number_format: str,
|
||||
supported_regions: Optional[Sequence[str]],
|
||||
supported_regions: Sequence[str] | None,
|
||||
phone_number: Any,
|
||||
) -> str:
|
||||
if not phone_number:
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
[`ABARoutingNumber`][pydantic_extra_types.routing_number.ABARoutingNumber] data type.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from pydantic import GetCoreSchemaHandler
|
||||
|
@ -54,7 +56,7 @@ class ABARoutingNumber(str):
|
|||
)
|
||||
|
||||
@classmethod
|
||||
def _validate(cls, __input_value: str, _: core_schema.ValidationInfo) -> 'ABARoutingNumber':
|
||||
def _validate(cls, __input_value: str, _: core_schema.ValidationInfo) -> ABARoutingNumber:
|
||||
return cls(__input_value)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -53,3 +53,7 @@ class SemanticVersion(semver.Version):
|
|||
pattern=r'^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def validate_from_str(cls, value: str) -> 'SemanticVersion':
|
||||
return cls.parse(value)
|
||||
|
|
|
@ -4,12 +4,13 @@ This class depends on the [semver](https://python-semver.readthedocs.io/en/lates
|
|||
"""
|
||||
|
||||
import warnings
|
||||
from typing import Annotated, Any, Callable
|
||||
from typing import Any, Callable
|
||||
|
||||
from pydantic import GetJsonSchemaHandler
|
||||
from pydantic.json_schema import JsonSchemaValue
|
||||
from pydantic_core import core_schema
|
||||
from semver import Version
|
||||
from typing_extensions import Annotated
|
||||
|
||||
warnings.warn(
|
||||
'Use from pydantic_extra_types.semver import SemanticVersion instead. Will be removed in 3.0.0.', DeprecationWarning
|
||||
|
|
|
@ -57,7 +57,7 @@ def get_timezones() -> set[str]:
|
|||
class TimeZoneNameSettings(type):
|
||||
def __new__(cls, name: str, bases: tuple[type, ...], dct: dict[str, Any], **kwargs: Any) -> type[TimeZoneName]:
|
||||
dct['strict'] = kwargs.pop('strict', True)
|
||||
return cast(type[TimeZoneName], super().__new__(cls, name, bases, dct))
|
||||
return cast('type[TimeZoneName]', super().__new__(cls, name, bases, dct))
|
||||
|
||||
def __init__(cls, name: str, bases: tuple[type, ...], dct: dict[str, Any], **kwargs: Any) -> None:
|
||||
super().__init__(name, bases, dct)
|
||||
|
|
|
@ -92,7 +92,7 @@ keep-runtime-typing = true
|
|||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
target-version = "py39"
|
||||
target-version = 'py38'
|
||||
|
||||
[tool.ruff.lint]
|
||||
extend-select = [
|
||||
|
|
|
@ -3,12 +3,7 @@ from typing import Union
|
|||
import pycountry
|
||||
import pytest
|
||||
from pydantic import BaseModel
|
||||
|
||||
try:
|
||||
from typing import Annotated
|
||||
except ImportError:
|
||||
# Python 3.8
|
||||
from typing import Annotated
|
||||
from typing_extensions import Annotated
|
||||
|
||||
import pydantic_extra_types
|
||||
from pydantic_extra_types import epoch
|
||||
|
|
|
@ -92,8 +92,30 @@ def test_pendulum_date_existing_instance(instance):
|
|||
[
|
||||
pendulum.duration(days=42, hours=13, minutes=37),
|
||||
pendulum.duration(days=-42, hours=13, minutes=37),
|
||||
pendulum.duration(weeks=97),
|
||||
pendulum.duration(days=463),
|
||||
pendulum.duration(milliseconds=90122),
|
||||
pendulum.duration(microseconds=90122),
|
||||
pendulum.duration(
|
||||
years=2,
|
||||
months=3,
|
||||
weeks=19,
|
||||
days=1,
|
||||
hours=25,
|
||||
seconds=732,
|
||||
milliseconds=123,
|
||||
microseconds=1324,
|
||||
),
|
||||
timedelta(days=42, hours=13, minutes=37),
|
||||
timedelta(days=-42, hours=13, minutes=37),
|
||||
timedelta(
|
||||
weeks=19,
|
||||
days=1,
|
||||
hours=25,
|
||||
seconds=732,
|
||||
milliseconds=123,
|
||||
microseconds=1324,
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_duration_timedelta__existing_instance(instance):
|
||||
|
@ -227,7 +249,11 @@ def test_pendulum_dt_from_str_unix_timestamp_is_utc(dt):
|
|||
|
||||
@pytest.mark.parametrize(
|
||||
'd',
|
||||
[pendulum.now().date().isoformat(), pendulum.now().to_w3c_string(), pendulum.now().to_iso8601_string()],
|
||||
[
|
||||
pendulum.now().date().isoformat(),
|
||||
pendulum.now().to_w3c_string(),
|
||||
pendulum.now().to_iso8601_string(),
|
||||
],
|
||||
)
|
||||
def test_pendulum_date_from_serialized(d):
|
||||
"""Verifies that building an instance from serialized, well-formed strings decode properly."""
|
||||
|
@ -308,7 +334,10 @@ def test_pendulum_dt_non_strict_malformed(dt):
|
|||
DtModelNotStrict(dt=dt)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('invalid_value', [None, 'malformed', pendulum.today().to_iso8601_string()[:5], 'P10Y10M10D'])
|
||||
@pytest.mark.parametrize(
|
||||
'invalid_value',
|
||||
[None, 'malformed', pendulum.today().to_iso8601_string()[:5], 'P10Y10M10D'],
|
||||
)
|
||||
def test_pendulum_date_malformed(invalid_value):
|
||||
"""Verifies that the instance fails to validate if malformed date are passed."""
|
||||
with pytest.raises(ValidationError):
|
||||
|
@ -317,7 +346,14 @@ def test_pendulum_date_malformed(invalid_value):
|
|||
|
||||
@pytest.mark.parametrize(
|
||||
'delta_t',
|
||||
[None, 'malformed', pendulum.today().to_iso8601_string()[:5], 42, '12m', '2021-01-01T12:00:00'],
|
||||
[
|
||||
None,
|
||||
'malformed',
|
||||
pendulum.today().to_iso8601_string()[:5],
|
||||
42,
|
||||
'12m',
|
||||
'2021-01-01T12:00:00',
|
||||
],
|
||||
)
|
||||
def test_pendulum_duration_malformed(delta_t):
|
||||
"""Verifies that the instance fails to validate if malformed durations are passed."""
|
||||
|
@ -344,3 +380,9 @@ def test_date_type_adapter(input_type: type, value, is_instance: type):
|
|||
assert type(validated) is input_type
|
||||
assert isinstance(validated, input_type)
|
||||
assert isinstance(validated, is_instance)
|
||||
|
||||
|
||||
def test_pendulum_duration_months_are_preserved():
|
||||
m = DurationModel(delta_t=pendulum.Duration(months=1))
|
||||
|
||||
assert m.delta_t.months == 1
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
from typing import Any, Optional, Union
|
||||
|
||||
try:
|
||||
from typing import Annotated
|
||||
except ImportError:
|
||||
# Python 3.8
|
||||
from typing import Annotated
|
||||
|
||||
|
||||
import phonenumbers
|
||||
import pytest
|
||||
from phonenumbers import PhoneNumber
|
||||
from pydantic import BaseModel, TypeAdapter, ValidationError
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from pydantic_extra_types.phone_numbers import PhoneNumberValidator
|
||||
|
||||
|
|
2
uv.lock
generated
2
uv.lock
generated
|
@ -477,7 +477,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "pydantic-extra-types"
|
||||
version = "2.10.0"
|
||||
version = "2.10.1"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
|
|
Loading…
Add table
Reference in a new issue