Spaces:
Sleeping
Sleeping
from typing import Optional, List, Tuple, Callable, Any | |
from .base import ILoaderClass, Loader, CAPTURE_EXCEPTIONS | |
from .exception import CompositeStructureError | |
from .types import method | |
COLLECTION_ERROR_ITEM = Tuple[int, Exception] | |
COLLECTION_ERRORS = List[COLLECTION_ERROR_ITEM] | |
class CollectionError(CompositeStructureError): | |
""" | |
Overview: | |
Collection error. | |
Interfaces: | |
``__init__``, ``errors`` | |
Properties: | |
``errors`` | |
""" | |
def __init__(self, errors: COLLECTION_ERRORS): | |
""" | |
Overview: | |
Initialize the CollectionError. | |
Arguments: | |
- errors (:obj:`COLLECTION_ERRORS`): The errors. | |
""" | |
self.__errors = list(errors or []) | |
CompositeStructureError.__init__( | |
self, '{count} error(s) found in collection.'.format(count=repr(list(self.__errors))) | |
) | |
def errors(self) -> COLLECTION_ERRORS: | |
""" | |
Overview: | |
Get the errors. | |
""" | |
return self.__errors | |
def collection(loader, type_back: bool = True) -> ILoaderClass: | |
""" | |
Overview: | |
Create a collection loader. | |
Arguments: | |
- loader (:obj:`ILoaderClass`): The loader. | |
- type_back (:obj:`bool`): Whether to convert the type back. | |
""" | |
loader = Loader(loader) | |
def _load(value): | |
_result = [] | |
_errors = [] | |
for index, item in enumerate(value): | |
try: | |
_return = loader.load(item) | |
except CAPTURE_EXCEPTIONS as err: | |
_errors.append((index, err)) | |
else: | |
_result.append(_return) | |
if _errors: | |
raise CollectionError(_errors) | |
if type_back: | |
_result = type(value)(_result) | |
return _result | |
return method('__iter__') & Loader(_load) | |
def tuple_(*loaders) -> ILoaderClass: | |
""" | |
Overview: | |
Create a tuple loader. | |
Arguments: | |
- loaders (:obj:`tuple`): The loaders. | |
""" | |
loaders = [Loader(loader) for loader in loaders] | |
def _load(value: tuple): | |
return tuple([loader(item) for loader, item in zip(loaders, value)]) | |
return tuple & length_is(len(loaders)) & Loader(_load) | |
def length(min_length: Optional[int] = None, max_length: Optional[int] = None) -> ILoaderClass: | |
""" | |
Overview: | |
Create a length loader. | |
Arguments: | |
- min_length (:obj:`int`): The minimum length. | |
- max_length (:obj:`int`): The maximum length. | |
""" | |
def _load(value): | |
_length = len(value) | |
if min_length is not None and _length < min_length: | |
raise ValueError( | |
'minimum length is {expect}, but {actual} found'.format(expect=repr(min_length), actual=repr(_length)) | |
) | |
if max_length is not None and _length > max_length: | |
raise ValueError( | |
'maximum length is {expect}, but {actual} found'.format(expect=repr(max_length), actual=repr(_length)) | |
) | |
return value | |
return method('__len__') & Loader(_load) | |
def length_is(length_: int) -> ILoaderClass: | |
""" | |
Overview: | |
Create a length loader. | |
Arguments: | |
- length_ (:obj:`int`): The length. | |
""" | |
return length(min_length=length_, max_length=length_) | |
def contains(content) -> ILoaderClass: | |
""" | |
Overview: | |
Create a contains loader. | |
Arguments: | |
- content (:obj:`Any`): The content. | |
""" | |
def _load(value): | |
if content not in value: | |
raise ValueError('{content} not found in value'.format(content=repr(content))) | |
return value | |
return method('__contains__') & Loader(_load) | |
def cofilter(checker: Callable[[Any], bool], type_back: bool = True) -> ILoaderClass: | |
""" | |
Overview: | |
Create a cofilter loader. | |
Arguments: | |
- checker (:obj:`Callable[[Any], bool]`): The checker. | |
- type_back (:obj:`bool`): Whether to convert the type back. | |
""" | |
def _load(value): | |
_result = [item for item in value if checker(item)] | |
if type_back: | |
_result = type(value)(_result) | |
return _result | |
return method('__iter__') & Loader(_load) | |
def tpselector(*indices) -> ILoaderClass: | |
""" | |
Overview: | |
Create a tuple selector loader. | |
Arguments: | |
- indices (:obj:`tuple`): The indices. | |
""" | |
def _load(value: tuple): | |
return tuple([value[index] for index in indices]) | |
return tuple & Loader(_load) | |