Skip to content

Commit

Permalink
Fix #19 by cleaning up load_book_assets and clarifying book id variab…
Browse files Browse the repository at this point in the history
…le names
  • Loading branch information
object-Object committed Nov 22, 2023
1 parent 310213c commit 8d0340a
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 61 deletions.
12 changes: 6 additions & 6 deletions src/hexdoc/cli/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ def repl(
all_metadata = loader.load_metadata(model_type=HexdocMetadata)
repl_locals["all_metadata"] = all_metadata

if props.book:
if props.book_id:
book, context = load_book(
book_id=props.book,
book_id=props.book_id,
pm=pm,
loader=loader,
i18n=i18n,
Expand Down Expand Up @@ -149,9 +149,9 @@ def export(
all_i18n = I18n.load_all(loader, allow_missing)
i18n = all_i18n[props.default_lang]

if props.book:
if props.book_id:
load_book(
book_id=props.book,
book_id=props.book_id,
pm=pm,
loader=loader,
i18n=i18n,
Expand All @@ -178,7 +178,7 @@ def render(

# load data
props, pm, plugin = load_common_data(props_file, verbosity, branch, book=True)
if not props.book:
if not props.book_id:
raise ValueError("Expected a value for props.book, got None")
if not props.template:
raise ValueError("Expected a value for props.template, got None")
Expand All @@ -196,7 +196,7 @@ def render(
i18n = I18n.load(loader, lang, allow_missing)

book, context = load_book(
book_id=props.book,
book_id=props.book_id,
pm=pm,
loader=loader,
i18n=i18n,
Expand Down
59 changes: 20 additions & 39 deletions src/hexdoc/core/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
strip_suffixes,
write_to_path,
)
from hexdoc.utils.types import PydanticOrderedSet

from .properties import Properties
from .resource import ResourceLocation, ResourceType
Expand All @@ -43,7 +44,6 @@
@dataclass(config=DEFAULT_CONFIG | {"arbitrary_types_allowed": True}, kw_only=True)
class ModResourceLoader:
props: Properties
root_book_id: ResourceLocation | None
export_dir: Path | None
resource_dirs: Sequence[PathResourceDir]
_stack: SkipValidation[ExitStack]
Expand Down Expand Up @@ -92,7 +92,6 @@ def load_all(

return cls(
props=props,
root_book_id=props.book,
export_dir=export_dir,
resource_dirs=[
path_resource_dir
Expand Down Expand Up @@ -166,53 +165,35 @@ def load_metadata(

return metadata

# TODO: maybe this should take lang as a variable?
@must_yield_something
def load_book_assets(
self,
book_id: ResourceLocation,
parent_book_id: ResourceLocation,
folder: BookFolder,
use_resource_pack: bool,
lang: str | None = None,
) -> Iterator[tuple[PathResourceDir, ResourceLocation, JSONDict]]:
if not self.root_book_id:
raise RuntimeError("Unable to call load_book_assets, root_book_id is None")

# self.root_book_id: hexcasting:thehexbook
# book_id: hexal:hexalbook
if book_id != self.root_book_id:
for extra_book_id in [book_id] + self.props.extra_books:
yield from self._load_book_assets(
extra_book_id,
folder,
use_resource_pack=use_resource_pack,
allow_missing=True,
)
if self.props.book_id is None:
raise TypeError("Can't load book assets because props.book_id is None")

yield from self._load_book_assets(
self.root_book_id,
folder,
use_resource_pack=use_resource_pack,
allow_missing=False,
)
if lang is None:
lang = self.props.default_lang

def _load_book_assets(
self,
book_id: ResourceLocation,
folder: BookFolder,
*,
use_resource_pack: bool,
allow_missing: bool,
) -> Iterator[tuple[PathResourceDir, ResourceLocation, JSONDict]]:
yield from self.load_resources(
type="assets" if use_resource_pack else "data",
folder=Path("patchouli_books")
/ book_id.path
/ self.props.default_lang
/ folder,
namespace=book_id.namespace,
allow_missing=allow_missing,
# use ordered set to be deterministic but avoid duplicate ids
books_to_check = PydanticOrderedSet.collect(
parent_book_id,
self.props.book_id,
*self.props.extra_books,
)

for book_id in books_to_check:
yield from self.load_resources(
type="assets" if use_resource_pack else "data",
folder=Path("patchouli_books") / book_id.path / lang / folder,
namespace=book_id.namespace,
allow_missing=True,
)

@overload
def load_resource(
self,
Expand Down
3 changes: 2 additions & 1 deletion src/hexdoc/core/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ class Properties(BaseProperties):
"""Pydantic model for `hexdoc.toml` / `properties.toml`."""

modid: str
book: ResourceLocation | None = None
# TODO: make another properties type without book_id
book_id: ResourceLocation | None = Field(alias="book", default=None)
extra_books: list[ResourceLocation] = Field(default_factory=list)
default_lang: str
default_branch: str
Expand Down
4 changes: 2 additions & 2 deletions src/hexdoc/patchouli/book.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def load_book_json(cls, loader: ModResourceLoader, id: ResourceLocation):
data = cls._load_book_resource(loader, id)

if IsVersion("<1.20") and "extend" in data:
id = loader.root_book_id = ResourceLocation.model_validate(data["extend"])
id = ResourceLocation.model_validate(data["extend"])
return cls._load_book_resource(loader, id)

return data
Expand Down Expand Up @@ -124,7 +124,7 @@ def _load_entries(self, context: BookContext):
internal_entries = defaultdict[ResLoc, dict[ResLoc, Entry]](dict)

for resource_dir, id, data in context.loader.load_book_assets(
book_id=self.id,
parent_book_id=self.id,
folder="entries",
use_resource_pack=self.use_resource_pack,
):
Expand Down
4 changes: 4 additions & 0 deletions src/hexdoc/utils/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class PydanticOrderedSet(OrderedSet[_T]):
def __init__(self, initial: OrderedSetInitializer[_T] | None = None):
super().__init__(initial or [])

@classmethod
def collect(cls, *initial: _T):
return cls(initial)

@classmethod
def __get_pydantic_core_schema__(
cls,
Expand Down
9 changes: 4 additions & 5 deletions test/core/test_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ def patchi_book(

def load_book_assets(
loader: ModResourceLoader,
book_id: ResourceLocation,
parent_book_id: ResourceLocation,
folder: BookFolder,
key: Callable[[JSONDict], Any],
):
assets = list(
data
for _, _, data in loader.load_book_assets(
book_id=book_id,
parent_book_id=parent_book_id,
folder=folder,
use_resource_pack=False,
)
Expand Down Expand Up @@ -78,20 +78,19 @@ def sortkey(v: JSONDict) -> str:
with ExitStack() as stack:
loader = ModResourceLoader(
props=props,
root_book_id=hexcasting_id,
export_dir=None,
resource_dirs=resource_dirs,
_stack=stack,
)

assert load_book_assets(loader, hexal_id, "categories", key=sortkey) == [
assert load_book_assets(loader, hexcasting_id, "categories", key=sortkey) == [
{"id": str(hexal_id)},
{"id": str(hexcasting_id)},
]

props.extra_books.append(hexgloop_id)

assert load_book_assets(loader, hexal_id, "categories", key=sortkey) == [
assert load_book_assets(loader, hexcasting_id, "categories", key=sortkey) == [
{"id": str(hexal_id)},
{"id": str(hexcasting_id)},
{"id": str(hexgloop_id)},
Expand Down
14 changes: 6 additions & 8 deletions test/integration/test_extend_book.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@ def child_loader(child_props: Properties, pm: PluginManager):
@pytest.fixture
def parent_book(pm: PluginManager, parent_loader: ModResourceLoader):
parent_props = parent_loader.props
assert parent_props.book
assert parent_props.book_id

i18n = I18n.load(parent_loader, parent_props.default_lang, allow_missing=True)

return load_book(
book_id=parent_props.book,
book_id=parent_props.book_id,
pm=pm,
loader=parent_loader,
i18n=i18n,
Expand All @@ -169,12 +169,12 @@ def parent_book(pm: PluginManager, parent_loader: ModResourceLoader):
@pytest.fixture
def child_book(pm: PluginManager, child_loader: ModResourceLoader):
child_props = child_loader.props
assert child_props.book
assert child_props.book_id

i18n = I18n.load(child_loader, child_props.default_lang, allow_missing=True)

return load_book(
book_id=child_props.book,
book_id=child_props.book_id,
pm=pm,
loader=child_loader,
i18n=i18n,
Expand All @@ -187,9 +187,8 @@ def test_parent_ids(parent_book: tuple[Book, BookContext]):

want_id = ResourceLocation("parent", "parentbook")

assert want_id == context.props.book
assert want_id == context.props.book_id
assert want_id == context.book_id
assert want_id == context.loader.root_book_id
assert want_id == book.id


Expand All @@ -199,7 +198,6 @@ def test_child_parent_ids(child_book: tuple[Book, BookContext]):
want_id = ResourceLocation("parent", "parentbook")

assert want_id == context.book_id
assert want_id == context.loader.root_book_id
assert want_id == book.id


Expand All @@ -208,4 +206,4 @@ def test_child_child_ids(child_book: tuple[Book, BookContext]):

want_id = ResourceLocation("child", "childbook")

assert want_id == context.props.book
assert want_id == context.props.book_id

0 comments on commit 8d0340a

Please sign in to comment.