zjowowen's picture
init space
079c32c
raw
history blame
2.89 kB
import re
from functools import wraps
from itertools import islice
from typing import Callable, Union, Pattern
from .base import Loader, ILoaderClass
STRING_PROCESSOR = Callable[[str], str]
def enum(*items, case_sensitive: bool = True) -> ILoaderClass:
"""
Overview:
Create an enum loader.
Arguments:
- items (:obj:`Iterable[str]`): The items.
- case_sensitive (:obj:`bool`): Whether case sensitive.
"""
def _case_sensitive(func: STRING_PROCESSOR) -> STRING_PROCESSOR:
if case_sensitive:
return func
else:
@wraps(func)
def _new_func(value: str) -> str:
return func(value).lower()
return _new_func
@_case_sensitive
def _item_process(value):
return str(value)
item_set = set([_item_process(item) for item in items])
def _load(value: str):
real_value = _item_process(value)
if real_value not in item_set:
raise ValueError('unknown enum value {value}'.format(value=repr(value)))
return real_value
return Loader(_load)
def _to_regexp(regexp) -> Pattern:
"""
Overview:
Convert regexp to re.Pattern.
Arguments:
- regexp (:obj:`Union[str, re.Pattern]`): The regexp.
"""
if isinstance(regexp, Pattern):
return regexp
elif isinstance(regexp, str):
return re.compile(regexp)
else:
raise TypeError(
'Regexp should be either str or re.Pattern but {actual} found.'.format(actual=repr(type(regexp).__name__))
)
def rematch(regexp: Union[str, Pattern]) -> ILoaderClass:
"""
Overview:
Create a rematch loader.
Arguments:
- regexp (:obj:`Union[str, re.Pattern]`): The regexp.
"""
regexp = _to_regexp(regexp)
def _load(value: str):
if not regexp.fullmatch(value):
raise ValueError(
'fully match with regexp {pattern} expected but {actual} found'.format(
pattern=repr(regexp.pattern),
actual=repr(value),
)
)
return value
return Loader(_load)
def regrep(regexp: Union[str, Pattern], group: int = 0) -> ILoaderClass:
"""
Overview:
Create a regrep loader.
Arguments:
- regexp (:obj:`Union[str, re.Pattern]`): The regexp.
- group (:obj:`int`): The group.
"""
regexp = _to_regexp(regexp)
def _load(value: str):
results = list(islice(regexp.finditer(value), 1))
if results:
return results[0][group]
else:
raise ValueError(
'fully match with regexp {pattern} expected but {actual} found'.format(
pattern=repr(regexp.pattern),
actual=repr(value),
)
)
return Loader(_load)