Skip to content

Commit

Permalink
the actual push for linting and #1
Browse files Browse the repository at this point in the history
  • Loading branch information
Zomatree authored Aug 22, 2019
1 parent 82a8573 commit b67807b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 41 deletions.
31 changes: 21 additions & 10 deletions actioneer/action.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from typing import Union, Callable, Any, List, Dict, Dict
from typing_extensions import Protocol, Annotated, TypeVar
import traceback
from typing import Callable, Any, List, Dict
from inspect import Parameter, signature
from .utils import identity, bool_from_str
from .argument import Argument
from .errors import AlreadyAActionWithThatName


class Command:
def __init__(self, func, aliases:List[str] = [], *, options: Dict[str, Callable] = {}, options_aliases: Dict[str, str] = {},
flags: List[str] = [], flags_aliases: Dict[str, str] = {}):
def __init__(self, func, aliases: List[str] = [], *,
options: Dict[str, Callable] = {},
options_aliases: Dict[str, str] = {}, flags: List[str] = [],
flags_aliases: Dict[str, str] = {}, performer=None):
self.subs = {}
self.name = func.__name__
self.func = func
Expand All @@ -20,6 +21,8 @@ def __init__(self, func, aliases:List[str] = [], *, options: Dict[str, Callable]
self.options_aliases = options_aliases
self.flags = flags
self.flags_aliases = flags_aliases
self.error_handler = None
self.performer = performer

overrides = {
Parameter.empty: identity,
Expand All @@ -29,7 +32,7 @@ def __init__(self, func, aliases:List[str] = [], *, options: Dict[str, Callable]
def make_cast(self, param):
return self.overrides.get(param, param)

def invoke(self, args: List[str] = [], ctx: List[Any] = []): # [10, "a", Message, ...]
def invoke(self, args: List[str] = [], ctx: List[Any] = []):
ctx = {type(a): a for a in ctx}
sub = self.subs.get(args[0])
if sub:
Expand All @@ -42,12 +45,15 @@ def invoke(self, args: List[str] = [], ctx: List[Any] = []): # [10, "a", Messag
ctxs = {name: ctx[value] for name, value in name_annots.items()}
self.func(*args, **ctxs)
except Exception as e:
raise e
if self.error_handler:
self.run_fail(e, ctx)
elif self.performer:
self.performer.run_fail(e, ctx)

def sub_command(self, aliases: list = []):
def wrapper(func):
if func.__name__ in self.subs.keys():
raise Exception(func.__name__, self.name) # TODO
raise AlreadyAActionWithThatName(func.__name__, self.name)
for name in aliases + [func.__name__]:
sub = Command(func)
self.subs[name] = sub
Expand All @@ -63,5 +69,10 @@ def parameters(self):
def error(self, func):
self.error_handler = func

def error_handler(self, error):
raise error # TODO
def run_fail(self, e, ctx: Dict[Any, Any] = []):
name_annots = {name: v.annotation for name, v in
signature(self.error_handler).parameters.items()
if v.kind == Parameter.KEYWORD_ONLY}

ctxs = {name: ctx[value] for name, value in name_annots.items()}
self.error_handler(e, **ctxs)
13 changes: 13 additions & 0 deletions actioneer/errors.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@

class ConvertingError(Exception):
"""Raised when converting a argument failed"""


class NoClosingQuote(Exception):
"""No closing quote on your command arguments"""


class NoCommandFound(Exception):
"""No command has been found with that name"""


class AlreadyAActionWithThatName(Exception):
"""When A Action is trying to be created with a name of a Action
with the same name"""
27 changes: 20 additions & 7 deletions actioneer/flags.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
class Flags:
def __init__(self, flags): self._flags = flags
def __len__(self): return len(self._flags)
def __getitem__(self, key): return self._flags[key]
def __iter__(self): return iter(self._flags)
def __reversed__(): return reversed(self._flags)
def __contains__(self, k): return k in self._flags
def __repr__(self): return repr(self._flags)
def __init__(self, flags):
self._flags = flags

def __len__(self):
return len(self._flags)

def __getitem__(self, key):
return self._flags[key]

def __iter__(self):
return iter(self._flags)

def __reversed__(self):
return reversed(self._flags)

def __contains__(self, k):
return k in self._flags

def __str__(self):
return str(self._flags)
27 changes: 20 additions & 7 deletions actioneer/options.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
class Options:
def __init__(self, options): self._options = options
def __len__(self): return len(self._options)
def __getitem__(self, key): return self._options[key]
def __iter__(self): return iter(self._options)
def __reversed__(): return reversed(self._options)
def __contains__(self, k): return k in self._options
def __repr__(self): return repr(self._options)
def __init__(self, options):
self._options = options

def __len__(self):
return len(self._options)

def __getitem__(self, key):
return self._options[key]

def __iter__(self):
return iter(self._options)

def __reversed__(self):
return reversed(self._options)

def __contains__(self, k):
return k in self._options

def __str__(self):
return str(self._options)
52 changes: 35 additions & 17 deletions actioneer/performer.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from typing import List, Any, Dict, Callable
from .errors import ConvertingError
from .errors import NoClosingQuote
from .flags import Flags
from .options import Options
import re

import inspect
import traceback
quoteRe = re.compile(r"[\"']")
chunk = re.compile(r"\S+")


class Performer:
def __init__(self, ctx: List[Any] = []):
self.commands = []
Expand All @@ -23,18 +25,35 @@ def register(self, cmd):
def run(self, args, ctx: List[Any] = []):
cmd = self.lookup.get(args.split(" ")[0])
if cmd:
args = self.split_args(args)
options, args = self.get_options(args, cmd.options, cmd.options_aliases)
flags, args = self.get_flags(args, cmd.flags, cmd.flags_aliases)
flags = Flags(flags)
options = Options(options)
return cmd.invoke(args[1:], ctx + self.ctx + [flags, options])
raise Exception("BRUH") # TODO: do custom error class
try:
args = self.split_args(args)
options, args = self.get_options(args, cmd.options,
cmd.options_aliases)
flags, args = self.get_flags(args, cmd.flags,
cmd.flags_aliases)
flags = Flags(flags)
options = Options(options)
return cmd.invoke(args[1:], ctx + self.ctx + [flags, options])
except Exception as e:
if cmd.error_handler:
cmd.run_fail(e, ctx)
else:
self.run_fail(e, ctx)

def error(self, func):
self.fail = func

def fail(self, e):
print("Invoking failed:", e)
traceback.print_exc()

def run_fail(self, e, ctx: Dict[Any, Any] = {}):
name_annots = {name: v.annotation for name, v in
inspect.signature(self.fail).parameters.items()
if v.kind == inspect.Parameter.KEYWORD_ONLY}

ctxs = {name: ctx[value] for name, value in name_annots.items()}
self.fail(e, **ctxs)

def split_args(self, s: str) -> List[str]:
"""Will split the raw input into the arguments"""
args = []
Expand All @@ -47,37 +66,36 @@ def split_args(self, s: str) -> List[str]:
args.append(s[i + 1: j])
i = j
except ValueError:
raise UnclosedQuote("Missing closing quote.")
raise NoClosingQuote("Missing closing quote.")
else:
match = chunk.match(s, i)
if match:
args.append(match.group())
i = match.end()
i += 1

return args

def get_options(self, inp: List[str], options: Dict[str, Callable],
aliases: Dict[str, str]) -> Dict[str, Any]: # {"channelid": "channel", "channel_id": "channel"}
aliases: Dict[str, str]) -> Dict[str, Any]:
"""Will get options, the return will be converted as setup"""
out = {}
for i, arg in enumerate(inp):
name = arg[2:]
if not arg.startswith("--"): continue
if not arg.startswith("-"):
continue
try:
if arg.startswith("--") and name in options.keys():
if arg.startswith("-") and name in options.keys():
out[name] = options[name](inp[i+1])
del inp[i]
del inp[i]
elif arg.startswith("--") and name in aliases.keys():
elif arg.startswith("-") and name in aliases.keys():
out[aliases[name]] = options[name](inp[i+1])
del inp[i]
del inp[i]
except Exception as e:
raise e
return out, inp


def get_flags(self, inp: List[str], flags: List[str],
aliases: Dict[str, str]) -> Dict[str, bool]:
"""Will get all flags"""
Expand Down

0 comments on commit b67807b

Please sign in to comment.