Skip to content

Commit c1c84e3

Browse files
committed
Merge remote-tracking branch 'refs/remotes/upstream/main' into validate-base64
2 parents f8addc1 + 66331bb commit c1c84e3

File tree

19 files changed

+220
-96
lines changed

19 files changed

+220
-96
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,9 @@ jobs:
467467
python-version: '3.11'
468468
architecture: ${{ matrix.python-architecture || 'x64' }}
469469

470-
- run: pip install -U twine 'ruff==0.1.3' typing_extensions
470+
- run: pip install -U twine 'ruff==0.1.3'
471+
# TODO: remove manual override for typing_extensions once a version newer than 4.12.1 is released
472+
- run: pip install -U git+https://github.com/python/typing_extensions@main
471473

472474
# generate self-schema now, so we don't have to do so inside docker in maturin build
473475
- run: python generate_self_schema.py
@@ -530,7 +532,9 @@ jobs:
530532
with:
531533
components: llvm-tools
532534

533-
- run: pip install -U 'ruff==0.1.3' typing_extensions
535+
- run: pip install -U 'ruff==0.1.3'
536+
# TODO: remove manual override for typing_extensions once a version newer than 4.12.1 is released
537+
- run: pip install -U git+https://github.com/python/typing_extensions@main
534538

535539
# generate self-schema now, so we don't have to do so inside docker in maturin build
536540
- run: python generate_self_schema.py
@@ -659,10 +663,8 @@ jobs:
659663
fi
660664
run: |
661665
set -x
662-
# typing-extensions isn't automatically installed because of `--no-index --no-deps`
663666
python3 -m venv venv
664667
source venv/bin/activate
665-
python3 -m pip install -U pip typing-extensions
666668
python3 -m pip install -r tests/requirements.txt
667669
python3 -m pip install pydantic-core --no-index --no-deps --find-links dist --force-reinstall
668670
python3 -m pytest --ignore=tests/test_docstrings.py
@@ -693,7 +695,6 @@ jobs:
693695
merge-multiple: true
694696
path: dist
695697

696-
- run: pip install typing-extensions
697698
- run: pip install -r tests/requirements.txt
698699
- run: pip install pydantic-core --no-index --no-deps --find-links dist --force-reinstall
699700
- run: pytest --ignore=tests/test_docstrings.py

Cargo.lock

Lines changed: 51 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pydantic-core"
3-
version = "2.18.3"
3+
version = "2.19.0"
44
edition = "2021"
55
license = "MIT"
66
homepage = "https://github.com/pydantic/pydantic-core"
@@ -24,7 +24,7 @@ include = [
2424
"!tests/.pytest_cache",
2525
"!*.so",
2626
]
27-
rust-version = "1.76"
27+
rust-version = "1.75"
2828

2929
[dependencies]
3030
pyo3 = { version = "0.21.2", features = ["generate-import-lib", "num-bigint"] }
@@ -33,7 +33,7 @@ strum = { version = "0.25.0", features = ["derive"] }
3333
strum_macros = "0.26.1"
3434
serde_json = {version = "1.0.116", features = ["arbitrary_precision", "preserve_order"]}
3535
enum_dispatch = "0.3.13"
36-
serde = { version = "1.0.197", features = ["derive"] }
36+
serde = { version = "1.0.203", features = ["derive"] }
3737
speedate = "0.14.0"
3838
smallvec = "1.13.2"
3939
ahash = "0.8.10"
@@ -43,8 +43,8 @@ idna = "0.5.0"
4343
base64 = "0.21.7"
4444
num-bigint = "0.4.4"
4545
python3-dll-a = "0.2.7"
46-
uuid = "1.7.0"
47-
jiter = { version = "0.2.1", features = ["python"] }
46+
uuid = "1.8.0"
47+
jiter = { version = "0.4.1", features = ["python"] }
4848

4949
[lib]
5050
name = "_pydantic_core"

generate_self_schema.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
import decimal
1111
import importlib.util
1212
import re
13+
import sys
1314
from collections.abc import Callable
1415
from datetime import date, datetime, time, timedelta
1516
from pathlib import Path
16-
from typing import TYPE_CHECKING, Any, Dict, ForwardRef, List, Set, Type, Union
17+
from typing import TYPE_CHECKING, Any, Dict, ForwardRef, List, Pattern, Set, Type, Union
1718

