File: test_nullable.py

package info (click to toggle)
pydantic-core 2.37.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,784 kB
  • sloc: python: 34,800; javascript: 211; makefile: 126
file content (66 lines) | stat: -rw-r--r-- 1,938 bytes parent folder | download
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
import platform
import weakref

import pytest

from pydantic_core import SchemaValidator, ValidationError, core_schema

from ..conftest import assert_gc


def test_nullable():
    v = SchemaValidator(core_schema.nullable_schema(schema=core_schema.int_schema()))
    assert v.validate_python(None) is None
    assert v.validate_python(1) == 1
    assert v.validate_python('123') == 123
    with pytest.raises(ValidationError) as exc_info:
        v.validate_python('hello')
    assert exc_info.value.errors(include_url=False) == [
        {
            'type': 'int_parsing',
            'loc': (),
            'msg': 'Input should be a valid integer, unable to parse string as an integer',
            'input': 'hello',
        }
    ]


def test_union_nullable_bool_int():
    v = SchemaValidator(
        core_schema.union_schema(
            choices=[
                core_schema.nullable_schema(schema=core_schema.bool_schema()),
                core_schema.nullable_schema(schema=core_schema.int_schema()),
            ]
        )
    )
    assert v.validate_python(None) is None
    assert v.validate_python(True) is True
    assert v.validate_python(1) == 1


@pytest.mark.xfail(
    condition=platform.python_implementation() == 'PyPy', reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
)
def test_leak_nullable():
    def fn():
        def validate(v, info):
            return v

        schema = core_schema.with_info_plain_validator_function(validate)
        schema = core_schema.nullable_schema(schema)

        # If any of the Rust validators don't implement traversal properly,
        # there will be an undetectable cycle created by this assignment
        # which will keep Defaulted alive
        validate.__pydantic_validator__ = SchemaValidator(schema)

        return validate

    cycle = fn()
    ref = weakref.ref(cycle)
    assert ref() is not None

    del cycle

    assert_gc(lambda: ref() is None)