Add missing files

This commit is contained in:
Matt Davis
2023-10-19 20:59:50 -04:00
committed by Oz Tiram
parent 649a05842d
commit ab392a6404
2 changed files with 189 additions and 0 deletions
+124
View File
@@ -0,0 +1,124 @@
# coding: utf-8
"""
In round-trip mode the original tag needs to be preserved, but the tag
transformed based on the directives needs to be available as well.
A Tag that is created during loading has a handle and a suffix.
Not all objects loaded currently have a Tag, that .tag attribute can be None
A Tag that is created for dumping only (on an object loaded without a tag) has a suffix
only.
"""
from typing import Any, Dict, Optional, List, Union, Optional, Iterator # NOQA
tag_attrib = '_yaml_tag'
class Tag:
"""store original tag information for roundtripping"""
attrib = tag_attrib
def __init__(self, handle: Any = None, suffix: Any = None, handles: Any = None) -> None:
self.handle = handle
self.suffix = suffix
self.handles = handles
self._transform_type: Optional[bool] = None
def __repr__(self) -> str:
return f'{self.__class__.__name__}({self.trval!r})'
def __str__(self) -> str:
return f'{self.trval}'
def __hash__(self) -> int:
try:
return self._hash_id # type: ignore
except AttributeError:
self._hash_id = res = hash((self.handle, self.suffix))
return res
def __eq__(self, other: Any) -> bool:
# other should not be a string, but the serializer sometimes provides these
if isinstance(other, str):
return self.trval == other
return bool(self.trval == other.trval)
def startswith(self, x: str) -> bool:
if self.trval is not None:
return self.trval.startswith(x)
return False
@property
def trval(self) -> Optional[str]:
try:
return self._trval
except AttributeError:
pass
if self.handle is None:
self._trval: Optional[str] = self.uri_decoded_suffix
return self._trval
assert self._transform_type is not None
if not self._transform_type:
# the non-round-trip case
self._trval = self.handles[self.handle] + self.uri_decoded_suffix
return self._trval
# round-trip case
if self.handle == '!!' and self.suffix in (
'null',
'bool',
'int',
'float',
'binary',
'timestamp',
'omap',
'pairs',
'set',
'str',
'seq',
'map',
):
self._trval = self.handles[self.handle] + self.uri_decoded_suffix
else:
# self._trval = self.handle + self.suffix
self._trval = self.handles[self.handle] + self.uri_decoded_suffix
return self._trval
value = trval
@property
def uri_decoded_suffix(self) -> Optional[str]:
try:
return self._uri_decoded_suffix
except AttributeError:
pass
if self.suffix is None:
self._uri_decoded_suffix: Optional[str] = None
return None
res = ''
# don't have to check for scanner errors here
idx = 0
while idx < len(self.suffix):
ch = self.suffix[idx]
idx += 1
if ch != '%':
res += ch
else:
res += chr(int(self.suffix[idx : idx + 2], 16))
idx += 2
self._uri_decoded_suffix = res
return res
def select_transform(self, val: bool) -> None:
"""
val: False -> non-round-trip
True -> round-trip
"""
assert self._transform_type is None
self._transform_type = val
def check_handle(self) -> bool:
if self.handle is None:
return False
return self.handle not in self.handles
+65
View File
@@ -0,0 +1,65 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from typing import Any
from typing import TypeVar
WT = TypeVar("WT", bound="WrapperType")
if TYPE_CHECKING: # pragma: no cover
# Define _CustomList and _CustomDict as a workaround for:
# https://github.com/python/mypy/issues/11427
#
# According to this issue, the typeshed contains a "lie"
# (it adds MutableSequence to the ancestry of list and MutableMapping to
# the ancestry of dict) which completely messes with the type inference for
# Table, InlineTable, Array and Container.
#
# Importing from builtins is preferred over simple assignment, see issues:
# https://github.com/python/mypy/issues/8715
# https://github.com/python/mypy/issues/10068
from builtins import dict as _CustomDict # noqa: N812
from builtins import float as _CustomFloat # noqa: N812
from builtins import int as _CustomInt # noqa: N812
from builtins import list as _CustomList # noqa: N812
from typing import Callable
from typing import Concatenate
from typing import ParamSpec
from typing import Protocol
P = ParamSpec("P")
class WrapperType(Protocol):
def _new(self: WT, value: Any) -> WT:
...
else:
from collections.abc import MutableMapping
from collections.abc import MutableSequence
from numbers import Integral
from numbers import Real
class _CustomList(MutableSequence, list):
"""Adds MutableSequence mixin while pretending to be a builtin list"""
class _CustomDict(MutableMapping, dict):
"""Adds MutableMapping mixin while pretending to be a builtin dict"""
class _CustomInt(Integral, int):
"""Adds Integral mixin while pretending to be a builtin int"""
class _CustomFloat(Real, float):
"""Adds Real mixin while pretending to be a builtin float"""
def wrap_method(
original_method: Callable[Concatenate[WT, P], Any]
) -> Callable[Concatenate[WT, P], Any]:
def wrapper(self: WT, *args: P.args, **kwargs: P.kwargs) -> Any:
result = original_method(self, *args, **kwargs)
if result is NotImplemented:
return result
return self._new(result)
return wrapper