diff --git a/docs/scripts/gen_ref_nav.py b/docs/scripts/gen_ref_nav.py
index a0133502..12041522 100644
--- a/docs/scripts/gen_ref_nav.py
+++ b/docs/scripts/gen_ref_nav.py
@@ -7,7 +7,9 @@
pkg_name = "xpuz"
nav = Nav()
-mod_symbol = '
'
+mod_symbol = (
+ '
'
+)
root = Path(__file__).parent.parent.parent
src = root / "src"
@@ -35,7 +37,9 @@
ident = ".".join(parts)
fd.write(f"::: {ident}")
- mkdocs_gen_files.set_edit_path(full_doc_path, ".." / path.relative_to(root))
+ mkdocs_gen_files.set_edit_path(
+ full_doc_path, ".." / path.relative_to(root)
+ )
with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file:
- nav_file.writelines(nav.build_literate_nav())
\ No newline at end of file
+ nav_file.writelines(nav.build_literate_nav())
diff --git a/src/xpuz/__init__.py b/src/xpuz/__init__.py
index 4a70f89b..15149794 100644
--- a/src/xpuz/__init__.py
+++ b/src/xpuz/__init__.py
@@ -1 +1 @@
-"""Play procedurally generated crosswords. Toplevel `__init__` module for `xpuz`."""
\ No newline at end of file
+"""Play procedurally generated crosswords. Toplevel `__init__` module for `xpuz`."""
diff --git a/src/xpuz/__main__.py b/src/xpuz/__main__.py
index 6a0dbe92..3a1dded2 100644
--- a/src/xpuz/__main__.py
+++ b/src/xpuz/__main__.py
@@ -1,6 +1,7 @@
"""Entry point of ``xpuz``."""
from configparser import ConfigParser
+
try:
from ctypes import windll
from locale import windows_locale
@@ -17,7 +18,7 @@
def _get_os_language() -> str:
"""Infer language code from operating system data.
-
+
Returns:
The locale.
"""
diff --git a/src/xpuz/app/app.py b/src/xpuz/app/app.py
index 759f05d7..2b64503e 100644
--- a/src/xpuz/app/app.py
+++ b/src/xpuz/app/app.py
@@ -22,9 +22,9 @@
def _app_process(**kwargs: Dict[str, Any]) -> None:
"""This function is executed as a new Process with the `multiprocessing`
- module to ensure the web application does not block the execution of the
+ module to ensure the web application does not block the execution of the
Tkinter GUI.
-
+
Args:
**kwargs: Jinja2 template and crossword-related data.
"""
@@ -62,10 +62,10 @@ def index() -> str:
def _is_port_in_use(port: int) -> bool:
"""Check if `port` is in use.
-
+
Args:
port: The port to check
-
+
Returns:
Whether the port is in use or not.
"""
@@ -75,7 +75,7 @@ def _is_port_in_use(port: int) -> bool:
def _create_app(**kwargs: Dict[str, Any]) -> None:
"""Execute the ``_app_process`` function as a multithreaded process.
-
+
Args:
**kwargs: Jinja2 template and crossword-related data.
"""
diff --git a/src/xpuz/base.py b/src/xpuz/base.py
index 03404f20..eae6669b 100644
--- a/src/xpuz/base.py
+++ b/src/xpuz/base.py
@@ -46,12 +46,15 @@ def _confirm_route(
confirmation: Dict[str, bool] = {"close": True},
) -> bool:
"""Allow the user to confirm if they wish to route through a messagebox.
-
+
Args:
action: A function to call if the user confirms to route.
condition: Only perform the confirmation if `True`.
- confirmation: Passed in `**kwargs` syntax to the [messagebox helper](utils.md#xpuz.utils.GUIHelper.confirm_with_messagebox)
-
+ confirmation: Passed in `**kwargs` syntax to the
+ [messagebox helper](
+ utils.md#xpuz.utils.GUIHelper.confirm_with_messagebox
+ )
+
Returns:
The status of the route confirmation; whether it was accepted or not.
"""
@@ -79,13 +82,15 @@ def _route(
All class instances that use ``_route`` must have their content packed
and contain 4 content generation methods, as seen in the source code.
-
+
Args:
- page_ref: The new page's name, used to retrieve the corresponding class from `locals()`.
+ page_ref: The new page's name, used to retrieve the corresponding
+ class from `locals()`.
base: The main app instance.
title: The new page's title.
- **kwargs: Confirmation dictionary routed to [_confirm_route](base.md#xpuz.base.Addons._confirm_route).
-
+ **kwargs: Confirmation dictionary routed to
+ [_confirm_route](base.md#xpuz.base.Addons._confirm_route).
+
Returns:
Status of the route; whether it was performed or not.
"""
@@ -126,18 +131,24 @@ class Base(CTk, Addons):
"""The main app instance. Contains methods used by all pages."""
base_container: CTkFrame = None
- lang_info: Tuple[Dict[str, str], List[str]] = []
- locale: Locale = None
- cfg: ConfigParser = None
+ lang_info: Tuple[Dict[str, str], List[str]] = []
+ locale: Locale = None
+ cfg: ConfigParser = None
fullscreen: bool = False
page_inst: object = None
- def __init__(self, **kwargs: Dict[str, Union[Tuple[Dict[str, str], List[str]], Locale, ConfigParser]]) -> None:
+ def __init__(
+ self,
+ **kwargs: Dict[
+ str, Union[Tuple[Dict[str, str], List[str]], Locale, ConfigParser]
+ ],
+ ) -> None:
"""Initialise the base instance and container and apply widget scaling,
theme and appearance.
-
+
Args:
- **kwargs: `lang_info`, `cfg`, and `locale` objects passed from [main](__main__.md#xpuz.__main__.main).
+ **kwargs: `lang_info`, `cfg`, and `locale` objects passed from
+ [main](__main__.md#xpuz.__main__.main).
"""
super().__init__()
@@ -167,8 +178,8 @@ def __init__(self, **kwargs: Dict[str, Union[Tuple[Dict[str, str], List[str]], L
def _set_dim(self, dim: Tuple[int, int] = DIM) -> None:
"""Set the dimensions of the program during runtime.
-
- Args:
+
+ Args:
dim: The dimensions.
"""
scale = float(Base.cfg.get("m", "scale"))
@@ -205,7 +216,7 @@ def _exit_handler(
"""Called when the event `WM_DELETE_WINDOW` occurs or when the the
program must be restarted, in which case the ``restart`` default
parameter is overridden.
-
+
Args:
restart: Whether to perform a restart or not.
webapp_on: Whether the `Flask` web app is running or not.
diff --git a/src/xpuz/constants.py b/src/xpuz/constants.py
index 2c950814..aebd37de 100644
--- a/src/xpuz/constants.py
+++ b/src/xpuz/constants.py
@@ -1,12 +1,49 @@
"""Constant values used across the source code, defining values such as paths
and colour values for both the GUI and the web application.
-NOTE: You can view the attributes that do not belong to any classes in this module
-by pressing the `View source of this page` to the left of the table of contents.
+Attributes:
+ DIR_PATH: Path to the toplevel of `xpuz`.
+ TEMPLATE_CFG_PATH: Path to template `config.ini` file.
+ DOC_PATH: Path to the system's documents directory or equivalent.
+ DOC_DATA_PATH: Path to the `xpuz` folder within the system's documents directory.
+ DOC_CAT_PATH: Path to the `user` folder within the `xpuz` folder.
+ DOC_CFG_PATH: Path to the `config.ini` file within the `xpuz` folder.
+ LOCALES_PATH: Path to the package's locales folder.
+ BASE_POT_PATH: Path to the package's translation template file.
+ ASSETS_PATH: Path to the package's `assets` folder.
+ IMAGES_PATH: Path to the package's `image` folder, located within `assets`.
+ BASE_CWORDS_PATH: Path to the package's base crosswords folder.
+ ATTEMPTS_DB_PATH: Path to the `attempts_db.json` file for crossword optimisation.
+ DIFFICULTIES: Crossword difficulties.
+ ACROSS: Representation of a word going right to left.
+ DOWN: Representation of a word going top to bottom.
+ EMPTY: Representation of a void cell in the crossword grid.
+ NONLANGUAGE_PATTERN: Regex pattern to filter out non-language characters.
+ QUALITY_MAP: Mapping of crossword quality descriptors to a float value,
+ which is used to scale how many optimisation attempts are undergone to
+ make a crossword with that quality.
+ WHITESPACE_SCALAR: A value to scale the whitespace present in a crossword grid.
+ DIMENSIONS_CONSTANT: A value that is added to the final grid dimension
+ calculation after applying `math.ceil`.
+ PDF_WIDTH: PDF A4 width.
+ PDF_HEIGHT: PDF A4 height.
+ PDF_MARGIN: PDF A4 margin.
+ FONTSIZE_DIR_TITLE: Font size of the title for the 'Across' or 'Down'
+ columns in a PDF.
+ FONTSIZE_DEF: Clue font size.
+ PAGE_DEF_MAX: How many clues can fit on a page.
+ DIM: Standard tkinter GUI dimensions
+ EDITOR_DIM: Dimensions for the crossword editor within the tkinter GUI.
+ LANG_REPLACEMENTS: Mapping of google translate language codes to their
+ respective `Babel` language codes. `None` if they do not exist, otherwise,
+ a string representing the `Babel`-correct code.
+
+
+
"""
from os import path
-from pathlib import Path
+from pathlib import Path, PosixPath, WindowsPath
from typing import Dict, List, Union
from platformdirs import user_documents_dir
@@ -18,6 +55,7 @@ class Colour:
class Global:
"""Global hex colours."""
+
BUTTON: str = "#21528C"
BUTTON_HOVER: str = "#13385F"
EXIT_BUTTON: str = "#ED3B4D"
@@ -30,6 +68,7 @@ class Global:
class Light:
"""Light mode hex colours."""
+
MAIN: str = "#C7D0D4"
SUB: str = "#DFE8ED"
TEXT: str = "#242424"
@@ -41,6 +80,7 @@ class Light:
class Dark:
"""Dark mode hex colours."""
+
MAIN: str = "#263238"
SUB: str = "#37474F"
TEXT: str = "#D7D6D6"
@@ -52,39 +92,39 @@ class Dark:
# Absolute paths used across the source code.
-DIR_PATH = Path(__file__).resolve().parents[0]
-TEMPLATE_CFG_PATH = path.join(DIR_PATH, "template.config.ini")
-DOC_PATH = user_documents_dir()
-DOC_DATA_PATH = path.join(DOC_PATH, "xpuz")
-DOC_CAT_PATH = path.join(DOC_DATA_PATH, "user")
-DOC_CFG_PATH = path.join(DOC_DATA_PATH, "config.ini")
-LOCALES_PATH = path.join(DIR_PATH, "locales")
-BASE_POT_PATH = path.join(LOCALES_PATH, "base.pot")
-ASSETS_PATH = path.join(DIR_PATH, "assets")
-IMAGES_PATH = path.join(ASSETS_PATH, "images")
-CWORD_IMG_LIGHT_PATH = path.join(IMAGES_PATH, "cword_light.png")
-CWORD_IMG_DARK_PATH = path.join(IMAGES_PATH, "cword_dark.png")
-FS_IMG_LIGHT_PATH = path.join(IMAGES_PATH, "fs_light.png")
-FS_IMG_DARK_PATH = path.join(IMAGES_PATH, "fs_dark.png")
-EXPORT_IMG_PATH = path.join(IMAGES_PATH, "export.png")
-IMPORT_IMG_PATH = path.join(IMAGES_PATH, "import.png")
-EXPORT_DIS_IMG_PATH = path.join(IMAGES_PATH, "export_dis.png")
-IMPORT_DIS_IMG_PATH = path.join(IMAGES_PATH, "import_dis.png")
-FOLDER_IMG_PATH = path.join(IMAGES_PATH, "folder.png")
-FOLDER_DIS_IMG_PATH = path.join(IMAGES_PATH, "folder_dis.png")
-WIN_LOGO_PATH = path.join(IMAGES_PATH, "logo.ico")
-LINUX_LOGO_PATH = "@" + path.join(IMAGES_PATH, "logo.xbm")
-BASE_CWORDS_PATH = path.join(DIR_PATH, "base_cwords")
-ATTEMPTS_DB_PATH = path.join(DIR_PATH, "data", "attempts_db.json")
+DIR_PATH: Union[PosixPath, WindowsPath] = Path(__file__).resolve().parents[0]
+TEMPLATE_CFG_PATH: str = path.join(DIR_PATH, "template.config.ini")
+DOC_PATH: str = user_documents_dir()
+DOC_DATA_PATH: str = path.join(DOC_PATH, "xpuz")
+DOC_CAT_PATH: str = path.join(DOC_DATA_PATH, "user")
+DOC_CFG_PATH: str = path.join(DOC_DATA_PATH, "config.ini")
+LOCALES_PATH: str = path.join(DIR_PATH, "locales")
+BASE_POT_PATH: str = path.join(LOCALES_PATH, "base.pot")
+ASSETS_PATH: str = path.join(DIR_PATH, "assets")
+IMAGES_PATH: str = path.join(ASSETS_PATH, "images")
+CWORD_IMG_LIGHT_PATH: str = path.join(IMAGES_PATH, "cword_light.png")
+CWORD_IMG_DARK_PATH: str = path.join(IMAGES_PATH, "cword_dark.png")
+FS_IMG_LIGHT_PATH: str = path.join(IMAGES_PATH, "fs_light.png")
+FS_IMG_DARK_PATH: str = path.join(IMAGES_PATH, "fs_dark.png")
+EXPORT_IMG_PATH: str = path.join(IMAGES_PATH, "export.png")
+IMPORT_IMG_PATH: str = path.join(IMAGES_PATH, "import.png")
+EXPORT_DIS_IMG_PATH: str = path.join(IMAGES_PATH, "export_dis.png")
+IMPORT_DIS_IMG_PATH: str = path.join(IMAGES_PATH, "import_dis.png")
+FOLDER_IMG_PATH: str = path.join(IMAGES_PATH, "folder.png")
+FOLDER_DIS_IMG_PATH: str = path.join(IMAGES_PATH, "folder_dis.png")
+WIN_LOGO_PATH: str = path.join(IMAGES_PATH, "logo.ico")
+LINUX_LOGO_PATH: str = "@" + path.join(IMAGES_PATH, "logo.xbm")
+BASE_CWORDS_PATH: str = path.join(DIR_PATH, "base_cwords")
+ATTEMPTS_DB_PATH: str = path.join(DIR_PATH, "data", "attempts_db.json")
# Crossword-related constants.
DIFFICULTIES: List[str] = ["Easy", "Medium", "Hard", "Extreme"]
ACROSS: str = "ACROSS"
DOWN: str = "DOWN"
-EMPTY: str = "\u25AE"
+EMPTY: str = "\u25ae"
NONLANGUAGE_PATTERN: Pattern = compile(r"\PL")
-QUALITY_MAP: Dict[str, int] = {
+QUALITY_MAP: Dict[str, float] = {
"terrible": 0.05,
"poor": 0.25,
"average": 0.5,
@@ -96,12 +136,12 @@ class Dark:
# PDF-related constants
-PDF_WIDTH = 3508
-PDF_HEIGHT = 2480
-PDF_MARGIN = 150
-FONTSIZE_DIR_TITLE = 100
-FONTSIZE_DEF = 40
-PAGE_DEF_MAX = 25
+PDF_WIDTH: int = 3508
+PDF_HEIGHT: int = 2480
+PDF_MARGIN: int = 150
+FONTSIZE_DIR_TITLE: int = 100
+FONTSIZE_DEF: int = 40
+PAGE_DEF_MAX: int = 25
# Base english strings
@@ -119,13 +159,13 @@ class Dark:
# Misc constants
-PYPI_URL = "https://pypi.org/project/xpuz/"
-RELEASE_API_URL = (
+PYPI_URL: str = "https://pypi.org/project/xpuz/"
+RELEASE_API_URL: str = (
"https://api.github.com/repos/tomasvana10/xpuz/releases/latest"
)
-PROJECT_URL = "https://github.com/tomasvana10/xpuz"
-DIM = (900, 650)
-EDITOR_DIM = (1125, 600)
+PROJECT_URL: str = "https://github.com/tomasvana10/xpuz"
+DIM: Tuple[int, int] = (900, 650)
+EDITOR_DIM: Tuple[int, int] = (1125, 600)
PAGE_MAP: Dict[str, str] = {
"HomePage": "Crossword Puzzle",
"BrowserPage": "Crossword Browser",
@@ -147,6 +187,6 @@ class Dark:
"ku": None,
"sd": None,
}
-REVERSE_LANG_REPLACEMENTS = {
+REVERSE_LANG_REPLACEMENTS: Dict[Union[str, None], str] = {
value: key for key, value in LANG_REPLACEMENTS.items()
}
diff --git a/src/xpuz/crossword.py b/src/xpuz/crossword.py
index 440b0b42..a1e3dd2b 100644
--- a/src/xpuz/crossword.py
+++ b/src/xpuz/crossword.py
@@ -21,7 +21,7 @@
class Crossword:
- """Creates and populates a grid with a given amount of randomly sampled
+ """Creates and populates a grid with a given amount of randomly sampled
words from a larger set of crossword definitions in a crossword-like pattern.
"""
@@ -35,15 +35,17 @@ def __init__(
) -> None:
"""Initialise the base parameters of a crossword such as definitions
and dimensions to prepare for generation.
-
+
Args:
name: The crossword's name.
definitions: The word:clue data for the crossword
word_count: The amount of words to try inserting into the grid.
- via_find_best_crossword: Whether this class is being instantiated with find_best_crossword or not.
- dimensions: The side length of the grid. Both length and width are identical.
+ via_find_best_crossword: Whether this class is being instantiated
+ with find_best_crossword or not.
+ dimensions: The side length of the grid. Both length and width are
+ identical.
"""
-
+
if via_find_best_crossword: # Prevent recalculation of dimensions and
# only shuffle existing definitions
self.definitions: Dict[str, str] = _randomise_definitions(
@@ -68,7 +70,7 @@ def __init__(
@property
def cells(self) -> str:
"""Show an easy-to-read representation of this `Crossword` instance.
-
+
Returns:
The cells.
"""
@@ -76,7 +78,7 @@ def cells(self) -> str:
def __repr__(self) -> str:
"""Display a dev-friendly representation of this `Crossword` instance.
-
+
Returns:
The representation in `namedtuple` format.
"""
@@ -95,7 +97,7 @@ def __repr__(self) -> str:
def generate(self) -> Union[bool, None]:
"""Create a two-dimensional array filled with ``EMPTY`` characters.
-
+
Returns:
Whether the grid was generated or not."""
if not self.generated:
@@ -111,7 +113,7 @@ def generate(self) -> Union[bool, None]:
def _get_dimensions(self) -> int:
"""Determine the square dimensions of the crossword based on total word
count or maximum word length.
-
+
Returns:
The dimensions.
"""
@@ -130,7 +132,7 @@ def _get_dimensions(self) -> int:
def _init_grid(self) -> List[List[str]]:
"""Create two-dimensional array of ``EMPTY`` characters.
-
+
Returns:
The two-dimensional array/crossword grid.
"""
@@ -145,10 +147,10 @@ def _unpack_placement_info(
) -> Tuple[str, Union[ACROSS, DOWN], int, int]:
"""Return specific data from `placement` that is required to call
[_place_word](crossword.md#xpuz.crossword.Crossword._place_word).
-
+
Args:
placement: The placement data.
-
+
Returns:
The extracted placement data.
"""
@@ -162,10 +164,10 @@ def _unpack_placement_info(
@staticmethod
def _sort_placements(placements: List[Placement]) -> List[Placement]:
"""Sort `placements` by their `intersections` key.
-
+
Args:
placements: The placements.
-
+
Returns:
The sorted placements.
"""
@@ -181,7 +183,7 @@ def _place_word(
col: int,
) -> None:
"""Place `word` in the grid at the given `row`, `column` and `direction`.
-
+
Args:
word: The word to be placed.
direction: The direction to place the word.
@@ -200,10 +202,10 @@ def _get_middle_placement(self, word: str) -> Placement:
"""Return the placement for the first word in a random orientation in
the middle of the grid. This naturally makes the generator build off of
the center, making the crossword look nicer.
-
+
Args:
word: The word to be placed in the middle of the grid.
-
+
Returns:
A pseudo-placement dictionary.
"""
@@ -233,15 +235,16 @@ def _find_intersections(
) -> Union[Tuple[None], Tuple[int]]:
"""Find the row and column of all points of intersection that `word`
has with `self.grid`.
-
+
Args:
word: The word to be placed.
direction: The direction the word is being placed in.
row: The row the word is being placed in.
col: The column the word is being placed in.
-
+
Returns:
- All the intersections that `word` has with `self.grid` in (row, column) form.
+ All the intersections that `word` has with `self.grid` in
+ (row, column) form.
"""
intersections: List[Tuple[int, int]] = []
@@ -266,24 +269,24 @@ def _validate_placement(
) -> bool:
"""Determine if a word is suitable to be inserted into the grid. Causes
for this method returning False are as follows:
-
+
1. The word exceeds the limits of the grid if placed at `row`
and `col`.
-
+
2. The word intersects with another word of the same orientation at
its first or last letter, e.x. ATHENSOFIA (Athens + Sofia)
-
+
3. Other characters are in the way of the word - not
overlapping/intersecting.
-
+
4. Directly adjacent intersections are present.
-
+
Args:
word: The word to be placed.
direction: The direction the word is being placed in.
row: The row the word is being placed in.
col: The column the word is being placed in.
-
+
Returns:
Whether the word is valid or not.
"""
@@ -357,10 +360,10 @@ def _prune_unreadable_placements(
) -> Union[List[Placement], List[None]]:
"""Remove all placements that will result in the word being directly
adjacent to another word, like `ATHENSSOFIA`.
-
+
Args:
placements: The placements to prune.
-
+
Returns:
The pruned placements.
"""
@@ -430,10 +433,10 @@ def _prune_unreadable_placements(
def _get_placements(self, word: str) -> Union[List[Placement], List[None]]:
"""Find all placements for a given word (across and down), if valid.
-
+
Args:
word: The word to find placements for.
-
+
Returns:
The placements that were obtained.
"""
@@ -464,7 +467,7 @@ def _get_placements(self, word: str) -> Union[List[Placement], List[None]]:
def _add_data(self, placement: Placement) -> None:
"""Add placement information to `self.data`, extracted from `placement`.
-
+
Args:
placement: The placement to extract data from.
"""
@@ -480,7 +483,7 @@ def _populate_grid(
) -> None:
"""Attempt to all the words in the grid, recursing once to retry the
placement of words with no intersections.
-
+
Args:
words: The randomly sampled words to insert.
insert_backlog: Whether to insert the backlog or not.
diff --git a/src/xpuz/errors.py b/src/xpuz/errors.py
index 07a72dc4..d23f2623 100644
--- a/src/xpuz/errors.py
+++ b/src/xpuz/errors.py
@@ -3,11 +3,13 @@
class CrosswordGenerationError(Exception):
"""Generic error class for errors related to crossword generation."""
+
pass
class DefinitionsParsingError(Exception):
- """Generic error class for errors related to the parsing of a crossword's
+ """Generic error class for errors related to the parsing of a crossword's
definitions.
"""
+
pass
diff --git a/src/xpuz/import_export.py b/src/xpuz/import_export.py
index a7cbb414..f10e97ff 100644
--- a/src/xpuz/import_export.py
+++ b/src/xpuz/import_export.py
@@ -15,7 +15,7 @@ class Export(list):
def __init__(self, blocks: List["UserCrosswordBlock"]) -> None:
"""Initialise the `self.blocks` array and export-related booleans.
-
+
Args:
blocks: The available user crossword blocks
"""
@@ -79,7 +79,7 @@ class Import:
def __init__(self, master: "CrosswordPane", fp: PathLike) -> None:
"""Initialise import-related booleans and lists.
-
+
Args:
master: The instance of the crossword pane.
fp: The filepath to which the crosswords will be imported.
@@ -145,7 +145,7 @@ def _import(self) -> None:
def _write(self, crosswords: Any) -> None:
"""Write ``crosswords`` to ``self.fp``, collecting information on invalid
and conflicting crosswords.
-
+
Args:
crosswords: The crosswords to import.
"""
diff --git a/src/xpuz/ipuz.py b/src/xpuz/ipuz.py
index 53d302da..c5d5e011 100644
--- a/src/xpuz/ipuz.py
+++ b/src/xpuz/ipuz.py
@@ -12,6 +12,7 @@
class IPuz(dict):
"""Export a generated crossword in ``ipuz`` format."""
+
def __init__(
self,
cwrapper: CrosswordWrapper,
@@ -20,12 +21,15 @@ def __init__(
definitions_d: List[Dict[int, Tuple[str]]],
) -> None:
"""Initialise crossword data and the crossword wrapper object.
-
+
Args:
cwrapper: The crossword wrapper.
- starting_word_matrix: [read this function](utils.md#xpuz.utils._interpret_cword_data)
- definitions_a: [read this function](utils.md#xpuz.utils._interpret_cword_data)
- definitions_d: [read this function](utils.md#xpuz.utils._interpret_cword_data)
+ starting_word_matrix:
+ [read this function](utils.md#xpuz.utils._interpret_cword_data)
+ definitions_a:
+ [read this function](utils.md#xpuz.utils._interpret_cword_data)
+ definitions_d:
+ [read this function](utils.md#xpuz.utils._interpret_cword_data)
"""
self.cwrapper = cwrapper
self.crossword = self.cwrapper.crossword
diff --git a/src/xpuz/pages/browser.py b/src/xpuz/pages/browser.py
index 7da7cec0..53358be3 100644
--- a/src/xpuz/pages/browser.py
+++ b/src/xpuz/pages/browser.py
@@ -581,15 +581,17 @@ def terminate(self) -> None:
self.webapp_on: bool = False
def _export(self) -> None:
- export: str = _get_english_string(BASE_ENG_EXPORTS, self.exports, self.export_pref.get())
+ export: str = _get_english_string(
+ BASE_ENG_EXPORTS, self.exports, self.export_pref.get()
+ )
if export == BASE_ENG_EXPORTS[0]:
self._export_pdf()
else:
self._export_ipuz()
def _export_ipuz(self) -> None:
- from xpuz.ipuz import IPuz
-
+ from xpuz.ipuz import IPuz
+
IPuz(
self.cwrapper,
self.starting_word_matrix,
diff --git a/src/xpuz/pages/home.py b/src/xpuz/pages/home.py
index 9becd7d7..d7f80e11 100644
--- a/src/xpuz/pages/home.py
+++ b/src/xpuz/pages/home.py
@@ -1,4 +1,4 @@
-"""Default GUI page for ``xpuz``. Provides global configuration options and
+"""Default GUI page for ``xpuz``. Provides global configuration options and
routing buttons to other available pages.
"""
diff --git a/src/xpuz/pdf.py b/src/xpuz/pdf.py
index 7ff2d6b3..abdc1dc8 100644
--- a/src/xpuz/pdf.py
+++ b/src/xpuz/pdf.py
@@ -40,15 +40,19 @@ def __init__(
definitions_d: List[Dict[int, Tuple[str]]],
) -> None:
"""Initialise the crossword data and the crossword wrapper object.
-
+
Args:
cwrapper: The crossword wrapper.
- starting_word_positions: [read this function](utils.md#xpuz.utils._interpret_cword_data)
- starting_word_matrix: [read this function](utils.md#xpuz.utils._interpret_cword_data)
- definitions_a: [read this function](utils.md#xpuz.utils._interpret_cword_data)
- definitions_d: [read this function](utils.md#xpuz.utils._interpret_cword_data)
+ starting_word_positions:
+ [read this function](utils.md#xpuz.utils._interpret_cword_data)
+ starting_word_matrix:
+ [read this function](utils.md#xpuz.utils._interpret_cword_data)
+ definitions_a:
+ [read this function](utils.md#xpuz.utils._interpret_cword_data)
+ definitions_d:
+ [read this function](utils.md#xpuz.utils._interpret_cword_data)
"""
-
+
self.cwrapper = cwrapper
self.crossword = self.cwrapper.crossword
self.grid: List[List[str]] = self.crossword.grid
@@ -113,8 +117,8 @@ def _set_font_face(
slant: str = FONT_SLANT_NORMAL,
weight: str = FONT_WEIGHT_BOLD,
) -> None:
- """Set the font that is used by `pycairo`.
-
+ """Set the font that is used by `pycairo`.
+
Args:
family: The font family.
slant: The font slant.
@@ -140,8 +144,8 @@ def _draw_all(self) -> None:
def _draw_grid(self, with_answers: bool = False) -> None:
"""Draw the crossword grid in the center of the page.
-
- Args:
+
+ Args:
with_answers: Whether to draw this current part of the crossword PDF
with answers in the grid or not.
"""
@@ -185,7 +189,7 @@ def _draw_grid(self, with_answers: bool = False) -> None:
def _draw_cell_letter(self, row: int, col: int) -> None:
"""Draw the letter at `self.grid[row][col]`.
-
+
Args:
row: The row, used as a reference to determine the drawing location.
col: The column, used as a reference to determine the drawing location.
@@ -208,7 +212,7 @@ def _draw_cell_letter(self, row: int, col: int) -> None:
def _draw_number_label(self, row: int, col: int) -> None:
"""Draw a number label in the top left hand corner of the cell at ``row``
and ``col``.
-
+
Args:
row: The row, used as a reference to determine the drawing location.
col: The column, used as a reference to determine the drawing location.
@@ -245,7 +249,7 @@ def _draw_grid_lines(self) -> None:
def _draw_display_name(self, name: str) -> None:
"""Draw ``name`` at the top of the current page.
-
+
Args:
name: The display name.
"""
@@ -300,7 +304,7 @@ def _draw_definitions_col(
"""Draw either the across or down definitions column.
DISCLAIMER: Does not provide wrapping for clues.
-
+
Args:
definitions: The definitions for either the across or down column.
dir_title: The title for the column.
diff --git a/src/xpuz/td.py b/src/xpuz/td.py
index 55d65b0e..a574eaeb 100644
--- a/src/xpuz/td.py
+++ b/src/xpuz/td.py
@@ -13,14 +13,14 @@
class Placement(TypedDict):
"""A dictionary specifying the placement information of `word` at `pos`
in the grid.
-
+
Args:
word (str): The word.
direction (Union[ACROSS, DOWN]): The direction of the word.
pos (Tuple[int, int]): The position of the word in (row, column) form.
- intersections (Union[List[None], List[Tuple[int, int]]]):
- The intersecting points that `word` has with a grid array in
- (row, column) form.
+ intersections (Union[List[None], List[Tuple[int, int]]]):
+ The intersecting points that `word` has with a grid array in
+ (row, column) form.
"""
word: str
@@ -31,7 +31,7 @@ class Placement(TypedDict):
class CrosswordData(TypedDict):
"""The JSON serialised definitions and info of a base crossword.
-
+
Args:
definitions (Dict[str, str]): The crossword's definitions.
info (Dict[str, Union[str, int, None]]): The crossword's info.
@@ -43,7 +43,7 @@ class CrosswordData(TypedDict):
class CrosswordInfo(TypedDict):
"""A crossword's information.
-
+
Example:
```json
{
@@ -55,16 +55,16 @@ class CrosswordInfo(TypedDict):
"category": "science"
}
```
-
+
Args:
total_definitions (int): The total amount of definitions available for
- the crossword.
+ the crossword.
difficulty (int): An integer ranging from 0-3 (Easy, Medium, Hard, Extreme)
- symbol (str): A hexadecimal stored in a string, representing the crossword's
+ symbol (str): A hexadecimal stored in a string, representing the crossword's
symbol. This value is converted to an integer at runtime.
name (str): The crossword's english name.
translated_name (str): The crossword's translated name.
- category (str): The crossword's category (Geography, Computer Science,
+ category (str): The crossword's category (Geography, Computer Science,
Mathematics, Science, or User))
"""
@@ -75,13 +75,14 @@ class CrosswordInfo(TypedDict):
translated_name: Union[None, str]
category: str
+
class IPuzV2(TypedDict):
"""The `ipuz` v2 structure (JSON).
-
+
Args:
version (str): The version of the ipuz format, stored as a url. Defaults
to [ipuz.org/v2](http://ipuz.org/v2)
- kind (List[str]): The puzzle format. Defaults to
+ kind (List[str]): The puzzle format. Defaults to
[crossword#1](http://ipuz.org/crossword#1)
origin (str): A link to the puzzle's origin. Default to the
[xpuz repository](https://github.com/tomasvana10/xpuz)
@@ -95,7 +96,7 @@ class IPuzV2(TypedDict):
solution (List[List[Union[str, None]]]): The solution to the puzzle.
clues (Dict[str, List[List[Union[int, str]]]]): The puzzle's clues.
"""
-
+
version: str
kind: List[str]
origin: str
@@ -107,11 +108,11 @@ class IPuzV2(TypedDict):
puzzle: List[List[Union[int, None]]]
solution: List[List[Union[str, None]]]
clues: Dict[str, List[List[Union[int, str]]]]
-
+
@classmethod
def create(
- cls,
- version: str = "http://ipuz.org/v2",
+ cls,
+ version: str = "http://ipuz.org/v2",
kind: List[str] = ["http://ipuz.org/crossword#1"],
origin: str = PROJECT_URL,
author: str = "xpuz Crossword Generator",
@@ -119,13 +120,13 @@ def create(
) -> "IPuzV2":
"""Return an instance of `IPuzV2` with the standard parameters already
defined through the method's default arguments.
-
+
Args:
version: The puzzle's version.
kind: The puzzle's kind.
origin: The puzzle's source of creation.
author: The puzzle's author.
- **kwargs: Remaining arguments that are covered in
+ **kwargs: Remaining arguments that are covered in
[IPuzV2](td.md#xpuz.td.IPuzV2)
"""
return cls(
diff --git a/src/xpuz/utils.py b/src/xpuz/utils.py
index a3e1571f..55f09c38 100644
--- a/src/xpuz/utils.py
+++ b/src/xpuz/utils.py
@@ -10,7 +10,17 @@
from platform import system
from random import randint, sample
from tkinter import messagebox, filedialog
-from typing import Callable, Dict, Iterable, List, Optional, Tuple, Union, Literal, Any
+from typing import (
+ Callable,
+ Dict,
+ Iterable,
+ List,
+ Optional,
+ Tuple,
+ Union,
+ Literal,
+ Any,
+)
from urllib.error import URLError
from babel import Locale
@@ -46,8 +56,8 @@ class GUIHelper:
@staticmethod
def _install_translations(locale: Locale) -> None:
"""Install translations from ``locale.language`` with gettext.
-
- Args:
+
+ Args:
locale: The current locale object.
"""
translation(
@@ -58,15 +68,17 @@ def _install_translations(locale: Locale) -> None:
).install()
@staticmethod
- def confirm_with_messagebox(*args: Tuple[str], **kwargs: Dict[str, str]) -> bool:
+ def confirm_with_messagebox(
+ *args: Tuple[str], **kwargs: Dict[str, str]
+ ) -> bool:
"""Provide confirmations to the user with tkinter messageboxes.
-
- Args:
+
+ Args:
*args: Optional info messages to be included with specific messagebox
calls.
- **kwargs: The specific messagebox name, selected by this method's
+ **kwargs: The specific messagebox name, selected by this method's
`if` statements.
-
+
Returns:
Whether the user confirmed/pressed yes on the messagebox or not.
"""
@@ -130,11 +142,11 @@ def confirm_with_messagebox(*args: Tuple[str], **kwargs: Dict[str, str]) -> bool
@staticmethod
def show_messagebox(*args: Tuple[str], **kwargs: Dict[str, str]) -> None:
"""Show an error/info messagebox
-
- Args:
- *args: Optional error messages/details to be included with specific
+
+ Args:
+ *args: Optional error messages/details to be included with specific
messagebox calls.
- **kwargs: The specific messagebox name, selected by this method's
+ **kwargs: The specific messagebox name, selected by this method's
`if` statements.
"""
if "same_lang" in kwargs:
@@ -255,12 +267,9 @@ def show_messagebox(*args: Tuple[str], **kwargs: Dict[str, str]) -> None:
)
+ ": https://pycairo.readthedocs.io/en/latest/getting_started.html",
)
-
+
if "ipuz_write_success" in kwargs:
- return messagebox.showinfo(
- _("Info"),
- _("Successfully wrote ipuz")
- )
+ return messagebox.showinfo(_("Info"), _("Successfully wrote ipuz"))
if "first_time_browser" in kwargs:
return messagebox.showinfo(
@@ -306,14 +315,14 @@ def _match_block_query(query: str, block_name: str, category: str) -> bool:
it consists of) starts with ``query``, or if ``category`` starts with
``query``. All comparisons are caseless and do not regard whitespace
(except the category, which keeps its whitespace).
-
+
Args:
query: A query entered by the user.
block_name: The current block name that is being queried.
category: The category of the current block name that is being queried.
-
+
Returns:
- Whether the query was found in the category or block name, or not.
+ Whether the query was found in the category or block name, or not.
"""
formatted_query = query.strip().casefold()
return any(
@@ -325,10 +334,10 @@ def _match_block_query(query: str, block_name: str, category: str) -> bool:
def _put_block(cls, block: CTkFrame, side: str = "left") -> None:
"""Pack ``block`` in its parent container and append it to the available
blocks in ``cls``.
-
+
Args:
- block: The block instance to be packed.
- side: The side to pack the block. `"top"` for the crossword editor
+ block: The block instance to be packed.
+ side: The side to pack the block. `"top"` for the crossword editor
panes, and `"left"` for the crossword browser container.
"""
block.pack(side=side, padx=5, pady=(5, 0))
@@ -338,7 +347,7 @@ def _put_block(cls, block: CTkFrame, side: str = "left") -> None:
def _remove_block(cls, block: CTkFrame) -> None:
"""Remove ``block`` from its parent container and the available blocks
in ``cls``.
-
+
Args:
block: The block to remove.
"""
@@ -352,8 +361,8 @@ def _set_all(
) -> None:
"""Call ``func``, passing each block in ``cls.blocks`` as parameters.
Most often used to put or remove all of the blocks in ``cls.blocks``.
-
- Args:
+
+ Args:
func: The function to perform on the block.
"""
for block in [
@@ -366,7 +375,7 @@ def _set_all(
@classmethod
def _config_selectors(cls, **kwargs: Dict[str, Any]) -> None:
"""Enable or disable all the radiobutton selectors in ``cls.blocks``.
-
+
Args:
**kwargs: Configuration parameters.
"""
@@ -376,8 +385,8 @@ def _config_selectors(cls, **kwargs: Dict[str, Any]) -> None:
def _open_file(fp: PathLike) -> None:
"""Open ``fp`` (directory) in the OS' default file explorer.
-
- Args:
+
+ Args:
fp: The filepath to open.
"""
plat: str = system()
@@ -394,9 +403,11 @@ def _open_file(fp: PathLike) -> None:
os_system("xdg-open %s" % fp)
-def _get_saveas_filename(title: str, name: str, extension: str, filetypes: List[Tuple[str]]) -> Union[str, PathLike]:
+def _get_saveas_filename(
+ title: str, name: str, extension: str, filetypes: List[Tuple[str]]
+) -> Union[str, PathLike]:
"""Get user input for a file save location.
-
+
Args:
title: The file explorer's titlebar text.
name: The default file name.
@@ -412,9 +423,11 @@ def _get_saveas_filename(title: str, name: str, extension: str, filetypes: List[
)
-def _get_open_filename(title: str, filetypes: List[Tuple[str]]) -> Union[str, PathLike]:
+def _get_open_filename(
+ title: str, filetypes: List[Tuple[str]]
+) -> Union[str, PathLike]:
"""Get user input for the location to a file that is to be opened.
-
+
Args:
title: The file explorer's titlebar text.
filetypes: Available filetypes to display.
@@ -432,12 +445,12 @@ def _get_english_string(
"""Find the english version of ``index_value`` by finding its index in
``localised_arr``, then using the resulting integer to index ``eng_arr``.
This function assumes both arrays have the same relative order.
-
+
Args:
eng_arr: The default english values.
localised_arr: The localised values.
index_value: The position of the localised string within `localised_arr`.
-
+
Returns:
The english string that was indexed.
"""
@@ -447,7 +460,7 @@ def _get_english_string(
def _check_version() -> Union[None, str]:
"""Find latest remote GitHub release if it is higher than the local
release using the ``urllib`` module.
-
+
Returns:
The latest release, if it was found. Otherwise, returns `None`.
"""
@@ -465,7 +478,10 @@ def _check_version() -> Union[None, str]:
# Any component of the remote semver'd tag is greater than that of the
# local tag (MAJOR or MINOR or PATCH), meaning a new version has been
# made, so, return the remote version.
- if any(int(item[0]) > int(item[1]) for item in list(zip(remote_ver, local_ver))):
+ if any(
+ int(item[0]) > int(item[1])
+ for item in list(zip(remote_ver, local_ver))
+ ):
return data["name"]
return None # ``response.status`` wasn't 200, meaning some error occurred.
@@ -480,16 +496,16 @@ def _doc_data_routine(
) -> bool:
"""Scan through both the package and system document directories, making
the required folders if needed.
-
+
Args:
doc_callback: A function to execute if possible when scanning the system's
document directory to make missing files.
- local_callback: A function to execute if possible when scanning the
+ local_callback: A function to execute if possible when scanning the
local data of the `xpuz` package to make missing files.
toplevel: The path of the system's document directory.
datalevel: The path to the data files within `toplevel`
sublevel: The path to `config.ini` within `toplevel`.
-
+
Returns:
Whether the document data has been successfully made or not.
"""
@@ -504,19 +520,15 @@ def _doc_data_routine(
return False # Cannot continue, as Documents do not exist
# If the code reached this point, it means a Documents folder must exist
- if not path.exists(
- datalevel
- ): # Attempt to make the ``xpuz`` dir in Documents
+ if not path.exists(datalevel): # Attempt to make the ``xpuz`` dir in Documents
mkdir(DOC_DATA_PATH)
- if not path.exists(
- sublevel
- ): # The required sub-directory doesn't exist yet
- # in Documents
+ if not path.exists(sublevel): # The required sub-directory doesn't exist
+ # yet in Documents
if doc_callback:
try:
doc_callback() # Attempt to make the required sub-directory
- # eg ``xpuz/user`` for user crosswords
+ # eg ``xpuz/user`` for user crosswords
except OSError:
pass
@@ -526,7 +538,7 @@ def _doc_data_routine(
def _check_doc_cfg_is_up_to_date() -> bool:
"""Check if the all the sections (and values of those sections) are present
in the document config.ini file.
-
+
Returns:
Whether the config.ini in the system's documents directory is up-to-date
or not.
@@ -570,7 +582,7 @@ def _update_cfg(
) -> None:
"""Update ``cfg`` at the given section, option and value, then write it
to an available config path.
-
+
Args:
section: The section to update.
option: The option to update.
@@ -594,8 +606,8 @@ def _read_cfg(cfg: ConfigParser) -> None:
"""Determine which config file to access (whether it is
``template.config.ini`` in the package or ``config.ini`` in the system
documents directory), and write its contents to ``cfg``.
-
- Args:
+
+ Args:
cfg: The config parser instance.
"""
# Documents directory unavailable
@@ -609,7 +621,7 @@ def _read_cfg(cfg: ConfigParser) -> None:
def _get_base_categories() -> Iterable[DirEntry]:
"""Get all the available crossword categories sorted alphabetically.
-
+
Returns:
All the directory entries to the available crossword categories. They
can be sourced from both the package and the system's data.
@@ -636,18 +648,18 @@ def _get_base_categories() -> Iterable[DirEntry]:
def _sort_crosswords_by_suffix(
- cwords: Union[List[DirEntry], List[Tuple[DirEntry, DirEntry]]]
+ cwords: Union[List[DirEntry], List[Tuple[DirEntry, DirEntry]]],
) -> Union[List[DirEntry], List[Tuple[DirEntry, DirEntry]]]:
"""Sort an iterable container with crossword directory entries based on
the crossword's suffix (from -easy to -extreme, if possible).
-
+
Args:
cwords: A list of directory entries of crosswords, or an array of
tuples with lists of both category entries **and** crossword
entries, if sorting all available crosswords.
-
+
Returns:
- The unsorted crosswords if any one of them is missing a suffix, or the
+ The unsorted crosswords if any one of them is missing a suffix, or the
sorted crosswords in the same structure they were passed to the function.
"""
try:
@@ -671,13 +683,13 @@ def _get_base_crosswords(
) -> Iterable[DirEntry]:
"""Get all the available crosswords from the base crossword directory if
they have valid ``definitions.json`` files.
-
+
Args:
category: The path/directory entry to the category.
sort: Whether to sort the obtained crosswords or not.
allow_empty_defs: Consider a crossword with no definitions to be valid
if it is user made.
-
+
Returns:
The acquired crosswords, sorted or unsorted, based on if any errors
occurred during the sorting process.
@@ -706,9 +718,9 @@ def _get_base_crosswords(
def _make_cword_info_json(
fp: PathLike, cword_name: str, category: str
) -> None:
- """Make an info.json file for a given crossword, since it doesn't exist.
+ """Make an info.json file for a given crossword, since it doesn't exist.
Infer any required information that is not passed by the caller.
-
+
Args:
fp: The path to write the info to.
cword_name: The name of the crossword.
@@ -755,7 +767,7 @@ def _update_cword_info_word_count(
"""Update the word count in a crossword's `info.json` file if it is
inconsistent with the amount of key-pair values in its `definitions.json`
file.
-
+
Args:
fp: The toplevel of the crossword.
info: The existing info of the crossword.
@@ -769,7 +781,7 @@ def _update_cword_info_word_count(
def _make_category_info_json(fp: PathLike, hex_: str = None) -> None:
"""Write a new info.json to a category since it does not exist in the a
category's directory.
-
+
Args:
fp: The path to write the category's `info.json` file to.
hex_: A hexadecimal colour value stored in a string, which represents
@@ -786,7 +798,7 @@ def _load_attempts_db() -> Dict[str, int]:
should be conducted for a crossword based on its word count. This is
integral to the crossword optimisation process, as crossword generation
time scales logarithmically with word count.
-
+
Returns:
The attempts dictionary.
"""
@@ -799,16 +811,16 @@ def _get_language_options() -> Tuple[Dict[str, str], List[str]]:
"""Gather a dictionary that maps each localised language name to its
english acronym, and a list that contains all of the localised language
names. This data is derived from ``LOCALES_PATH``.
-
+
Returns:
The localised language dictionary and the localised languages list.
"""
localised_lang_db: Dict[str, str] = {} # Used to retrieve the language
- # code for the selected language
- # e.x. {"አማርኛ": "am",}
+ # code for the selected language
+ # e.x. {"አማርኛ": "am",}
localised_langs: List[str] = [] # Used in the language selection
- # optionmenu
- # e.x. ["አማርኛ", "عربي"]
+ # optionmenu
+ # e.x. ["አማርኛ", "عربي"]
i: int = 0
for locale in sorted(
@@ -829,13 +841,15 @@ def _get_language_options() -> Tuple[Dict[str, str], List[str]]:
def _get_colour_palette(
- appearance_mode: Union[Literal["Light"], Literal["Dark"], Literal["System"]]
+ appearance_mode: Union[
+ Literal["Light"], Literal["Dark"], Literal["System"]
+ ],
) -> Dict[str, str]:
"""Create a dictionary based on ``constants.Colour`` for the web app.
-
+
Args:
appearance_mode: The current tkinter appearance mode.
-
+
Returns:
A colour code dictionary.
"""
@@ -854,11 +868,11 @@ def _find_best_crossword(
"""Determine the best crossword out of a amount of instantiated
crosswords based on the largest amount of total intersections and
smallest amount of fails.
-
+
Args:
crossword: The `Crossword` instance to perform the optimised creation on.
cls: The `Crossword` class.
-
+
Returns:
The best `Crossword` instance that was found.
"""
@@ -923,15 +937,15 @@ def _find_best_crossword(
return best_crossword
-def _interpret_cword_data(crossword: "Crossword") -> Tuple[
- List[Tuple[int]], List[Dict[int, Tuple[str]]], List[List[int]]
- ]:
+def _interpret_cword_data(
+ crossword: "Crossword",
+) -> Tuple[List[Tuple[int]], List[Dict[int, Tuple[str]]], List[List[int]]]:
"""Gather data to help with the templated creation of the crossword
web application.
-
+
Args:
crossword: The `Crossword` instance to gather data on.
-
+
Returns:
The interpreted crossword data. Please view the source code below for
more information.
@@ -949,7 +963,7 @@ def _interpret_cword_data(crossword: "Crossword") -> Tuple[
num_label: int = (
1 # Incremented whenever the start of a word is found;
- # used to create ``starting_word_matrix``.
+ # used to create ``starting_word_matrix``.
)
for row in range(crossword.dimensions):
for column in range(crossword.dimensions):
@@ -997,31 +1011,29 @@ def _randomise_definitions(definitions: Dict[str, str]) -> Dict[str, str]:
"""Randomises the existing definitions when attempting reinsertion,
which prevents ``_find_best_crossword`` from favouring certain word
groups with intrinsically higher intersections.
-
+
Args:
definitions: The crossword's definitions.
-
+
Returns:
The randomised crossword definitions.
"""
return dict(sample(list(definitions.items()), len(definitions)))
-def _verify_definitions(
- definitions: Dict[str, str], word_count: int
-) -> None:
+def _verify_definitions(definitions: Dict[str, str], word_count: int) -> None:
"""Process a dictionary of definitions through statements to raise
errors for particular edge cases in a definitions dictionary. This
function also uses ``_format_definitions`` to randomly sample a specified
amount of definitions from the definitions dictionary, then format
those definitions appropriately.
-
+
Args:
definitions: The crossword's definitions.
word_count: The crossword's word count.
-
+
Raises:
- DefinitionsParsingError: If the definitions are invalid. Please view the
+ DefinitionsParsingError: If the definitions are invalid. Please view the
source code below for more information.
"""
# Required error checking
@@ -1045,11 +1057,11 @@ def _format_definitions(
"""Randomly pick definitions from a larger sample, then prune
everything except the language characters from the words (the keys of
the definitions).
-
+
Args:
definitions: The crossword's definitions.
word_count: The crossword's word count.
-
+
Returns:
The formatted crossword definitions.
"""
diff --git a/src/xpuz/wrappers.py b/src/xpuz/wrappers.py
index 786b920d..cdf12f1f 100644
--- a/src/xpuz/wrappers.py
+++ b/src/xpuz/wrappers.py
@@ -30,8 +30,8 @@ class CrosswordWrapper:
"""
helper: Union[None, object] = None # Set to ``main.GUIHelper`` at runtime
- # (if using the GUI)
- logger: object = lambda *args, **kwargs: print(f"{args[0]}({args[1]})")
+ # (if using the GUI)
+ logger: object = lambda *args, **kwargs: print(f"{args[0]}({args[1]})")
def __init__(
self,
@@ -45,16 +45,16 @@ def __init__(
value: int = None,
) -> None:
"""Initialise the crossword's data and prime the instance for generation.
-
+
Args:
category: The crossword's category.
name: The crossword's name.
word_count: The crossword's word count.
language: The crossword's language in `ISO 639` format (probably)
- optimise: Whether to run
+ optimise: Whether to run
[_find_best_crossword](utils.md#xpuz.utils._find_best_crossword)
or not.
- category_object: The crossword category block that "contains" this
+ category_object: The crossword category block that "contains" this
wrapper's crossword. This wrapper itself was generated
when its crossword block was instantiated.
value: The value of this crossword (ranging from 0-~10), used by
@@ -80,12 +80,14 @@ def __init__(
self.translated_name: str = self.info["translated_name"] or self.name
self.difficulty: str = DIFFICULTIES[self.info["difficulty"]]
self.translated_difficulty = _(self.difficulty)
- self.display_name: str = f"{self.translated_name} ({_(self.difficulty)})"
+ self.display_name: str = (
+ f"{self.translated_name} ({_(self.difficulty)})"
+ )
def __str__(self) -> str:
"""Display a dev-friendly representation of this `CrosswordWrapper` and
its attributes
-
+
Returns:
The representation.
"""
@@ -102,7 +104,7 @@ def __str__(self) -> str:
def set_word_count(self, count: int) -> None:
"""Set this wrapper's word count. Called when the user changes their
word count preference.
-
+
Args:
count: The word count.
"""
@@ -146,12 +148,12 @@ def _get_toplevel(self) -> PathLike:
(e.g `/locales/geography/capitals-easy`).
The path returned will be in 1 of 3 locations:
-
+
1. Locales directory (if it is found),
2. Base crossword directory (if not localised version is present),
3. The system's document directory (if it is available and the crossword
belongs to the `User` category).
-
+
Returns:
The path to the toplevel of this crossword.
"""
@@ -174,7 +176,7 @@ def _get_toplevel(self) -> PathLike:
return toplevel
def make(self) -> Union[None, Crossword]:
- """Generate a crossword, running
+ """Generate a crossword, running
[_find_best_crossword](utils.md#xpuz.utils._find_best_crossword) if
`self.optimise` is set to True (it is by default). Any errors caught
are relayed to the main GUI through the helper attribute of
@@ -206,7 +208,7 @@ def make(self) -> Union[None, Crossword]:
def cells(self) -> str:
"""Return the representation of `self.crossword`'s cells. Essentially a
router method for `crossword.cells`
-
+
Returns:
The cells.
"""
@@ -215,7 +217,7 @@ def cells(self) -> str:
@property
def definitions(self) -> Dict[str, str]:
"""Read the current definitions of the crossword.
-
+
Returns:
The crossword's definitions.
"""
@@ -225,7 +227,7 @@ def definitions(self) -> Dict[str, str]:
@property
def info(self) -> CrosswordInfo:
"""Read the current info of the crossword, checking it if it's invalid.
-
+
Returns:
The crossword's info.
"""