1819
from typing_extensions import TypedDict, get_args, get_origin, is_typeddict
1920

@@ -46,7 +47,7 @@
4647
schema_ref_validator = {'type': 'definition-ref', 'schema_ref': 'root-schema'}
4748

4849

49-
def get_schema(obj: Any, definitions: dict[str, core_schema.CoreSchema]) -> core_schema.CoreSchema:
50+
def get_schema(obj: Any, definitions: dict[str, core_schema.CoreSchema]) -> core_schema.CoreSchema: # noqa: C901
5051
if isinstance(obj, str):
5152
return {'type': obj}
5253
elif obj in (datetime, timedelta, date, time, bool, int, float, str, decimal.Decimal):
@@ -81,6 +82,9 @@ def get_schema(obj: Any, definitions: dict[str, core_schema.CoreSchema]) -> core
8182
elif issubclass(origin, Type):
8283
# can't really use 'is-instance' since this is used for the class_ parameter of 'is-instance' validators
8384
return {'type': 'any'}
85+
elif origin in (Pattern, re.Pattern):
86+
# can't really use 'is-instance' easily with Pattern, so we use `any` as a placeholder for now
87+
return {'type': 'any'}
8488
else:
8589
# debug(obj)
8690
raise TypeError(f'Unknown type: {obj!r}')
@@ -189,16 +193,12 @@ def all_literal_values(type_: type[core_schema.Literal]) -> list[any]:
189193

190194

191195
def eval_forward_ref(type_: Any) -> Any:
192-
try:
193-
try:
194-
# Python 3.12+
195-
return type_._evaluate(core_schema.__dict__, None, type_params=set(), recursive_guard=set())
196-
except TypeError:
197-
# Python 3.9+
198-
return type_._evaluate(core_schema.__dict__, None, set())
199-
except TypeError:
200-
# for Python 3.8
196+
if sys.version_info < (3, 9):
201197
return type_._evaluate(core_schema.__dict__, None)
198+
elif sys.version_info < (3, 12, 4):
199+
return type_._evaluate(core_schema.__dict__, None, recursive_guard=set())
200+
else:
201+
return type_._evaluate(core_schema.__dict__, None, type_params=set(), recursive_guard=set())
202202

203203

204204
def main() -> None:

