201 lines
4.0 KiB
Python
Executable File
201 lines
4.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from dataclasses import dataclass, field
|
|
from collections import Counter
|
|
import sys, re, os, enum, itertools
|
|
from functools import partial, partialmethod
|
|
from time import sleep
|
|
from subprocess import Popen, PIPE, DEVNULL
|
|
from operator import itemgetter
|
|
from defl import (
|
|
log,
|
|
cl,
|
|
Dath,
|
|
Undefined,
|
|
Null,
|
|
Assert,
|
|
Time,
|
|
Obj,
|
|
IterableType,
|
|
isIterableType,
|
|
Run,
|
|
checkType,
|
|
richReprAuto,
|
|
quoteSh,
|
|
CliError,
|
|
)
|
|
from defl._typing_ import *
|
|
from defl._typing_ import T, F, N, U
|
|
from defl._rich_ import *
|
|
from defl._pydantic_ import *
|
|
import defl
|
|
|
|
from defl.testing_ import Tester, testFail
|
|
from datetime import datetime
|
|
|
|
|
|
defl.log.setLevel('i')
|
|
tester = Tester(name=__file__)
|
|
|
|
|
|
@tester.add()
|
|
def test():
|
|
from pydantic import BaseModel, PositiveInt
|
|
from pydantic.dataclasses import dataclass as danticlass, Field as DantiField
|
|
from pydantic import Field, TypeAdapter
|
|
|
|
class User(BaseModel):
|
|
idd: int
|
|
name: str = 'John Doe'
|
|
signup_ts: datetime | None
|
|
tastes: dict[str, PositiveInt]
|
|
|
|
external_data = {
|
|
'idd': 123,
|
|
'signup_ts': '2019-06-01 12:22',
|
|
'tastes': {
|
|
'wine': 9,
|
|
b'cheese': 7,
|
|
'cabbage': '1',
|
|
},
|
|
}
|
|
user = User(**external_data)
|
|
print(user.idd)
|
|
print(user.model_dump())
|
|
|
|
|
|
@tester.add()
|
|
def test():
|
|
from pydantic import BaseModel, PositiveInt
|
|
from pydantic.dataclasses import dataclass as danticlass, Field as DantiField
|
|
from pydantic import Field, TypeAdapter
|
|
|
|
from typing_extensions import Self
|
|
|
|
@danticlass(slots=T, kw_only=T)
|
|
class A:
|
|
y: list = DantiField([]) # | okay for pydantic. it'll copy
|
|
z: float
|
|
na: float | N = N
|
|
Count: ClassVar[int] = 0
|
|
|
|
def __post_init__(_: Self) -> N:
|
|
_.y.append(A.Count)
|
|
A.Count += 1
|
|
|
|
a1 = A(z=2)
|
|
a2 = A(z=2.1)
|
|
print(a1)
|
|
print(a2)
|
|
assert id(a1.y) != id(a2.y)
|
|
assert a1.y != a2.y
|
|
|
|
print(TypeAdapter(A).json_schema())
|
|
print(TypeAdapter(A).dump_json(a1))
|
|
print(TypeAdapter(A).dump_python(a1))
|
|
|
|
|
|
@tester.add()
|
|
def test():
|
|
@dantDC()
|
|
class A:
|
|
y: list[int] = DantField([]) # | okay for pydantic. it'll copy
|
|
z: float
|
|
na: float | N = N
|
|
Count: ClassVar[int] = 0
|
|
|
|
def __post_init__(_) -> N:
|
|
_.y.append(A.Count)
|
|
A.Count += 1
|
|
|
|
a1 = A(z=2)
|
|
a2 = A(z=2.1)
|
|
print(a1)
|
|
print(a2)
|
|
assert id(a1.y) != id(a2.y)
|
|
assert a1.y != a2.y
|
|
|
|
with testFail(DantValidationError):
|
|
a1.y = 1
|
|
with testFail(DantValidationError):
|
|
a1.y = ['a']
|
|
|
|
a1.y = [3]
|
|
|
|
print(DantTypeAdapter(A).json_schema())
|
|
print(DantTypeAdapter(A).dump_json(a1))
|
|
print(DantTypeAdapter(A).dump_python(a1))
|
|
|
|
assert not hasattr(a1, '__dict__')
|
|
assert hasattr(a1, '__slots__')
|
|
|
|
|
|
@tester.add()
|
|
def test():
|
|
@dantClass()
|
|
class A:
|
|
y: list[tuple[list[dict[float, str]]]] = DantField(kw_only=F)
|
|
|
|
a1 = A([[[{1: b'cat'}]]])
|
|
|
|
with testFail(DantValidationError):
|
|
a1 = A([[[{'x': b'cat'}]]])
|
|
|
|
|
|
@tester.add()
|
|
def test():
|
|
@dantClass()
|
|
class A:
|
|
y: int
|
|
|
|
@dantClass()
|
|
class B:
|
|
y: list[A]
|
|
|
|
a1 = B(y=[A(y=1), A(y=2)])
|
|
print(a1)
|
|
|
|
|
|
@tester.add()
|
|
def test():
|
|
@dantCall
|
|
def cat(a: int, b: list[float], c: str) -> tuple[int, list[float], str]:
|
|
return (a, b, c)
|
|
|
|
r = cat(a=1, b=[1], c='cat')
|
|
print(r)
|
|
|
|
with testFail(DantValidationError):
|
|
cat(a=1, b=[1], c=1)
|
|
|
|
@dantCall
|
|
def cat() -> float:
|
|
return 1
|
|
|
|
r = cat()
|
|
print(r)
|
|
|
|
@dantCall
|
|
def cat() -> str:
|
|
return 1.1
|
|
|
|
with testFail(DantValidationError):
|
|
cat()
|
|
|
|
|
|
@tester.add()
|
|
def test():
|
|
from pydantic import ConfigDict
|
|
from pydantic.dataclasses import dataclass
|
|
|
|
class MyClass:
|
|
pass
|
|
|
|
@dataclass(config=ConfigDict(arbitrary_types_allowed=True))
|
|
class MyPydanticDataclass:
|
|
a: MyClass
|
|
|
|
|
|
log.info(tester.run())
|
|
tester.exitWithStatus()
|