jamtur01's picture
Upload folder using huggingface_hub
9c6594c verified
"""Internal utilities for working with Pydantic types and data."""
from __future__ import annotations
import json
import sys
from contextlib import suppress
from typing import Any, Type
import pydantic
from pydantic import BaseModel, ValidationError
from typing_extensions import TypeAlias
PYTHON_VERSION = sys.version_info
pydantic_major, *_ = pydantic.VERSION.split(".")
IS_PYDANTIC_V2: bool = int(pydantic_major) >= 2
BaseModelType: TypeAlias = Type[BaseModel]
def gql_typename(cls: type[BaseModel]) -> str:
"""Get the GraphQL typename for a Pydantic model."""
if (field := cls.model_fields.get("typename__")) and (typename := field.default):
return typename
raise TypeError(f"Cannot extract GraphQL typename from: {cls.__qualname__!r}.")
if IS_PYDANTIC_V2:
import pydantic_core # pydantic_core is only installed by pydantic v2
def from_json(s: str) -> Any:
"""Quickly deserialize a JSON string to a Python object."""
return pydantic_core.from_json(s)
def to_json(v: Any) -> str:
"""Quickly serialize a (possibly Pydantic) object to a JSON string."""
return pydantic_core.to_json(v, by_alias=True, round_trip=True).decode("utf-8")
def pydantic_isinstance(
v: Any, classinfo: BaseModelType | tuple[BaseModelType, ...]
) -> bool:
"""Return True if the object could be parsed into the given Pydantic type.
This is like a more lenient version of `isinstance()` for use with Pydantic.
In Pydantic v2, should be fast since the underlying implementation is in Rust,
and it may be preferable over `try:...except ValidationError:...`.
See: https://docs.pydantic.dev/latest/api/pydantic_core/#pydantic_core.SchemaValidator.isinstance_python
"""
if isinstance(classinfo, tuple):
return any(
cls.__pydantic_validator__.isinstance_python(v) for cls in classinfo
)
cls = classinfo
return cls.__pydantic_validator__.isinstance_python(v)
else:
# Pydantic v1 fallback implementations.
# These may be noticeably slower, but their primary goal is to ensure
# compatibility with Pydantic v1 so long as we need to support it.
from pydantic.json import pydantic_encoder # Only valid in pydantic v1
def from_json(s: str) -> Any:
return json.loads(s)
def to_json(v: Any) -> str:
return json.dumps(v, default=pydantic_encoder)
def pydantic_isinstance(
v: Any, classinfo: BaseModelType | tuple[BaseModelType, ...]
) -> bool:
classes = classinfo if isinstance(classinfo, tuple) else (classinfo,)
for cls in classes:
with suppress(ValidationError):
cls.model_validate(v)
return True
return False