diff options
| author | 2020-01-26 00:06:47 +0000 | |
|---|---|---|
| committer | 2020-01-26 00:06:47 +0000 | |
| commit | 1d1e2d95a965007d5a82e6d247ec205ff7256b2f (patch) | |
| tree | 2061544908ff85a8b5e12e5e43de841a2ffddf61 /src/utils | |
| parent | update !ignore to use command specs (diff) | |
| signature | ||
split utils/parse.py in to multiple files
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/parse/__init__.py (renamed from src/utils/parse.py) | 125 | ||||
| -rw-r--r-- | src/utils/parse/spec.py | 113 | ||||
| -rw-r--r-- | src/utils/parse/time.py | 9 |
3 files changed, 127 insertions, 120 deletions
diff --git a/src/utils/parse.py b/src/utils/parse/__init__.py index 689c5f87..bc3b8647 100644 --- a/src/utils/parse.py +++ b/src/utils/parse/__init__.py @@ -1,5 +1,8 @@ -import decimal, enum, io, typing -from . import datetime, errors +import decimal, io, typing +from src.utils import datetime, errors + +from .time import duration +from .spec import * COMMENT_TYPES = ["#", "//"] def hashflags(filename: str @@ -110,13 +113,6 @@ def parse_number(s: str) -> str: raise ValueError("Unknown unit '%s' given to parse_number" % unit) return str(number) -def duration(s: str): - if s[0] == "+": - duration = datetime.from_pretty_time(s[1:]) - if not duration == None: - return duration - return None - def format_tokens(s: str, names: typing.List[str], sigil: str="$" ) -> typing.List[typing.Tuple[int, str]]: names = names.copy() @@ -152,114 +148,3 @@ def format_token_replace(s: str, vars: typing.Dict[str, str], for i, token in tokens: s = s[:i] + vars[token.replace(sigil, "", 1)] + s[i+len(token):] return s - -class SpecArgumentContext(enum.IntFlag): - CHANNEL = 1 - PRIVATE = 2 - ALL = 3 - -class SpecArgumentType(object): - context = SpecArgumentContext.ALL - - def __init__(self, type_name: str, name: typing.Optional[str], exported: str): - self.type = type_name - self._name = name - self.exported = exported - - def name(self) -> typing.Optional[str]: - return self._name - def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: - return None, -1 - def error(self) -> typing.Optional[str]: - return None - -class SpecArgumentTypeWord(SpecArgumentType): - def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: - if args: - return args[0], 1 - return None, 1 -class SpecArgumentTypeWordLower(SpecArgumentTypeWord): - def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: - out = SpecArgumentTypeWord.simple(self, args) - if out[0]: - return out[0].lower(), out[1] - return out - -class SpecArgumentTypeString(SpecArgumentType): - def name(self): - return "%s ..." % SpecArgumentType.name(self) - def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: - return " ".join(args), len(args) - -class SpecArgumentTypeDuration(SpecArgumentType): - def name(self): - return "+%s" % (SpecArgumentType.name(self) or "duration") - def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: - if args: - return duration(args[0]), 1 - return None, 1 - def error(self) -> typing.Optional[str]: - return "Invalid timeframe" - -class SpecArgumentPrivateType(SpecArgumentType): - context = SpecArgumentContext.PRIVATE - -SPEC_ARGUMENT_TYPES = { - "word": SpecArgumentTypeWord, - "wordlower": SpecArgumentTypeWordLower, - "string": SpecArgumentTypeString, - "duration": SpecArgumentTypeDuration -} - -class SpecArgument(object): - def __init__(self, optional: bool, types: typing.List[SpecArgumentType]): - self.optional = optional - self.types = types - -def argument_spec(spec: str) -> typing.List[SpecArgument]: - out: typing.List[SpecArgument] = [] - for spec_argument in spec.split(" "): - optional = spec_argument[0] == "?" - - argument_types: typing.List[SpecArgumentType] = [] - for argument_type in spec_argument[1:].split("|"): - exported = "" - if "~" in argument_type: - exported = argument_type.split("~", 1)[1] - argument_type = argument_type.replace("~", "", 1) - - argument_type_name: typing.Optional[str] = None - name_end = argument_type.find(">") - if argument_type.startswith("<") and name_end > 0: - argument_type_name = argument_type[1:name_end] - argument_type = argument_type[name_end+1:] - - argument_type_class = SpecArgumentType - if argument_type in SPEC_ARGUMENT_TYPES: - argument_type_class = SPEC_ARGUMENT_TYPES[argument_type] - elif exported: - argument_type_class = SpecArgumentPrivateType - - argument_types.append(argument_type_class(argument_type, - argument_type_name, exported)) - out.append(SpecArgument(optional, argument_types)) - return out - -def argument_spec_human(spec: typing.List[SpecArgument], - context: SpecArgumentContext=SpecArgumentContext.ALL) -> str: - out: typing.List[str] = [] - for spec_argument in spec: - names: typing.List[str] = [] - for argument_type in spec_argument.types: - if not (context&argument_type.context) == 0: - name = argument_type.name() or argument_type.type - if name: - names.append(name) - - if names: - if spec_argument.optional: - format = "[%s]" - else: - format = "<%s>" - out.append(format % "|".join(names)) - return " ".join(out) diff --git a/src/utils/parse/spec.py b/src/utils/parse/spec.py new file mode 100644 index 00000000..2cde7410 --- /dev/null +++ b/src/utils/parse/spec.py @@ -0,0 +1,113 @@ +import enum, typing +from .time import duration + +class SpecArgumentContext(enum.IntFlag): + CHANNEL = 1 + PRIVATE = 2 + ALL = 3 + +class SpecArgumentType(object): + context = SpecArgumentContext.ALL + + def __init__(self, type_name: str, name: typing.Optional[str], exported: str): + self.type = type_name + self._name = name + self.exported = exported + + def name(self) -> typing.Optional[str]: + return self._name + def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: + return None, -1 + def error(self) -> typing.Optional[str]: + return None + +class SpecArgumentTypeWord(SpecArgumentType): + def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: + if args: + return args[0], 1 + return None, 1 +class SpecArgumentTypeWordLower(SpecArgumentTypeWord): + def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: + out = SpecArgumentTypeWord.simple(self, args) + if out[0]: + return out[0].lower(), out[1] + return out + +class SpecArgumentTypeString(SpecArgumentType): + def name(self): + return "%s ..." % SpecArgumentType.name(self) + def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: + return " ".join(args), len(args) + +class SpecArgumentTypeDuration(SpecArgumentType): + def name(self): + return "+%s" % (SpecArgumentType.name(self) or "duration") + def simple(self, args: typing.List[str]) -> typing.Tuple[typing.Any, int]: + if args: + return duration(args[0]), 1 + return None, 1 + def error(self) -> typing.Optional[str]: + return "Invalid timeframe" + +class SpecArgumentPrivateType(SpecArgumentType): + context = SpecArgumentContext.PRIVATE + +SPEC_ARGUMENT_TYPES = { + "word": SpecArgumentTypeWord, + "wordlower": SpecArgumentTypeWordLower, + "string": SpecArgumentTypeString, + "duration": SpecArgumentTypeDuration +} + +class SpecArgument(object): + def __init__(self, optional: bool, types: typing.List[SpecArgumentType]): + self.optional = optional + self.types = types + +def argument_spec(spec: str) -> typing.List[SpecArgument]: + out: typing.List[SpecArgument] = [] + for spec_argument in spec.split(" "): + optional = spec_argument[0] == "?" + + argument_types: typing.List[SpecArgumentType] = [] + for argument_type in spec_argument[1:].split("|"): + exported = "" + if "~" in argument_type: + exported = argument_type.split("~", 1)[1] + argument_type = argument_type.replace("~", "", 1) + + argument_type_name: typing.Optional[str] = None + name_end = argument_type.find(">") + if argument_type.startswith("<") and name_end > 0: + argument_type_name = argument_type[1:name_end] + argument_type = argument_type[name_end+1:] + + argument_type_class = SpecArgumentType + if argument_type in SPEC_ARGUMENT_TYPES: + argument_type_class = SPEC_ARGUMENT_TYPES[argument_type] + elif exported: + argument_type_class = SpecArgumentPrivateType + + argument_types.append(argument_type_class(argument_type, + argument_type_name, exported)) + out.append(SpecArgument(optional, argument_types)) + return out + +def argument_spec_human(spec: typing.List[SpecArgument], + context: SpecArgumentContext=SpecArgumentContext.ALL) -> str: + out: typing.List[str] = [] + for spec_argument in spec: + names: typing.List[str] = [] + for argument_type in spec_argument.types: + if not (context&argument_type.context) == 0: + name = argument_type.name() or argument_type.type + if name: + names.append(name) + + if names: + if spec_argument.optional: + format = "[%s]" + else: + format = "<%s>" + out.append(format % "|".join(names)) + return " ".join(out) diff --git a/src/utils/parse/time.py b/src/utils/parse/time.py new file mode 100644 index 00000000..51094c2d --- /dev/null +++ b/src/utils/parse/time.py @@ -0,0 +1,9 @@ +from src.utils import datetime + +def duration(s: str): + if s[0] == "+": + duration = datetime.from_pretty_time(s[1:]) + if not duration == None: + return duration + return None + |
