Skip to content

Commit 56c896b

Browse files
committed
Document all code with proper docstrings except for the 'pages' module.
1 parent 63eac19 commit 56c896b

File tree

14 files changed

+671
-133
lines changed

14 files changed

+671
-133
lines changed

src/xpuz/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"""Play procedurally generated crosswords."""
1+
"""Play procedurally generated crosswords. Toplevel `__init__` module for `xpuz`."""

src/xpuz/__main__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Entry point for initialising ``xpuz``."""
1+
"""Entry point of ``xpuz``."""
22

33
from configparser import ConfigParser
44
try:
@@ -16,7 +16,11 @@
1616

1717

1818
def _get_os_language() -> str:
19-
"""Infer language code from operating system data."""
19+
"""Infer language code from operating system data.
20+
21+
Returns:
22+
The locale.
23+
"""
2024
if os_name == "posix":
2125
return environ["LANG"].split("-")[0]
2226
else:
@@ -26,6 +30,7 @@ def _get_os_language() -> str:
2630

2731

2832
def main() -> None:
33+
"""Main function to initialise the `xpuz` GUI."""
2934
cfg: ConfigParser = ConfigParser()
3035
_read_cfg(cfg)
3136

src/xpuz/app/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"""test docstring"""
1+
"""The crossword game, hosted locally with a `Flask` server."""

src/xpuz/app/app.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
"""Flask web app to produce an interactive interface to complete a crossword.
2-
The app is run when the user presses the "Load crossword" button in the main GUI.
3-
"""
1+
"""Flask web app that produces an interactive interface to complete a crossword."""
42

3+
from typing import Any, Dict
54
from configparser import ConfigParser
65
from logging import ERROR, getLogger
76
from multiprocessing import Process
@@ -21,10 +20,13 @@
2120
cfg: ConfigParser = ConfigParser()
2221

2322

24-
def _app_process(*args, **kwargs) -> None:
25-
"""Ran as a new Process using the ``multiprocessing`` module. Kwargs are
26-
forwarded from ``_create_app``, which forwards the arguments from
27-
``main.init_webapp``.
23+
def _app_process(**kwargs: Dict[str, Any]) -> None:
24+
"""This function is executed as a new Process with the `multiprocessing`
25+
module to ensure the web application does not block the execution of the
26+
Tkinter GUI.
27+
28+
Args:
29+
**kwargs: Jinja2 template and crossword-related data.
2830
"""
2931

3032
@app.route("/")
@@ -59,18 +61,31 @@ def index() -> str:
5961

6062

6163
def _is_port_in_use(port: int) -> bool:
64+
"""Check if `port` is in use.
65+
66+
Args:
67+
port: The port to check
68+
69+
Returns:
70+
Whether the port is in use or not.
71+
"""
6272
with socket(AF_INET, SOCK_STREAM) as s:
6373
return s.connect_ex(("localhost", port)) == 0
6474

6575

66-
def _create_app(**kwargs) -> None:
67-
"""Execute the ``_app_process`` function as a multithreaded process."""
76+
def _create_app(**kwargs: Dict[str, Any]) -> None:
77+
"""Execute the ``_app_process`` function as a multithreaded process.
78+
79+
Args:
80+
**kwargs: Jinja2 template and crossword-related data.
81+
"""
6882
global server
6983
server = Process(target=_app_process, kwargs=kwargs)
7084
server.start()
7185

7286

7387
def _terminate_app() -> None:
88+
"""Terminate the app process."""
7489
if "server" in globals().keys():
7590
server.terminate()
7691
server.join()

src/xpuz/base.py

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from configparser import ConfigParser
66
from platform import system
7-
from typing import Dict, List, Tuple
7+
from typing import Dict, List, Union, Tuple, Callable, Literal
88

