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 PySide6.QtCore import Qt
from .config import Config from .config import Config
from .args import Args
from .utils import Utils from .utils import Utils
from .ants import Ant from .ants import Ant
from .ants import Ants from .ants import Ants
@ -91,11 +92,15 @@ class Game:
container = QHBoxLayout() container = QHBoxLayout()
root.setContentsMargins(0, 0, 0, 0) root.setContentsMargins(0, 0, 0, 0)
container.setContentsMargins(0, 0, 0, 0) container.setContentsMargins(0, 0, 0, 0)
if Args.images:
image_label = Game.get_image(ant) image_label = Game.get_image(ant)
right_container = Game.make_right_container(ant)
container.addWidget(image_label) container.addWidget(image_label)
container.addSpacing(Config.space_1)
right_container = Game.make_right_container(ant)
container.addWidget(right_container) container.addWidget(right_container)
container.addSpacing(Config.space_1)
root.setLayout(container) root.setLayout(container)
Game.add_item(root) Game.add_item(root)

View File

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

View File

@ -8,6 +8,7 @@ from .config import Config
if TYPE_CHECKING: if TYPE_CHECKING:
from .ants import Ant from .ants import Ant
from .args import Args
from .utils import Utils from .utils import Utils
@ -30,7 +31,13 @@ class Storage:
@staticmethod @staticmethod
def get_names() -> Any: 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) return json.load(file)
@staticmethod @staticmethod

View File

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