split utils/parse.py in to multiple files

This commit is contained in:
jesopo 2020-01-26 00:06:47 +00:00
parent b24d62c0e6
commit 1d1e2d95a9
3 changed files with 127 additions and 120 deletions

View file

@ -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)

113
src/utils/parse/spec.py Normal file
View file

@ -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)

9
src/utils/parse/time.py Normal file
View file

@ -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