99
from babel import Locale
1010
from customtkinter import (
@@ -26,6 +26,7 @@ class Addons:
2626
"""Convenience and utility methods for all page classes."""
2727

2828
def _set_fonts(self) -> None:
29+
"""Initialise this instance with all the required CTkFont objects."""
2930
self.TITLE_FONT = CTkFont(size=31, weight="bold", slant="roman")
3031
self.SUBHEADING_FONT = CTkFont(size=24, weight="normal", slant="roman")
3132
self.TEXT_FONT = CTkFont(size=15, weight="normal", slant="roman")
@@ -40,11 +41,20 @@ def _set_fonts(self) -> None:
4041
def _confirm_route(
4142
self,
4243
*,
43-
action: bool = None,
44+
action: Callable = None,
4445
condition: bool = None,
4546
confirmation: Dict[str, bool] = {"close": True},
4647
) -> bool:
47-
"""Allow the user to confirm if they wish to route through a messagebox."""
48+
"""Allow the user to confirm if they wish to route through a messagebox.
49+
50+
Args:
51+
action: A function to call if the user confirms to route.
52+
condition: Only perform the confirmation if `True`.
53+
confirmation: Passed in `**kwargs` syntax to the [messagebox helper](utils.md#xpuz.utils.GUIHelper.confirm_with_messagebox)
54+
55+
Returns:
56+
The status of the route confirmation; whether it was accepted or not.
57+
"""
4858

4959
if (
5060
condition
@@ -60,15 +70,24 @@ def _confirm_route(
6070

6171
def _route(
6272
self,
63-
page_ref: str, # Name of the page instance
64-
base: "Base", # Reference to base instance
65-
title: str, # Title of the new page
66-
**kwargs,
73+
page_ref: Literal,
74+
base: CTk,
75+
title: str,
76+
**kwargs: Dict[str, bool],
6777
) -> bool:
6878
"""Method for all page-related classes to simplify navigation.
6979
7080
All class instances that use ``_route`` must have their content packed
71-
and contain 4 content generation methods, as seen below.
81+
and contain 4 content generation methods, as seen in the source code.
82+
83+
Args:
84+
page_ref: The new page's name, used to retrieve the corresponding class from `locals()`.
85+
base: The main app instance.
86+
title: The new page's title.
87+
**kwargs: Confirmation dictionary routed to [_confirm_route](base.md#xpuz.base.Addons._confirm_route).
88+
89+
Returns:
90+
Status of the route; whether it was performed or not.
7291
"""
7392
if (
7493
kwargs
@@ -107,13 +126,19 @@ class Base(CTk, Addons):
107126
"""The main app instance. Contains methods used by all pages."""
108127

109128
base_container: CTkFrame = None
110-
lang_info: Tuple[Dict[str, str], List[str]] = []
111-
locale: Locale = None
112-
cfg: ConfigParser = None
129+
lang_info: Tuple[Dict[str, str], List[str]] = []
130+
locale: Locale = None
131+
cfg: ConfigParser = None
113132
fullscreen: bool = False
114133
page_inst: object = None
115134

116-
def __init__(self, **kwargs) -> None:
135+
def __init__(self, **kwargs: Dict[str, Union[Tuple[Dict[str, str], List[str]], Locale, ConfigParser]]) -> None:
136+
"""Initialise the base instance and container and apply widget scaling,
137+
theme and appearance.
138+
139+
Args:
140+
**kwargs: `lang_info`, `cfg`, and `locale` objects passed from [main](__main__.md#xpuz.__main__.main).
141+
"""
117142
super().__init__()
118143

119144
base_container = CTkFrame(self)
@@ -141,6 +166,11 @@ def __init__(self, **kwargs) -> None:
141166
self._route(page, self, _(PAGE_MAP[page]))
142167

143168
def _set_dim(self, dim: Tuple[int, int] = DIM) -> None:
169+
"""Set the dimensions of the program during runtime.
170+
171+
Args:
172+
dim: The dimensions.
173+
"""
144174
scale = float(Base.cfg.get("m", "scale"))
145175
new_width = dim[0] * scale
146176
new_height = dim[1] * scale
@@ -152,6 +182,7 @@ def _set_dim(self, dim: Tuple[int, int] = DIM) -> None:
152182
self.update()
153183

154184
def _toggle_fullscreen(self) -> None:
185+
"""Enable or disabled fullscreen mode."""
155186
Base.fullscreen = not Base.fullscreen
156187
if self.fullscreen:
157188
self.maxsize(self.winfo_screenwidth(), self.winfo_screenheight())
@@ -171,9 +202,13 @@ def _increment_launches(self) -> None:
171202
def _exit_handler(
172203
self, restart: bool = False, webapp_on: bool = False
173204
) -> None:
174-
"""Called when the event "WM_DELETE_WINDOW" occurs or when the the
205+
"""Called when the event `WM_DELETE_WINDOW` occurs or when the the
175206
program must be restarted, in which case the ``restart`` default
176207
parameter is overridden.
208+
209+
Args:
210+
restart: Whether to perform a restart or not.
211+
webapp_on: Whether the `Flask` web app is running or not.
177212
"""
178213
# If user wants to exit/restart
179214
if GUIHelper.confirm_with_messagebox(exit_=True, restart=restart):

src/xpuz/constants.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""Constant values used across the source code, defining values such as paths
22
and colour values for both the GUI and the web application.
3+
4+
NOTE: You can view the attributes that do not belong to any classes in this module
5+
by pressing the `View source of this page` to the left of the table of contents.
36
"""
47

58
from os import path
@@ -11,9 +14,10 @@
1114

1215

1316
class Colour:
14-
"""Global and light/dark hex colours."""
17+
"""Hex colour specification for both the GUI and the web app."""
1518

1619
class Global:
20+
"""Global hex colours."""
1721
BUTTON: str = "#21528C"
1822
BUTTON_HOVER: str = "#13385F"
1923
EXIT_BUTTON: str = "#ED3B4D"
@@ -25,6 +29,7 @@ class Global:
2529
DIFFICULTIES: List[str] = ["#089E19", "#FCBA03", "#E01C07", "#6408A6"]
2630

2731
class Light:
32+
"""Light mode hex colours."""
2833
MAIN: str = "#C7D0D4"
2934
SUB: str = "#DFE8ED"
3035
TEXT: str = "#242424"
@@ -35,6 +40,7 @@ class Light:
3540
WRONG: str = "#FC0A2A"
3641

3742
class Dark:
43+
"""Dark mode hex colours."""
3844
MAIN: str = "#263238"
3945
SUB: str = "#37474F"
4046
TEXT: str = "#D7D6D6"
@@ -45,7 +51,7 @@ class Dark:
4551
WRONG: str = "#D90D28"
4652

4753

48-
"""Absolute paths used across the source code."""
54+
# Absolute paths used across the source code.
4955
DIR_PATH = Path(__file__).resolve().parents[0]
5056
TEMPLATE_CFG_PATH = path.join(DIR_PATH, "template.config.ini")
5157
DOC_PATH = user_documents_dir()
@@ -72,7 +78,7 @@ class Dark:
7278
ATTEMPTS_DB_PATH = path.join(DIR_PATH, "data", "attempts_db.json")
7379

7480

75-
"""Crossword-related constants."""
81+
# Crossword-related constants.
7682
DIFFICULTIES: List[str] = ["Easy", "Medium", "Hard", "Extreme"]
7783
ACROSS: str = "ACROSS"
7884
DOWN: str = "DOWN"
@@ -89,7 +95,7 @@ class Dark:
8995
DIMENSIONS_CONSTANT: int = 1
9096

9197

92-
"""PDF-related constants"""
98+
# PDF-related constants
9399
PDF_WIDTH = 3508
94100
PDF_HEIGHT = 2480
95101
PDF_MARGIN = 150
@@ -98,7 +104,7 @@ class Dark:
98104
PAGE_DEF_MAX = 25
99105

100106

101-
"""Base english strings"""
107+
# Base english strings
102108
BASE_ENG_CWORD_QUALITIES: List[str] = [
103109
"terrible",
104110
"poor",
@@ -112,7 +118,7 @@ class Dark:
112118
BASE_ENG_EXPORTS: List[str] = ["PDF", "ipuz"]
113119

114120

115-
"""Misc constants"""
121+
# Misc constants
116122
PYPI_URL = "https://pypi.org/project/xpuz/"
117123
RELEASE_API_URL = (
118124
"https://api.github.com/repos/tomasvana10/xpuz/releases/latest"

0 commit comments

Comments
 (0)