Skip to content

Commit

Permalink
Add docstrings to UI and Controller
Browse files Browse the repository at this point in the history
  • Loading branch information
cyberrumor committed Oct 30, 2023
1 parent 88314fe commit 5ae2263
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 19 deletions.
10 changes: 8 additions & 2 deletions ammo/mod_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@


class ModController(Controller):
def __init__(self, downloads_dir: Path, game: Game, *args, **kwargs):
"""
ModController is responsible for managing mods. It exposes
methods to the UI that allow the user to easily manage mods.
Private methods here are private simply so the UI doesn't
display them.
"""
def __init__(self, downloads_dir: Path, game: Game, *keywords):
self.downloads_dir: Path = downloads_dir
self.game: Game = game
self.changes: bool = False
self.downloads: list[Download] = []
self.mods: list[Mod] = []
self.plugins: list[Plugin] = []
self.keywords = [*args]
self.keywords = [*keywords]

# Create required directories for testing. Harmless if exists.
Path.mkdir(self.game.ammo_mods_dir, parents=True, exist_ok=True)
Expand Down
56 changes: 39 additions & 17 deletions ammo/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ class Controller(ABC):
methods, as they are consumed by the UI.
The UI performs validation and type casting based on type
hinting and inspection, so type hints for public methods
are required.
hinting and doc inspection, so type hints for public methods
are required. Doc strings for public methods should typically
fit on one line.
A recoverable error from any public methods should be raised
as a Warning(). This will cause the UI to display the warning
text and prompt the user to [Enter] before the next frame
is drawn.
"""
@abstractmethod
def _prompt(self) -> str:
Expand All @@ -38,6 +44,16 @@ def _post_exec(self) -> bool:
"""
return False

@abstractmethod
def __str__(self) -> str:
"""
Between every command, the screen will be cleared, and
controller will be printed before the user is presented
with the prompt. This should return a 'frame' of your
interface.
"""
return str(self)


class UI:
"""
Expand All @@ -55,6 +71,20 @@ def __init__(self, controller: Controller):
# get a map of commands to functions and the amount of args they expect
self.command = {}

# Default 'help', may be overridden.
self.command["help"] = {
"func": self.help,
"args": [],
"doc": str(self.help.__doc__).strip(),
}

# Default 'exit', may be overridden.
self.command["exit"] = {
"func": self.exit,
"args": [],
"doc": str(self.exit.__doc__).strip(),
}

for name, func in inspect.getmembers(
self.controller.__class__, predicate=inspect.isfunction
):
Expand Down Expand Up @@ -106,17 +136,6 @@ def __init__(self, controller: Controller):
"instance": self.controller,
}

self.command["help"] = {
"func": self.help,
"args": [],
"doc": str(self.help.__doc__).strip(),
}

self.command["exit"] = {
"func": self.exit,
"args": [],
"doc": str(self.exit.__doc__).strip(),
}

def help(self):
"""
Expand All @@ -143,14 +162,17 @@ def help(self):

def exit(self):
"""
Quit. Prompts if there are changes.
Quit.
"""
if self.controller.changes:
if input("There are unapplied changes. Quit? [y/n]: ").lower() != "y":
return True
sys.exit(0)


def cast_to_type(self, arg, target_type):
"""
This method is responsible for casting user input into
the type that the command expects. If target_type is
type[str|int], it may not be cast correctly.
"""
if target_type is int:
try:
return int(arg)
Expand Down

0 comments on commit 5ae2263

Please sign in to comment.