Source code for warg.config_shell
#!/usr/bin/env python3
__author__ = "Christian Heider Lindbjerg"
__doc__ = r"""
Created on 17/03/2020
"""
__all__ = ["PlaybackShell", "ConfigShell"]
from pathlib import Path
import cmd
import logging
from typing import Callable, MutableMapping, Optional
from warg import PropertySettings, passes_kws_to
_logger = logging.getLogger(__name__)
[docs]
class PlaybackShell(cmd.Cmd):
"""description"""
intro = "Type help or ? to list commands.\n"
default_file_path = Path("playback.cmd")
file = None
# ----- record and playback -----
[docs]
def do_record(self, file: Path) -> None:
"""Save future commands to filename: RECORD file.cmd"""
if not file:
file = self.default_file_path
self.file = open(file, "w")
[docs]
def do_playback(self, file: Path) -> None:
"""Playback commands from a file: PLAYBACK file.cmd"""
self.close()
if not file:
file = self.default_file_path
with open(file) as f:
self.cmdqueue.extend(f.read().splitlines())
[docs]
def precmd(self, line: str) -> str:
"""
:param line:
:return:
"""
line = line.lower()
if self.file and "playback" not in line:
_logger.info(line, file=self.file)
return line
[docs]
def close(self) -> None:
"""Close file"""
if self.file:
self.file.close()
self.file = None
[docs]
def do_exit(self, arg) -> bool:
"""If recording, stop, close file, close window, and exit:"""
_logger.info("Exiting")
self.close()
return True
[docs]
def do_close(self, arg) -> None:
"""If recording, stop, close file, close window, and exit:"""
self.do_exit(arg)
[docs]
class ConfigShell(PlaybackShell):
"""description"""
[docs]
def get_names(self): # Override!
"""
:return:
:rtype:
"""
return dir(self)
[docs]
def onecmd(self, line): # Override!
"""
:param line:
:type line:
:return:
:rtype:
"""
try:
return super().onecmd(line)
except Exception as e:
_logger.info(e)
return False # don't stop
[docs]
@passes_kws_to(cmd.Cmd.__init__)
def __init__(self, name: str = "config", **kwargs: MutableMapping):
super().__init__(**kwargs)
ConfigShell.prompt = f"({name}) "
[docs]
def add_property_options(self, ps: PropertySettings) -> None:
"""
:param ps:
:type ps:
"""
for p in ps.__iter_keys__():
prop = getattr(ps.__class__, p)
if isinstance(prop, property):
getter = lambda *e: _logger.info(prop.fget(ps))
getter.__doc__ = prop.fget.__doc__
setter = lambda *e: prop.fset(ps, *e)
setter.__doc__ = prop.fset.__doc__
if prop.fdel:
deleter = lambda *e: prop.fdel(ps)
deleter.__doc__ = prop.fdel.__doc__
else:
deleter = None
self.add_option(p, getter=getter, setter=setter, deleter=deleter)
[docs]
def add_option(
self,
key: str,
*,
getter: Callable,
setter: Callable,
deleter: Optional[callable] = None,
) -> None:
"""
:param key:
:type key:
:param getter:
:type getter:
:param setter:
:type setter:
:param deleter:
:type deleter:
"""
self.add_func(f"get_{key}", getter)
self.add_func(f"set_{key}", setter)
if deleter:
self.add_func(f"del_{key}", deleter)
[docs]
def add_func(self, key: str, func: Callable) -> None:
"""
:param key:
:type key:
:param func:
:type func:
"""
k = f"do_{key}"
assert k not in self.get_names()
self.__setattr__(k, func)
if __name__ == "__main__":
def main():
"""
:return:
:rtype:
"""
global A
global SOME
A = 99
SOME = 99
class Aconfig(PropertySettings):
@property
def some(self):
"""
return SOME
:return:
:rtype:
"""
return SOME
@some.setter
def some(self, i):
"""
set SOME
:return:
:rtype:
"""
global SOME
SOME = i
@some.deleter
def some(self):
"""
del SOME
:return:
:rtype:
"""
del SOME
@property
def other(self):
"""
return A
:return:
:rtype:
"""
return A
@other.setter
def other(self, i):
"""
set A
:return:
:rtype:
"""
global A
A = i
ac = Aconfig()
def set_A(e):
"""
:param e:
:type e:
"""
global A
A = e
def get_A(e):
"""
:param e:
:type e:
"""
_logger.info(A)
cs = ConfigShell()
cs.add_option("a", getter=get_A, setter=set_A)
cs.add_property_options(ac)
cs.cmdloop()
main()