python/pydantic_core/_pydantic_core.pyi

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class SchemaValidator:
8989
*,
9090
strict: bool | None = None,
9191
from_attributes: bool | None = None,
92-
context: dict[str, Any] | None = None,
92+
context: Any | None = None,
9393
self_instance: Any | None = None,
9494
) -> Any:
9595
"""
@@ -119,7 +119,7 @@ class SchemaValidator:
119119
*,
120120
strict: bool | None = None,
121121
from_attributes: bool | None = None,
122-
context: dict[str, Any] | None = None,
122+
context: Any | None = None,
123123
self_instance: Any | None = None,
124124
) -> bool:
125125
"""
@@ -136,7 +136,7 @@ class SchemaValidator:
136136
input: str | bytes | bytearray,
137137
*,
138138
strict: bool | None = None,
139-
context: dict[str, Any] | None = None,
139+
context: Any | None = None,
140140
self_instance: Any | None = None,
141141
) -> Any:
142142
"""
@@ -163,9 +163,7 @@ class SchemaValidator:
163163
Returns:
164164
The validated Python object.
165165
"""
166-
def validate_strings(
167-
self, input: _StringInput, *, strict: bool | None = None, context: dict[str, Any] | None = None
168-
) -> Any:
166+
def validate_strings(self, input: _StringInput, *, strict: bool | None = None, context: Any | None = None) -> Any:
169167
"""
170168
Validate a string against the schema and return the validated Python object.
171169
@@ -194,7 +192,7 @@ class SchemaValidator:
194192
*,
195193
strict: bool | None = None,
196194
from_attributes: bool | None = None,
197-
context: dict[str, Any] | None = None,
195+
context: Any | None = None,
198196
) -> dict[str, Any] | tuple[dict[str, Any], dict[str, Any] | None, set[str]]:
199197
"""
200198
Validate an assignment to a field on a model.
@@ -267,7 +265,7 @@ class SchemaSerializer:
267265
warnings: bool | Literal['none', 'warn', 'error'] = True,
268266
fallback: Callable[[Any], Any] | None = None,
269267
serialize_as_any: bool = False,
270-
context: dict[str, Any] | None = None,
268+
context: Any | None = None,
271269
) -> Any:
272270
"""
273271
Serialize/marshal a Python object to a Python object including transforming and filtering data.
@@ -313,7 +311,7 @@ class SchemaSerializer:
313311
warnings: bool | Literal['none', 'warn', 'error'] = True,
314312
fallback: Callable[[Any], Any] | None = None,
315313
serialize_as_any: bool = False,
316-
context: dict[str, Any] | None = None,
314+
context: Any | None = None,
317315
) -> bytes:
318316
"""
319317
Serialize a Python object to JSON including transforming and filtering data.
@@ -355,11 +353,11 @@ def to_json(
355353
round_trip: bool = False,
356354
timedelta_mode: Literal['iso8601', 'float'] = 'iso8601',
357355
bytes_mode: Literal['utf8', 'base64'] = 'utf8',
358-
inf_nan_mode: Literal['null', 'constants'] = 'constants',
356+
inf_nan_mode: Literal['null', 'constants', 'strings'] = 'constants',
359357
serialize_unknown: bool = False,
360358
fallback: Callable[[Any], Any] | None = None,
361359
serialize_as_any: bool = False,
362-
context: dict[str, Any] | None = None,
360+
context: Any | None = None,
363361
) -> bytes:
364362
"""
365363
Serialize a Python object to JSON including transforming and filtering data.
@@ -376,7 +374,7 @@ def to_json(
376374
round_trip: Whether to enable serialization and validation round-trip support.
377375
timedelta_mode: How to serialize `timedelta` objects, either `'iso8601'` or `'float'`.
378376
bytes_mode: How to serialize `bytes` objects, either `'utf8'` or `'base64'`.
379-
inf_nan_mode: How to serialize `Infinity`, `-Infinity` and `NaN` values, either `'null'` or `'constants'`.
377+
inf_nan_mode: How to serialize `Infinity`, `-Infinity` and `NaN` values, either `'null'`, `'constants'`, or `'strings'`.
380378
serialize_unknown: Attempt to serialize unknown types, `str(value)` will be used, if that fails
381379
`"<Unserializable {value_type} object>"` will be used.
382380
fallback: A function to call when an unknown value is encountered,
@@ -430,11 +428,11 @@ def to_jsonable_python(
430428
round_trip: bool = False,
431429
timedelta_mode: Literal['iso8601', 'float'] = 'iso8601',
432430
bytes_mode: Literal['utf8', 'base64'] = 'utf8',
433-
inf_nan_mode: Literal['null', 'constants'] = 'constants',
431+
inf_nan_mode: Literal['null', 'constants', 'strings'] = 'constants',
434432
serialize_unknown: bool = False,
435433
fallback: Callable[[Any], Any] | None = None,
436434
serialize_as_any: bool = False,
437-
context: dict[str, Any] | None = None,
435+
context: Any | None = None,
438436
) -> Any:
439437
"""
440438
Serialize/marshal a Python object to a JSON-serializable Python object including transforming and filtering data.
@@ -451,7 +449,7 @@ def to_jsonable_python(
451449
round_trip: Whether to enable serialization and validation round-trip support.
452450
timedelta_mode: How to serialize `timedelta` objects, either `'iso8601'` or `'float'`.
453451
bytes_mode: How to serialize `bytes` objects, either `'utf8'` or `'base64'`.
454-
inf_nan_mode: How to serialize `Infinity`, `-Infinity` and `NaN` values, either `'null'` or `'constants'`.
452+
inf_nan_mode: How to serialize `Infinity`, `-Infinity` and `NaN` values, either `'null'`, `'constants'`, or `'strings'`.
455453
serialize_unknown: Attempt to serialize unknown types, `str(value)` will be used, if that fails
456454
`"<Unserializable {value_type} object>"` will be used.
457455
fallback: A function to call when an unknown value is encountered,

0 commit comments

Comments
 (0)