From 1217c73c17758bff6cce223d11be8a08ca2cfe3c Mon Sep 17 00:00:00 2001 From: evilchili Date: Wed, 17 Jan 2024 21:15:39 -0800 Subject: [PATCH] adding importable roll tables and generative CLI --- rolltable/cli.py | 52 +++++++++++++------------------------------- rolltable/tables.py | 22 +++++++++++++++++++ rolltable/types.py | 16 +++++--------- tests/test_tables.py | 24 +++++++------------- 4 files changed, 51 insertions(+), 63 deletions(-) create mode 100644 rolltable/tables.py diff --git a/rolltable/cli.py b/rolltable/cli.py index 360fa3a..874ae1b 100644 --- a/rolltable/cli.py +++ b/rolltable/cli.py @@ -1,4 +1,5 @@ from rolltable.types import RollTable +from rolltable import tables import typer from enum import Enum from rich import print @@ -15,43 +16,6 @@ class OUTPUT_FORMATS(Enum): markdown = 'markdown' -@app.command("psychadelic-effects") -def psycheffects(): - """ - Generate a roll table of psychadelic effects. - """ - rt = RollTable([(Path(__file__).parent / 'sources' / 'psychadelic_effects.yaml').read_text()]) - print(rt.as_table()) - - -@app.command("trinkets") -def trinkets(): - """ - Generate a roll table of random junk. - """ - rt = RollTable([(Path(__file__).parent / 'sources' / 'trinkets.yaml').read_text()]) - print(rt.as_table()) - - -@app.command("wild-magic") -def wildmagic(): - """ - Generate a wild magic surge table. - """ - rt = RollTable([(Path(__file__).parent / 'sources' / 'wild_magic.yaml').read_text()]) - print(rt.as_table()) - - -@app.command("spells") -def spells(): - """ - Generate a random spell table. - """ - rt = RollTable([(Path(__file__).parent / 'sources' / 'spells.yaml').read_text()]) - rt.set_headers('Level', 'Name', 'School', None, None, None, None, None) - print(rt.as_table()) - - @app.command("custom") def custom( sources: List[Path] = typer.Argument( @@ -92,5 +56,19 @@ def custom( print(rt.as_table(width=width, expanded=not collapsed)) +def make_callback(roll_table_instance): + def inner(): + print(roll_table_instance.as_table()) + return inner + + +# step through all the predfined tables and create a cli for each +for name, table in tables.index.items(): + help_text = name.replace('_', ' ').title() + app.command(name=name, help=f"Create a roll table of {help_text}")( + make_callback(table) + ) + + if __name__ == '__main__': app() diff --git a/rolltable/tables.py b/rolltable/tables.py new file mode 100644 index 0000000..7adbb68 --- /dev/null +++ b/rolltable/tables.py @@ -0,0 +1,22 @@ +from pathlib import Path +from rolltable.types import RollTable +from typing import Any + + +def from_sources(names: list[str] = []) -> list: + return RollTable([ + (Path(__file__).parent / "sources" / name).read_text() + for name in names + ]) + + +index = dict( + psychadelic_effects=from_sources(['psychadelic_effects.yaml']), + trinkets=from_sources(['trinkets.yaml']), + wild_magic=from_sources(['wild_magic.yaml']), + spells=from_sources(['spells.yaml']) +) + + +def __getattr__(name: str) -> Any: + return index[name] diff --git a/rolltable/types.py b/rolltable/types.py index 7e9a922..5266bda 100644 --- a/rolltable/types.py +++ b/rolltable/types.py @@ -33,9 +33,9 @@ class RollTable: die: Optional[int] = 20, hide_rolls: bool = False) -> None: self._sources = sources self._frequency = frequency - self._die = die - self._hide_rolls = hide_rolls - self._data = None + self.die = die + self.hide_rolls = hide_rolls + self.data = None self._rows = None self._headers = None self._header_excludes = None @@ -46,10 +46,6 @@ class RollTable: def datasources(self) -> List: return self._data - @property - def die(self) -> int: - return self._die - @property def headers(self) -> List: return self._headers @@ -90,7 +86,7 @@ class RollTable: offset = 0 self._rows = [self._column_filter(['Roll'] + self.headers)] - for face in range(self._die): + for face in range(self.die): row = self._values[face] if not lastrow: lastrow = row @@ -106,7 +102,7 @@ class RollTable: @property def expanded_rows(self) -> List: self._rows = [self._column_filter(['Roll'] + self.headers)] - for face in range(self._die): + for face in range(self.die): row = self._values[face] self._rows.append(self._column_filter([f'd{face+1}'] + row)) return self._rows @@ -167,7 +163,7 @@ class RollTable: # pad the row with empty columns if there are more headers than columns cols = cols + [''] * (1 + len(self.headers) - len(row)) # strip the leading column if we're hiding the dice rolls - return cols[1:] if self._hide_rolls else cols + return cols[1:] if self.hide_rolls else cols def _flatten(self, obj: List) -> List: for member in obj: diff --git a/tests/test_tables.py b/tests/test_tables.py index 41ff011..9018ac8 100644 --- a/tests/test_tables.py +++ b/tests/test_tables.py @@ -1,22 +1,14 @@ import pytest -from pathlib import Path -from rolltable.types import RollTable +from rolltable import tables -sources = Path(__file__).parent / '..' / 'rolltable' / 'sources' - -flat_list = (sources / 'trinkets.yaml').read_text() -dict_of_dicts = (sources / 'wild_magic.yaml').read_text() -dict_of_lists = (sources / 'psychadelic_effects.yaml').read_text() - - -@pytest.mark.parametrize('data, expected', [ - ([dict_of_dicts], ['d1000 ', 'A third eye', 'Advantage on perception checks']), - ([flat_list], ['d1000 ', 'ivory mimic']), - ([dict_of_lists], ['d1000', 'Cosmic', 'mind expands', 'it will become so']), +@pytest.mark.parametrize('table, expected', [ + (tables.wild_magic, ['d1000 ', 'A third eye', 'Advantage on perception checks']), + (tables.trinkets, ['d1000 ', 'ivory mimic']), + (tables.psychadelic_effects, ['d1000', 'Cosmic', 'mind expands', 'it will become so']), ]) -def test_flat(data, expected): - rt = RollTable(data, die=1000) +def test_flat(table, expected): + table.die = 1000 for txt in expected: - assert txt in str(rt) + assert txt in str(table)