This commit is contained in:
Auric Vente 2024-07-25 05:41:47 -06:00
parent 522297aa33
commit c97c6d0a70
6 changed files with 213 additions and 4 deletions

90
cromulant/args.py Normal file
View File

@ -0,0 +1,90 @@
from __future__ import annotations
import argparse
from pathlib import Path
from typing import Any
from .config import Config
from .argspec import ArgSpec
class Args:
names: Path
images: bool = True
@staticmethod
def prepare() -> None:
ArgSpec.prepare()
ArgParser.prepare(Config.title, ArgSpec.arguments)
for attr_name, attr_value in vars(Args).items():
ArgSpec.defaults[attr_name] = attr_value
other_name = [
("no_images", "images"),
]
for r_item in other_name:
ArgParser.get_value(*r_item)
paths = [
"names",
]
for n_item in paths:
ArgParser.get_value(n_item, path=True)
class ArgParser:
parser: argparse.ArgumentParser
args: argparse.Namespace
@staticmethod
def prepare(title: str, argdefs: dict[str, Any]) -> None:
parser = argparse.ArgumentParser(description=title)
argdefs["string_arg"] = {"nargs": "*"}
for key in argdefs:
item = argdefs[key]
if key == "string_arg":
name = key
else:
name = ArgParser.under_to_dash(key)
name = f"--{name}"
tail = {key: value for key, value in item.items() if value is not None}
parser.add_argument(name, **tail)
ArgParser.parser = parser
ArgParser.args = parser.parse_args()
@staticmethod
def string_arg() -> str:
return " ".join(ArgParser.args.string_arg)
@staticmethod
def get_value(
attr: str, key: str | None = None, no_strip: bool = False, path: bool = False
) -> None:
value = getattr(ArgParser.args, attr)
if value is not None:
if not no_strip:
if isinstance(value, str):
value = value.strip()
obj = key if key else attr
if path:
value = Path(value)
ArgParser.set(obj, value)
@staticmethod
def set(attr: str, value: Any) -> None:
setattr(Args, attr, value)
@staticmethod
def under_to_dash(s: str) -> str:
return s.replace("_", "-")

83
cromulant/argspec.py Normal file
View File

@ -0,0 +1,83 @@
from __future__ import annotations
from typing import Any
from .config import Config
class DuplicateArgumentError(Exception):
def __init__(self, key: str) -> None:
self.message = f"Duplicate argument: {key}"
def __str__(self) -> str:
return self.message
class MissingInfoError(Exception):
def __init__(self, key: str) -> None:
self.message = f"Missing info for argument: {key}"
def __str__(self) -> str:
return self.message
class DuplicateInfoError(Exception):
def __init__(self, key: str) -> None:
self.message = f"Duplicate info for argument: {key}"
def __str__(self) -> str:
return self.message
class ArgSpec:
vinfo: str
defaults: dict[str, Any]
arguments: dict[str, Any]
infos: list[str]
@staticmethod
def prepare() -> None:
ArgSpec.vinfo = f"{Config.title} {Config.version}"
ArgSpec.defaults = {}
ArgSpec.arguments = {}
ArgSpec.infos = []
ArgSpec.add_arguments()
@staticmethod
def add_argument(key: str, info: str, **kwargs: Any) -> None:
if key in ArgSpec.arguments:
raise DuplicateArgumentError(key)
if not info:
raise MissingInfoError(key)
if info in ArgSpec.infos:
raise DuplicateInfoError(key)
ArgSpec.arguments[key] = {
"help": info,
**kwargs,
}
ArgSpec.infos.append(info)
@staticmethod
def add_arguments() -> None:
ArgSpec.add_argument(
"version",
action="version",
info="Check the version of the program",
version=ArgSpec.vinfo,
)
ArgSpec.add_argument(
"names",
type=str,
info="Path to a JSON files with a list of names. The game will use these names instead of the default ones",
)
ArgSpec.add_argument(
"no_images",
action="store_false",
info="Don't show the images on the left",
)

View File

@ -17,6 +17,7 @@ from PySide6.QtCore import QTimer # type: ignore
from PySide6.QtCore import Qt
from .config import Config
from .args import Args
from .utils import Utils
from .ants import Ant
from .ants import Ants
@ -91,11 +92,15 @@ class Game:
container = QHBoxLayout()
root.setContentsMargins(0, 0, 0, 0)
container.setContentsMargins(0, 0, 0, 0)
if Args.images:
image_label = Game.get_image(ant)
right_container = Game.make_right_container(ant)
container.addWidget(image_label)
container.addSpacing(Config.space_1)
right_container = Game.make_right_container(ant)
container.addWidget(right_container)
container.addSpacing(Config.space_1)
root.setLayout(container)
Game.add_item(root)

View File

@ -13,10 +13,12 @@ from .window import Window
from .game import Game
from .settings import Settings
from .filter import Filter
from .args import Args
def main() -> None:
Config.prepare()
Args.prepare()
program = Config.program
title = Config.title

View File

@ -8,6 +8,7 @@ from .config import Config
if TYPE_CHECKING:
from .ants import Ant
from .args import Args
from .utils import Utils
@ -30,7 +31,13 @@ class Storage:
@staticmethod
def get_names() -> Any:
with Config.names_json.open() as file:
path = Config.names_json
if Args.names:
if Args.names.exists():
path = Args.names
with path.open() as file:
return json.load(file)
@staticmethod

View File

@ -17,6 +17,8 @@ class Utils:
countries: ClassVar[list[str]] = []
rand_word: RandomWord
rand_sentence: RandomSentence
vowels = "aeiou"
consonants = "bcdfghjklmnpqrstvwxyz"
@staticmethod
def prepare() -> None:
@ -103,6 +105,10 @@ class Utils:
names.append(name)
filtered = [name for name in Utils.names if name not in ignore]
if not filtered:
return Utils.make_name()
return random.choice(filtered)
@staticmethod
@ -185,3 +191,19 @@ class Utils:
@staticmethod
def words_4() -> str:
return str(Utils.rand_sentence.sentence())
@staticmethod
def make_word() -> str:
name = ""
name += random.choice(Utils.consonants)
name += random.choice(Utils.vowels)
name += random.choice(Utils.consonants)
name += random.choice(Utils.vowels)
return name
@staticmethod
def make_name() -> str:
word_1 = Utils.make_word()
word_2 = Utils.make_word()
return f"{Utils.capitalize(word_1)} {Utils.capitalize(word_2)}"