Files
pyoo/pyoo/base.py

123 lines
3.6 KiB
Python

"""
Base data and types for supporting Pyoo operations.
"""
from collections import namedtuple
from typing import Callable, List, Tuple, Type, Sequence, Union, Iterable, Protocol
PREPOSITIONS = (
"with/using",
"at/to",
# 'in front of',
"in/inside/into",
# 'on top of/on/onto/upon',
"on/onto/upon",
# 'out of/from inside/from',
"from",
"over",
"through",
"under/underneath/beneath",
"behind",
"beside",
"for/about",
"is",
"as",
"off",
)
"""`tuple[str]`: A list of preposition strings (equivilancies are / separated)"""
NORMALIZED_PREPS = tuple([x.split("/") for x in PREPOSITIONS])
"""A list of prepositions with equiviliants split."""
class PyooError(Exception):
"""Generic Pyoo error."""
class PyooVerbNotFound(PyooError):
"""Pyoo Error which indicates a verb was not found."""
class PyooObjectNotFound(PyooError):
"""Pyoo Error which indicates an object was not found."""
VerbCallFrame = namedtuple("VerbCallFrame", "environment,player,verbname,dobj,dobjstr,prepstr,iobj,iobjstr,argstr")
"""Namedtuple which contains the call frame (all arguments) for a verb call."""
class Verb:
"""This is a wrapper for a callable to give it the properties required for verbs."""
def __init__(self,
function: Callable,
names: List[str],
callspec: Tuple[str, List[str], str]):
self.function = function
self.name = names[0]
self.names = names
self.callspec = callspec
def __call__(self, *args, **kwargs) -> None:
return self.function(*args, **kwargs)
def __get__(self, obj, objtype: Type):
class VerbFunction:
def __init__(self, func: Callable, obj, typ: Type, verb: "Verb"):
self._func = func
self._obj = obj
self._typ = typ
self.is_verb = True
self.name = verb.name
self.names = verb.names
self.callspec = verb.callspec
def __call__(self, *args, **kwargs):
return self._func.__get__(self._obj, self._typ)(*args, **kwargs)
return VerbFunction(self.function, obj, objtype, self)
def __repr__(self) -> str:
return f"<Verb {self.name} {self.callspec}>"
def make_verb(verbname: str, dobjspec: str, prepspec: str, iobjspec: str) -> Callable[..., Verb]:
"""This simple decorator adds verb metadata to a method or function.
Arguments:
verbname (str): List of verb names, comma separated, with wildcards.
dobjspec (str): 'this' or 'that' or 'none' or 'any'
(this = the object which defines the verb, that = an object in the soup, any = any string,
none = blank)
iobjspec (str): 'this' or 'that' or 'none' or 'any' (as above)
prepspec (str): one of prepositions strings (as in the PREPOSITIONS list)
"""
def verb_decorate(verbfunc: Callable[[VerbCallFrame, ], None]) -> Verb:
names = [x.strip() for x in verbname.split(",")]
ps: List[str] = []
if prepspec.find("/") > 0:
ps = prepspec.split("/")
else:
for prep in NORMALIZED_PREPS:
if prepspec in prep:
ps = prep
break
ps = [prepspec]
return Verb(verbfunc, names, (dobjspec, ps, iobjspec))
return verb_decorate
#
# type things
#
class InterpreterProtocol(Protocol):
"""Defines minimal protocol for interpreter objects."""
def update(self) -> None:
...
SingleMultiString = Union[Sequence[str], str, Iterable[str]]