pydantic
Custom Pydantic types (v1.x).
- class yagni.pydantic.types.CaseInsensitiveEnum(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
>>> class Gender(CaseInsensitiveEnum): ... MALE = 'male' ... FEMALE = 'female' >>> Gender('mAlE') <Gender.MALE: 'male'> >>> Gender('FEMALE') <Gender.FEMALE: 'female'> >>> Gender('helicopter') Traceback (most recent call last): ... ValueError: 'helicopter' is not a valid Gender
- class yagni.pydantic.types.MBI(*args: Any, **kwargs: Any)
Medicare Beneficiary Identifier (MBI).
https://www.cms.gov/medicare/new-medicare-card/understanding-the-mbi-with-format.pdf
Implementation credits to https://stackoverflow.com/a/47683670/3455614
>>> import re >>> from pydantic import parse_obj_as >>> parse_obj_as(MBI, '1ax0Y67Dw34') '1AX0Y67DW34' >>> all(re.match(MBI.regex, mbi) for mbi in [ ... '1AX0Y67DW34', '4C56de7FG00', '9EN1EQ3TT59', '2H52CD7GQ83', '3U90VV3UV09', ... ]) True >>> any(re.match(MBI.regex, mbi) for mbi in ['0AX0Y67DW34', '4256DE7FG00']) False
- class yagni.pydantic.types.NonEmptyStr(*args: Any, **kwargs: Any)
Non-empty string in a shorthand form.
White space is stripped by default.
- class yagni.pydantic.types.SSN(*args: Any, **kwargs: Any)
10-digit US SSN with optional dashes.
Dashes are automatically removed during validation.
>>> from pydantic import parse_obj_as >>> parse_obj_as(SSN, '123456789') '123456789' >>> parse_obj_as(SSN, '1234-5-6789') '123456789'
- classmethod cleanup_ssn(value) str
Remove dashes.
- class yagni.pydantic.types.StringEnum(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
Sane enum that behaves like a string.
Can be safely used for JSON serialization. Convenient for API responses and storing in NoSQL or key-value databases.
>>> class Gender(str, Enum): ... MALE = 'male' ... FEMALE = 'female' >>> str(Gender.MALE) 'Gender.MALE'
>>> class Gender(StringEnum): ... MALE = 'male' ... FEMALE = 'female' >>> str(Gender.MALE) 'male'
>>> class Gender(StringEnum): ... MALE = 'male' ... FEMALE = 'female' >>> f'{Gender.MALE}' 'male'
- class yagni.pydantic.types.UTCDatetime
Datetime with UTC timezone.
Enforces UTC timezone and disallows naive timestamps.
>>> from pydantic import BaseModel >>> import pytz >>> class Message(BaseModel): ... text: str ... created: UTCDatetime >>> naive_str = '1991-08-24 10:00:00' >>> naive = datetime.fromisoformat(naive_str)
>>> Message(text='Do the barrel roll!', created=naive) Traceback (most recent call last): ... pydantic.error_wrappers.ValidationError: 1 validation error for Message created Naive timestamps are not allowed (type=value_error)
>>> Message(text='Do the barrel roll!', created=naive_str) Traceback (most recent call last): ... pydantic.error_wrappers.ValidationError: 1 validation error for Message created Naive timestamps are not allowed (type=value_error)
>>> Message(text='Батько наш Бандера!', created=naive.replace(tzinfo=pytz.timezone('Europe/Kyiv'))) Traceback (most recent call last): ... pydantic.error_wrappers.ValidationError: 1 validation error for Message created Timestamp must be in UTC timezone (type=value_error)
>>> Message(text='Батько наш Бандера!', created=f'{naive_str}+03:00') Traceback (most recent call last): ... pydantic.error_wrappers.ValidationError: 1 validation error for Message created Timestamp must be in UTC timezone (type=value_error)
>>> Message(text='Slava Ukraini!', created=naive.replace(tzinfo=timezone.utc)) Message(text='Slava Ukraini!', created=datetime.datetime(1991, 8, 24, 10, 0, tzinfo=datetime.timezone.utc))
>>> Message(text='Slava Ukraini!', created=f'{naive_str}+00:00') Message(text='Slava Ukraini!', created=datetime.datetime(1991, 8, 24, 10, 0, tzinfo=datetime.timezone.utc))
>>> Message(text='Slava Ukraini!', created=f'{naive_str}+00:00').json() '{"text": "Slava Ukraini!", "created": "1991-08-24T10:00:00+00:00"}'