Moved mod_str function from forms.py back to stats.py, and black formatting.

This commit is contained in:
Mark Wolfman
2021-07-07 10:29:46 -05:00
parent 8a054b335f
commit a31b9eb42c
10 changed files with 99 additions and 59 deletions
+33 -22
View File
@@ -11,10 +11,7 @@ from dungeonsheets.forms import dice_re, jinja_environment
def create_epub( def create_epub(
chapters: Mapping, chapters: Mapping, title: str, basename: str, use_dnd_decorations: bool = False
title: str,
basename: str,
use_dnd_decorations: bool = False
): ):
"""Prepare an EPUB file from the list of chapters. """Prepare an EPUB file from the list of chapters.
@@ -34,14 +31,18 @@ def create_epub(
""" """
# Create a new epub book # Create a new epub book
book = epub.EpubBook() book = epub.EpubBook()
book.set_identifier('id123456') book.set_identifier("id123456")
book.set_title(title) book.set_title(title)
book.set_language('en') book.set_language("en")
# Add the css files # Add the css files
css_template = jinja_env.get_template("dungeonsheets_epub.css") css_template = jinja_env.get_template("dungeonsheets_epub.css")
style = css_template.render(use_dnd_decorations=use_dnd_decorations) style = css_template.render(use_dnd_decorations=use_dnd_decorations)
css = epub.EpubItem(uid="style_default", file_name="style/gm_sheet.css", css = epub.EpubItem(
media_type="text/css", content=style) uid="style_default",
file_name="style/gm_sheet.css",
media_type="text/css",
content=style,
)
book.add_item(css) book.add_item(css)
toc = ["nav"] toc = ["nav"]
# Create the separate chapters # Create the separate chapters
@@ -49,15 +50,22 @@ def create_epub(
for chap_title, content in chapters.items(): for chap_title, content in chapters.items():
chap_fname = chap_title.replace(" - ", "-").replace(" ", "_").lower() chap_fname = chap_title.replace(" - ", "-").replace(" ", "_").lower()
chap_fname = "{}.html".format(chap_fname) chap_fname = "{}.html".format(chap_fname)
chapter = epub.EpubHtml(title=chap_title, chapter = epub.EpubHtml(
file_name=chap_fname, lang="en", title=chap_title,
media_type="application/xhtml+xml") file_name=chap_fname,
lang="en",
media_type="application/xhtml+xml",
)
chapter.set_content(content) chapter.set_content(content)
chapter.add_item(css) chapter.add_item(css)
book.add_item(chapter) book.add_item(chapter)
html_chapters.append(chapter) html_chapters.append(chapter)
# Add entries for the table of contents # Add entries for the table of contents
toc.append(toc_from_headings(html=content, filename=chap_fname, chapter_title=chap_title)) toc.append(
toc_from_headings(
html=content, filename=chap_fname, chapter_title=chap_title
)
)
# Add the table of contents # Add the table of contents
book.toc = toc book.toc = toc
book.spine = ("nav", *html_chapters) book.spine = ("nav", *html_chapters)
@@ -92,7 +100,7 @@ class HeadingParser(HTMLParser):
# Found a heading, so process the properties # Found a heading, so process the properties
self._curr_level = this_level self._curr_level = this_level
attrs = {k: v for k, v in attrs} attrs = {k: v for k, v in attrs}
self._curr_id = attrs.get('id') self._curr_id = attrs.get("id")
def handle_endtag(self, tag): def handle_endtag(self, tag):
this_level = self.heading_level(tag) this_level = self.heading_level(tag)
@@ -100,7 +108,7 @@ class HeadingParser(HTMLParser):
heading = { heading = {
"level": this_level, "level": this_level,
"id": self._curr_id, "id": self._curr_id,
"title": self._curr_title "title": self._curr_title,
} }
self.headings.append(heading) self.headings.append(heading)
@@ -110,7 +118,9 @@ class HeadingParser(HTMLParser):
self._curr_title = data self._curr_title = data
def toc_from_headings(html: str, filename: str = "", chapter_title: str = "Sheet") -> list: def toc_from_headings(
html: str, filename: str = "", chapter_title: str = "Sheet"
) -> list:
"""Accept a chapter of HTML, and extract a table of contents segment. """Accept a chapter of HTML, and extract a table of contents segment.
Parameters Parameters
@@ -149,18 +159,19 @@ def toc_from_headings(html: str, filename: str = "", chapter_title: str = "Sheet
href = f"{filename}#{heading['id']}" href = f"{filename}#{heading['id']}"
parent_section = sections_stack[-1] parent_section = sections_stack[-1]
is_last = idx == (len(headings) - 1) is_last = idx == (len(headings) - 1)
is_leaf = is_last or heading['level'] >= headings[idx+1]['level'] is_leaf = is_last or heading["level"] >= headings[idx + 1]["level"]
# Add a leaf or branch depending on the heading structure # Add a leaf or branch depending on the heading structure
if is_leaf: if is_leaf:
parent_section[1].append(epub.Link(href=href, title=heading['title'], uid=href)) parent_section[1].append(
epub.Link(href=href, title=heading["title"], uid=href)
)
else: else:
new_section = (epub.Section(href=href, title=heading['title']), new_section = (epub.Section(href=href, title=heading["title"]), [])
[])
parent_section[1].append(new_section) parent_section[1].append(new_section)
sections_stack.append(new_section) sections_stack.append(new_section)
# Walk back up the stack # Walk back up the stack
if not is_last: if not is_last:
for idx in range(max(0, heading['level'] - headings[idx + 1]['level'])): for idx in range(max(0, heading["level"] - headings[idx + 1]["level"])):
sections_stack.pop() sections_stack.pop()
return toc return toc
@@ -258,5 +269,5 @@ def to_heading_id(inpt: str) -> str:
# Prepare the jinja environment # Prepare the jinja environment
jinja_env = jinja_environment() jinja_env = jinja_environment()
jinja_env.filters['rst_to_html'] = rst_to_html jinja_env.filters["rst_to_html"] = rst_to_html
jinja_env.filters['to_heading_id'] = to_heading_id jinja_env.filters["to_heading_id"] = to_heading_id
+1
View File
@@ -25,5 +25,6 @@ class JSONFormatError(RuntimeError):
class UnknownFileType(RuntimeError): class UnknownFileType(RuntimeError):
"""The input file does not match one of the known formats.""" """The input file does not match one of the known formats."""
class UnknownOutputFormat(RuntimeError): class UnknownOutputFormat(RuntimeError):
"""The output format requested is not one of the known outputs.""" """The output format requested is not one of the known outputs."""
+1 -1
View File
@@ -160,7 +160,7 @@ def create_character_pdf_template(character, basename, flatten=False):
# Additional attacks beyond 3 # Additional attacks beyond 3
attack = [ attack = [
f"{w.name}: Atk {w.attack_modifier:+d}, Dam {w.damage}/{w.damage_type}" f"{w.name}: Atk {w.attack_modifier:+d}, Dam {w.damage}/{w.damage_type}"
for w in character.weapons[len(weapon_fields):] for w in character.weapons[len(weapon_fields) :]
] ]
# Other attack information # Other attack information
if character.armor: if character.armor:
+3 -7
View File
@@ -3,15 +3,13 @@ import re
from jinja2 import Environment, PackageLoader from jinja2 import Environment, PackageLoader
from dungeonsheets.stats import mod_str
# A dice string, with optional backticks: ``1d6 + 3`` # A dice string, with optional backticks: ``1d6 + 3``
dice_re = re.compile(r"`*(\d+d\d+(?:\s*\+\s*\d+)?)`*") dice_re = re.compile(r"`*(\d+d\d+(?:\s*\+\s*\d+)?)`*")
def mod_str(modifier):
"""Converts a modifier to a string, eg 2 -> '+2'."""
return "{:+d}".format(modifier)
def jinja_environment(): def jinja_environment():
"""Prepare a new environment for Jinja templates. """Prepare a new environment for Jinja templates.
@@ -34,5 +32,3 @@ def jinja_environment():
) )
jinja_env.filters["mod_str"] = mod_str jinja_env.filters["mod_str"] = mod_str
return jinja_env return jinja_env
+6 -1
View File
@@ -43,7 +43,12 @@ def _remove_temp_files(basename_):
filename.unlink() filename.unlink()
def create_latex_pdf(tex: str, basename: str, keep_temp_files: bool=False, use_dnd_decorations: bool=False): def create_latex_pdf(
tex: str,
basename: str,
keep_temp_files: bool = False,
use_dnd_decorations: bool = False,
):
# Create tex document # Create tex document
tex_file = f"{basename}.tex" tex_file = f"{basename}.tex"
with open(tex_file, mode="w", encoding="utf-8") as f: with open(tex_file, mode="w", encoding="utf-8") as f:
+26 -8
View File
@@ -11,7 +11,15 @@ from multiprocessing import Pool, cpu_count
from itertools import product from itertools import product
from typing import Union, Sequence, Optional from typing import Union, Sequence, Optional
from dungeonsheets import character as _char, exceptions, readers, latex, epub, monsters, forms from dungeonsheets import (
character as _char,
exceptions,
readers,
latex,
epub,
monsters,
forms,
)
from dungeonsheets.forms import mod_str from dungeonsheets.forms import mod_str
from dungeonsheets.content_registry import find_content from dungeonsheets.content_registry import find_content
from dungeonsheets.fill_pdf_template import ( from dungeonsheets.fill_pdf_template import (
@@ -132,8 +140,9 @@ def create_random_tables_content(
use_dnd_decorations: bool = False, use_dnd_decorations: bool = False,
) -> str: ) -> str:
template = jinja_env.get_template(f"random_tables_template.{suffix}") template = jinja_env.get_template(f"random_tables_template.{suffix}")
return template.render(conjure_animals=conjure_animals, return template.render(
use_dnd_decorations=use_dnd_decorations) conjure_animals=conjure_animals, use_dnd_decorations=use_dnd_decorations
)
def make_sheet( def make_sheet(
@@ -236,7 +245,10 @@ def make_gm_sheet(
summary = gm_props.pop("summary", "") summary = gm_props.pop("summary", "")
content.append( content.append(
create_party_summary_content( create_party_summary_content(
party, summary_rst=summary, suffix=content_suffix, use_dnd_decorations=fancy_decorations party,
summary_rst=summary,
suffix=content_suffix,
use_dnd_decorations=fancy_decorations,
) )
) )
# Add the monsters # Add the monsters
@@ -257,10 +269,14 @@ def make_gm_sheet(
monsters_.append(new_monster) monsters_.append(new_monster)
if len(monsters_) > 0: if len(monsters_) > 0:
content.append( content.append(
create_monsters_content(monsters_, suffix=content_suffix, use_dnd_decorations=fancy_decorations) create_monsters_content(
monsters_, suffix=content_suffix, use_dnd_decorations=fancy_decorations
)
) )
# Add the random tables # Add the random tables
random_tables = [s.replace(" ", "_").lower() for s in gm_props.pop("random_tables", [])] random_tables = [
s.replace(" ", "_").lower() for s in gm_props.pop("random_tables", [])
]
content.append( content.append(
create_random_tables_content( create_random_tables_content(
conjure_animals=("conjure_animals" in random_tables), conjure_animals=("conjure_animals" in random_tables),
@@ -303,7 +319,8 @@ def make_gm_sheet(
) )
else: else:
raise exceptions.UnknownOutputFormat( raise exceptions.UnknownOutputFormat(
f"Unknown output format requested: {output_format}. Valid options are: 'pdf', 'epub'" f"Unknown output format requested: {output_format}. Valid options are:"
" 'pdf', 'epub'"
) )
@@ -512,7 +529,8 @@ def main(args=None):
), ),
) )
parser.add_argument( parser.add_argument(
"--output-format", "-o", "--output-format",
"-o",
help="Specify the output format for the sheets.", help="Specify the output format for the sheets.",
choices=["pdf", "epub"], choices=["pdf", "epub"],
default="pdf", default="pdf",
+7 -1
View File
@@ -4,7 +4,13 @@ game mechanics."""
from dungeonsheets.spells import Spell from dungeonsheets.spells import Spell
from dungeonsheets.features import Feature from dungeonsheets.features import Feature
from dungeonsheets.infusions import Infusion from dungeonsheets.infusions import Infusion
from dungeonsheets.weapons import Weapon, MeleeWeapon, RangedWeapon, SimpleWeapon, MartialWeapon from dungeonsheets.weapons import (
Weapon,
MeleeWeapon,
RangedWeapon,
SimpleWeapon,
MartialWeapon,
)
from dungeonsheets.armor import Armor, Shield from dungeonsheets.armor import Armor, Shield
from dungeonsheets.magic_items import MagicItem from dungeonsheets.magic_items import MagicItem
from dungeonsheets.monsters import Monster from dungeonsheets.monsters import Monster
+1 -1
View File
@@ -9,7 +9,7 @@ from dungeonsheets.stats import Ability
class Baboon(Monster): class Baboon(Monster):
""" Pack Tactics. """Pack Tactics.
The baboon has advantage on an attack roll against a creature if The baboon has advantage on an attack roll against a creature if
at least one of the baboon's allies is within 5 ft. of the at least one of the baboon's allies is within 5 ft. of the
creature and the ally isn't incapacitated. creature and the ally isn't incapacitated.
+1 -3
View File
@@ -528,9 +528,7 @@ class FoundryCharacterReader(JSONCharacterReader):
tool_profs.extend([s.strip() for s in custom_tool_profs.split(";")]) tool_profs.extend([s.strip() for s in custom_tool_profs.split(";")])
char_props["_proficiencies_text"] = tool_profs char_props["_proficiencies_text"] = tool_profs
# Combat stats # Combat stats
char_props["hp_max"] = self.as_int( char_props["hp_max"] = self.as_int(json_data["data"]["attributes"]["hp"]["max"])
json_data["data"]["attributes"]["hp"]["max"]
)
# Equipment # Equipment
currency = json_data["data"]["currency"] currency = json_data["data"]["currency"]
char_props["cp"] = currency["cp"] char_props["cp"] = currency["cp"]
+5
View File
@@ -30,6 +30,11 @@ from dungeonsheets.features import (
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def mod_str(modifier):
"""Converts a modifier to a string, eg 2 -> '+2'."""
return "{:+d}".format(modifier)
AbilityScore = namedtuple("AbilityScore", ("value", "modifier", "saving_throw")) AbilityScore = namedtuple("AbilityScore", ("value", "modifier", "saving_throw"))