forked from pydantic/pydantic-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_garbage_collection.py
More file actions
116 lines (86 loc) · 3.61 KB
/
test_garbage_collection.py
File metadata and controls
116 lines (86 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import platform
import sys
from collections.abc import Iterable
from typing import Any
from weakref import WeakValueDictionary
import pytest
from pydantic_core import SchemaSerializer, SchemaValidator, core_schema
from .conftest import assert_gc, is_free_threaded
GC_TEST_SCHEMA_INNER = core_schema.definitions_schema(
core_schema.definition_reference_schema(schema_ref='model'),
[
core_schema.typed_dict_schema(
{'x': core_schema.typed_dict_field(core_schema.definition_reference_schema(schema_ref='model'))},
ref='model',
)
],
)
@pytest.mark.xfail(is_free_threaded and sys.version_info < (3, 14), reason='GC leaks on free-threaded (<3.14)')
@pytest.mark.xfail(
condition=platform.python_implementation() == 'PyPy', reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
)
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM', reason='Cannot reliably trigger GC on GraalPy')
def test_gc_schema_serializer() -> None:
# test for https://github.com/pydantic/pydantic/issues/5136
class BaseModel:
__schema__: SchemaSerializer
def __init_subclass__(cls) -> None:
cls.__schema__ = SchemaSerializer(
core_schema.model_schema(cls, GC_TEST_SCHEMA_INNER), config={'ser_json_timedelta': 'float'}
)
cache: WeakValueDictionary[int, Any] = WeakValueDictionary()
for _ in range(10_000):
class MyModel(BaseModel):
pass
cache[id(MyModel)] = MyModel
del MyModel
assert_gc(lambda: len(cache) == 0)
@pytest.mark.xfail(is_free_threaded and sys.version_info < (3, 14), reason='GC leaks on free-threaded (<3.14)')
@pytest.mark.xfail(
condition=platform.python_implementation() == 'PyPy', reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
)
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM', reason='Cannot reliably trigger GC on GraalPy')
def test_gc_schema_validator() -> None:
# test for https://github.com/pydantic/pydantic/issues/5136
class BaseModel:
__validator__: SchemaValidator
def __init_subclass__(cls) -> None:
cls.__validator__ = SchemaValidator(
schema=core_schema.model_schema(cls, GC_TEST_SCHEMA_INNER),
config=core_schema.CoreConfig(extra_fields_behavior='allow'),
)
cache: WeakValueDictionary[int, Any] = WeakValueDictionary()
for _ in range(10_000):
class MyModel(BaseModel):
pass
cache[id(MyModel)] = MyModel
del MyModel
assert_gc(lambda: len(cache) == 0)
@pytest.mark.xfail(
condition=platform.python_implementation() == 'PyPy', reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
)
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM', reason='Cannot reliably trigger GC on GraalPy')
def test_gc_validator_iterator() -> None:
# test for https://github.com/pydantic/pydantic/issues/9243
class MyModel:
iter: Iterable[int]
v = SchemaValidator(
core_schema.model_schema(
MyModel,
core_schema.model_fields_schema(
{'iter': core_schema.model_field(core_schema.generator_schema(core_schema.int_schema()))}
),
)
)
class MyIterable:
def __iter__(self):
return self
def __next__(self):
raise StopIteration()
cache: WeakValueDictionary[int, Any] = WeakValueDictionary()
for _ in range(10_000):
iterable = MyIterable()
cache[id(iterable)] = iterable
v.validate_python({'iter': iterable})
del iterable
assert_gc(lambda: len(cache) == 0)