mirror of
https://github.com/meta-llama/llama-stack.git
synced 2025-07-27 06:28:50 +00:00
feat: use XDG directory standards
Signed-off-by: Mustafa Elbehery <melbeher@redhat.com>
This commit is contained in:
parent
9736f096f6
commit
407c3e3bad
50 changed files with 5611 additions and 508 deletions
|
@ -20,19 +20,14 @@ import ipaddress
|
|||
import sys
|
||||
import typing
|
||||
import uuid
|
||||
from collections.abc import Callable
|
||||
from types import ModuleType
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Generic,
|
||||
List,
|
||||
Literal,
|
||||
NamedTuple,
|
||||
Optional,
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
|
@ -70,7 +65,7 @@ V = TypeVar("V")
|
|||
class Deserializer(abc.ABC, Generic[T]):
|
||||
"Parses a JSON value into a Python type."
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
"""
|
||||
Creates auxiliary parsers that this parser is depending on.
|
||||
|
||||
|
@ -203,19 +198,19 @@ class IPv6Deserializer(Deserializer[ipaddress.IPv6Address]):
|
|||
return ipaddress.IPv6Address(data)
|
||||
|
||||
|
||||
class ListDeserializer(Deserializer[List[T]]):
|
||||
class ListDeserializer(Deserializer[list[T]]):
|
||||
"Recursively de-serializes a JSON array into a Python `list`."
|
||||
|
||||
item_type: Type[T]
|
||||
item_type: type[T]
|
||||
item_parser: Deserializer
|
||||
|
||||
def __init__(self, item_type: Type[T]) -> None:
|
||||
def __init__(self, item_type: type[T]) -> None:
|
||||
self.item_type = item_type
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
self.item_parser = _get_deserializer(self.item_type, context)
|
||||
|
||||
def parse(self, data: JsonType) -> List[T]:
|
||||
def parse(self, data: JsonType) -> list[T]:
|
||||
if not isinstance(data, list):
|
||||
type_name = python_type_to_str(self.item_type)
|
||||
raise JsonTypeError(f"type `List[{type_name}]` expects JSON `array` data but instead received: {data}")
|
||||
|
@ -223,19 +218,19 @@ class ListDeserializer(Deserializer[List[T]]):
|
|||
return [self.item_parser.parse(item) for item in data]
|
||||
|
||||
|
||||
class DictDeserializer(Deserializer[Dict[K, V]]):
|
||||
class DictDeserializer(Deserializer[dict[K, V]]):
|
||||
"Recursively de-serializes a JSON object into a Python `dict`."
|
||||
|
||||
key_type: Type[K]
|
||||
value_type: Type[V]
|
||||
key_type: type[K]
|
||||
value_type: type[V]
|
||||
value_parser: Deserializer[V]
|
||||
|
||||
def __init__(self, key_type: Type[K], value_type: Type[V]) -> None:
|
||||
def __init__(self, key_type: type[K], value_type: type[V]) -> None:
|
||||
self.key_type = key_type
|
||||
self.value_type = value_type
|
||||
self._check_key_type()
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
self.value_parser = _get_deserializer(self.value_type, context)
|
||||
|
||||
def _check_key_type(self) -> None:
|
||||
|
@ -264,48 +259,48 @@ class DictDeserializer(Deserializer[Dict[K, V]]):
|
|||
value_type_name = python_type_to_str(self.value_type)
|
||||
return f"Dict[{key_type_name}, {value_type_name}]"
|
||||
|
||||
def parse(self, data: JsonType) -> Dict[K, V]:
|
||||
def parse(self, data: JsonType) -> dict[K, V]:
|
||||
if not isinstance(data, dict):
|
||||
raise JsonTypeError(
|
||||
f"`type `{self.container_type}` expects JSON `object` data but instead received: {data}"
|
||||
)
|
||||
|
||||
return dict(
|
||||
(self.key_type(key), self.value_parser.parse(value)) # type: ignore[call-arg]
|
||||
return {
|
||||
self.key_type(key): self.value_parser.parse(value) # type: ignore[call-arg]
|
||||
for key, value in data.items()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
class SetDeserializer(Deserializer[Set[T]]):
|
||||
class SetDeserializer(Deserializer[set[T]]):
|
||||
"Recursively de-serializes a JSON list into a Python `set`."
|
||||
|
||||
member_type: Type[T]
|
||||
member_type: type[T]
|
||||
member_parser: Deserializer
|
||||
|
||||
def __init__(self, member_type: Type[T]) -> None:
|
||||
def __init__(self, member_type: type[T]) -> None:
|
||||
self.member_type = member_type
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
self.member_parser = _get_deserializer(self.member_type, context)
|
||||
|
||||
def parse(self, data: JsonType) -> Set[T]:
|
||||
def parse(self, data: JsonType) -> set[T]:
|
||||
if not isinstance(data, list):
|
||||
type_name = python_type_to_str(self.member_type)
|
||||
raise JsonTypeError(f"type `Set[{type_name}]` expects JSON `array` data but instead received: {data}")
|
||||
|
||||
return set(self.member_parser.parse(item) for item in data)
|
||||
return {self.member_parser.parse(item) for item in data}
|
||||
|
||||
|
||||
class TupleDeserializer(Deserializer[Tuple[Any, ...]]):
|
||||
class TupleDeserializer(Deserializer[tuple[Any, ...]]):
|
||||
"Recursively de-serializes a JSON list into a Python `tuple`."
|
||||
|
||||
item_types: Tuple[Type[Any], ...]
|
||||
item_parsers: Tuple[Deserializer[Any], ...]
|
||||
item_types: tuple[type[Any], ...]
|
||||
item_parsers: tuple[Deserializer[Any], ...]
|
||||
|
||||
def __init__(self, item_types: Tuple[Type[Any], ...]) -> None:
|
||||
def __init__(self, item_types: tuple[type[Any], ...]) -> None:
|
||||
self.item_types = item_types
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
self.item_parsers = tuple(_get_deserializer(item_type, context) for item_type in self.item_types)
|
||||
|
||||
@property
|
||||
|
@ -313,7 +308,7 @@ class TupleDeserializer(Deserializer[Tuple[Any, ...]]):
|
|||
type_names = ", ".join(python_type_to_str(item_type) for item_type in self.item_types)
|
||||
return f"Tuple[{type_names}]"
|
||||
|
||||
def parse(self, data: JsonType) -> Tuple[Any, ...]:
|
||||
def parse(self, data: JsonType) -> tuple[Any, ...]:
|
||||
if not isinstance(data, list) or len(data) != len(self.item_parsers):
|
||||
if not isinstance(data, list):
|
||||
raise JsonTypeError(
|
||||
|
@ -331,13 +326,13 @@ class TupleDeserializer(Deserializer[Tuple[Any, ...]]):
|
|||
class UnionDeserializer(Deserializer):
|
||||
"De-serializes a JSON value (of any type) into a Python union type."
|
||||
|
||||
member_types: Tuple[type, ...]
|
||||
member_parsers: Tuple[Deserializer, ...]
|
||||
member_types: tuple[type, ...]
|
||||
member_parsers: tuple[Deserializer, ...]
|
||||
|
||||
def __init__(self, member_types: Tuple[type, ...]) -> None:
|
||||
def __init__(self, member_types: tuple[type, ...]) -> None:
|
||||
self.member_types = member_types
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
self.member_parsers = tuple(_get_deserializer(member_type, context) for member_type in self.member_types)
|
||||
|
||||
def parse(self, data: JsonType) -> Any:
|
||||
|
@ -354,15 +349,15 @@ class UnionDeserializer(Deserializer):
|
|||
raise JsonKeyError(f"type `Union[{type_names}]` could not be instantiated from: {data}")
|
||||
|
||||
|
||||
def get_literal_properties(typ: type) -> Set[str]:
|
||||
def get_literal_properties(typ: type) -> set[str]:
|
||||
"Returns the names of all properties in a class that are of a literal type."
|
||||
|
||||
return set(
|
||||
return {
|
||||
property_name for property_name, property_type in get_class_properties(typ) if is_type_literal(property_type)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
def get_discriminating_properties(types: Tuple[type, ...]) -> Set[str]:
|
||||
def get_discriminating_properties(types: tuple[type, ...]) -> set[str]:
|
||||
"Returns a set of properties with literal type that are common across all specified classes."
|
||||
|
||||
if not types or not all(isinstance(typ, type) for typ in types):
|
||||
|
@ -378,15 +373,15 @@ def get_discriminating_properties(types: Tuple[type, ...]) -> Set[str]:
|
|||
class TaggedUnionDeserializer(Deserializer):
|
||||
"De-serializes a JSON value with one or more disambiguating properties into a Python union type."
|
||||
|
||||
member_types: Tuple[type, ...]
|
||||
disambiguating_properties: Set[str]
|
||||
member_parsers: Dict[Tuple[str, Any], Deserializer]
|
||||
member_types: tuple[type, ...]
|
||||
disambiguating_properties: set[str]
|
||||
member_parsers: dict[tuple[str, Any], Deserializer]
|
||||
|
||||
def __init__(self, member_types: Tuple[type, ...]) -> None:
|
||||
def __init__(self, member_types: tuple[type, ...]) -> None:
|
||||
self.member_types = member_types
|
||||
self.disambiguating_properties = get_discriminating_properties(member_types)
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
self.member_parsers = {}
|
||||
for member_type in self.member_types:
|
||||
for property_name in self.disambiguating_properties:
|
||||
|
@ -435,13 +430,13 @@ class TaggedUnionDeserializer(Deserializer):
|
|||
class LiteralDeserializer(Deserializer):
|
||||
"De-serializes a JSON value into a Python literal type."
|
||||
|
||||
values: Tuple[Any, ...]
|
||||
values: tuple[Any, ...]
|
||||
parser: Deserializer
|
||||
|
||||
def __init__(self, values: Tuple[Any, ...]) -> None:
|
||||
def __init__(self, values: tuple[Any, ...]) -> None:
|
||||
self.values = values
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
literal_type_tuple = tuple(type(value) for value in self.values)
|
||||
literal_type_set = set(literal_type_tuple)
|
||||
if len(literal_type_set) != 1:
|
||||
|
@ -464,9 +459,9 @@ class LiteralDeserializer(Deserializer):
|
|||
class EnumDeserializer(Deserializer[E]):
|
||||
"Returns an enumeration instance based on the enumeration value read from a JSON value."
|
||||
|
||||
enum_type: Type[E]
|
||||
enum_type: type[E]
|
||||
|
||||
def __init__(self, enum_type: Type[E]) -> None:
|
||||
def __init__(self, enum_type: type[E]) -> None:
|
||||
self.enum_type = enum_type
|
||||
|
||||
def parse(self, data: JsonType) -> E:
|
||||
|
@ -504,13 +499,13 @@ class FieldDeserializer(abc.ABC, Generic[T, R]):
|
|||
self.parser = parser
|
||||
|
||||
@abc.abstractmethod
|
||||
def parse_field(self, data: Dict[str, JsonType]) -> R: ...
|
||||
def parse_field(self, data: dict[str, JsonType]) -> R: ...
|
||||
|
||||
|
||||
class RequiredFieldDeserializer(FieldDeserializer[T, T]):
|
||||
"Deserializes a JSON property into a mandatory Python object field."
|
||||
|
||||
def parse_field(self, data: Dict[str, JsonType]) -> T:
|
||||
def parse_field(self, data: dict[str, JsonType]) -> T:
|
||||
if self.property_name not in data:
|
||||
raise JsonKeyError(f"missing required property `{self.property_name}` from JSON object: {data}")
|
||||
|
||||
|
@ -520,7 +515,7 @@ class RequiredFieldDeserializer(FieldDeserializer[T, T]):
|
|||
class OptionalFieldDeserializer(FieldDeserializer[T, Optional[T]]):
|
||||
"Deserializes a JSON property into an optional Python object field with a default value of `None`."
|
||||
|
||||
def parse_field(self, data: Dict[str, JsonType]) -> Optional[T]:
|
||||
def parse_field(self, data: dict[str, JsonType]) -> T | None:
|
||||
value = data.get(self.property_name)
|
||||
if value is not None:
|
||||
return self.parser.parse(value)
|
||||
|
@ -543,7 +538,7 @@ class DefaultFieldDeserializer(FieldDeserializer[T, T]):
|
|||
super().__init__(property_name, field_name, parser)
|
||||
self.default_value = default_value
|
||||
|
||||
def parse_field(self, data: Dict[str, JsonType]) -> T:
|
||||
def parse_field(self, data: dict[str, JsonType]) -> T:
|
||||
value = data.get(self.property_name)
|
||||
if value is not None:
|
||||
return self.parser.parse(value)
|
||||
|
@ -566,7 +561,7 @@ class DefaultFactoryFieldDeserializer(FieldDeserializer[T, T]):
|
|||
super().__init__(property_name, field_name, parser)
|
||||
self.default_factory = default_factory
|
||||
|
||||
def parse_field(self, data: Dict[str, JsonType]) -> T:
|
||||
def parse_field(self, data: dict[str, JsonType]) -> T:
|
||||
value = data.get(self.property_name)
|
||||
if value is not None:
|
||||
return self.parser.parse(value)
|
||||
|
@ -578,22 +573,22 @@ class ClassDeserializer(Deserializer[T]):
|
|||
"Base class for de-serializing class-like types such as data classes, named tuples and regular classes."
|
||||
|
||||
class_type: type
|
||||
property_parsers: List[FieldDeserializer]
|
||||
property_fields: Set[str]
|
||||
property_parsers: list[FieldDeserializer]
|
||||
property_fields: set[str]
|
||||
|
||||
def __init__(self, class_type: Type[T]) -> None:
|
||||
def __init__(self, class_type: type[T]) -> None:
|
||||
self.class_type = class_type
|
||||
|
||||
def assign(self, property_parsers: List[FieldDeserializer]) -> None:
|
||||
def assign(self, property_parsers: list[FieldDeserializer]) -> None:
|
||||
self.property_parsers = property_parsers
|
||||
self.property_fields = set(property_parser.property_name for property_parser in property_parsers)
|
||||
self.property_fields = {property_parser.property_name for property_parser in property_parsers}
|
||||
|
||||
def parse(self, data: JsonType) -> T:
|
||||
if not isinstance(data, dict):
|
||||
type_name = python_type_to_str(self.class_type)
|
||||
raise JsonTypeError(f"`type `{type_name}` expects JSON `object` data but instead received: {data}")
|
||||
|
||||
object_data: Dict[str, JsonType] = typing.cast(Dict[str, JsonType], data)
|
||||
object_data: dict[str, JsonType] = typing.cast(dict[str, JsonType], data)
|
||||
|
||||
field_values = {}
|
||||
for property_parser in self.property_parsers:
|
||||
|
@ -619,8 +614,8 @@ class ClassDeserializer(Deserializer[T]):
|
|||
class NamedTupleDeserializer(ClassDeserializer[NamedTuple]):
|
||||
"De-serializes a named tuple from a JSON `object`."
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
property_parsers: List[FieldDeserializer] = [
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
property_parsers: list[FieldDeserializer] = [
|
||||
RequiredFieldDeserializer(field_name, field_name, _get_deserializer(field_type, context))
|
||||
for field_name, field_type in get_resolved_hints(self.class_type).items()
|
||||
]
|
||||
|
@ -634,13 +629,13 @@ class NamedTupleDeserializer(ClassDeserializer[NamedTuple]):
|
|||
class DataclassDeserializer(ClassDeserializer[T]):
|
||||
"De-serializes a data class from a JSON `object`."
|
||||
|
||||
def __init__(self, class_type: Type[T]) -> None:
|
||||
def __init__(self, class_type: type[T]) -> None:
|
||||
if not dataclasses.is_dataclass(class_type):
|
||||
raise TypeError("expected: data-class type")
|
||||
super().__init__(class_type) # type: ignore[arg-type]
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
property_parsers: List[FieldDeserializer] = []
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
property_parsers: list[FieldDeserializer] = []
|
||||
resolved_hints = get_resolved_hints(self.class_type)
|
||||
for field in dataclasses.fields(self.class_type):
|
||||
field_type = resolved_hints[field.name]
|
||||
|
@ -651,7 +646,7 @@ class DataclassDeserializer(ClassDeserializer[T]):
|
|||
has_default_factory = field.default_factory is not dataclasses.MISSING
|
||||
|
||||
if is_optional:
|
||||
required_type: Type[T] = unwrap_optional_type(field_type)
|
||||
required_type: type[T] = unwrap_optional_type(field_type)
|
||||
else:
|
||||
required_type = field_type
|
||||
|
||||
|
@ -691,15 +686,15 @@ class FrozenDataclassDeserializer(DataclassDeserializer[T]):
|
|||
class TypedClassDeserializer(ClassDeserializer[T]):
|
||||
"De-serializes a class with type annotations from a JSON `object` by iterating over class properties."
|
||||
|
||||
def build(self, context: Optional[ModuleType]) -> None:
|
||||
property_parsers: List[FieldDeserializer] = []
|
||||
def build(self, context: ModuleType | None) -> None:
|
||||
property_parsers: list[FieldDeserializer] = []
|
||||
for field_name, field_type in get_resolved_hints(self.class_type).items():
|
||||
property_name = python_field_to_json_property(field_name, field_type)
|
||||
|
||||
is_optional = is_type_optional(field_type)
|
||||
|
||||
if is_optional:
|
||||
required_type: Type[T] = unwrap_optional_type(field_type)
|
||||
required_type: type[T] = unwrap_optional_type(field_type)
|
||||
else:
|
||||
required_type = field_type
|
||||
|
||||
|
@ -715,7 +710,7 @@ class TypedClassDeserializer(ClassDeserializer[T]):
|
|||
super().assign(property_parsers)
|
||||
|
||||
|
||||
def create_deserializer(typ: TypeLike, context: Optional[ModuleType] = None) -> Deserializer:
|
||||
def create_deserializer(typ: TypeLike, context: ModuleType | None = None) -> Deserializer:
|
||||
"""
|
||||
Creates a de-serializer engine to produce a Python object from an object obtained from a JSON string.
|
||||
|
||||
|
@ -741,15 +736,15 @@ def create_deserializer(typ: TypeLike, context: Optional[ModuleType] = None) ->
|
|||
return _get_deserializer(typ, context)
|
||||
|
||||
|
||||
_CACHE: Dict[Tuple[str, str], Deserializer] = {}
|
||||
_CACHE: dict[tuple[str, str], Deserializer] = {}
|
||||
|
||||
|
||||
def _get_deserializer(typ: TypeLike, context: Optional[ModuleType]) -> Deserializer:
|
||||
def _get_deserializer(typ: TypeLike, context: ModuleType | None) -> Deserializer:
|
||||
"Creates or re-uses a de-serializer engine to parse an object obtained from a JSON string."
|
||||
|
||||
cache_key = None
|
||||
|
||||
if isinstance(typ, (str, typing.ForwardRef)):
|
||||
if isinstance(typ, str | typing.ForwardRef):
|
||||
if context is None:
|
||||
raise TypeError(f"missing context for evaluating type: {typ}")
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue