File size: 2,887 Bytes
079c32c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
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)
|