Load Entries in Book instead of Category
This commit is contained in:
parent
d282ff8ffb
commit
e52bbc37be
3 changed files with 51 additions and 43 deletions
|
@ -153,17 +153,19 @@ class Book:
|
|||
self.__post_init_pre_categories__(*args, **kwargs)
|
||||
|
||||
# categories
|
||||
self.categories: dict[ResourceLocation, patchouli.Category] = {}
|
||||
for path in self.categories_dir.rglob("*.json"):
|
||||
category = patchouli.Category.load(path, self)
|
||||
self.categories[category.id] = category
|
||||
self.categories = patchouli.Category.load_all(self)
|
||||
|
||||
# NOTE: category sorting requires book.categories to already contain all of the
|
||||
# categories, because category sorting depends on its parent, and categories get
|
||||
# their parent from the book. it's mildly scuffed, but it works
|
||||
self.categories = sorted_dict(self.categories)
|
||||
# entries
|
||||
# must be after categories, since Entry uses book.categories to get the parent
|
||||
for path in self.entries_dir.rglob("*.json"):
|
||||
# i used the entry to insert the entry
|
||||
# pretty sure thanos said that
|
||||
entry = patchouli.Entry.load(path, self)
|
||||
entry.category.entries.append(entry)
|
||||
|
||||
# TODO: entries
|
||||
# we inserted a bunch of entries in no particular order, so sort each category
|
||||
for category in self.categories.values():
|
||||
category.entries.sort()
|
||||
|
||||
def __post_init_pre_categories__(self) -> None:
|
||||
"""Subclasses may override this method to run code just before categories are
|
||||
|
@ -172,17 +174,21 @@ class Book:
|
|||
Type hooks are initialized before this, so you can add more here if needed.
|
||||
"""
|
||||
|
||||
@property
|
||||
def _dir_with_lang(self) -> Path:
|
||||
return self.props.book_dir / self.props.i18n.lang
|
||||
|
||||
@property
|
||||
def categories_dir(self) -> Path:
|
||||
return self.props.book_dir / self.props.i18n.lang / "categories"
|
||||
return self._dir_with_lang / "categories"
|
||||
|
||||
@property
|
||||
def entries_dir(self) -> Path:
|
||||
return self.props.book_dir / self.props.i18n.lang / "entries"
|
||||
return self._dir_with_lang / "entries"
|
||||
|
||||
@property
|
||||
def templates_dir(self) -> Path:
|
||||
return self.props.book_dir / self.props.i18n.lang / "templates"
|
||||
return self._dir_with_lang / "templates"
|
||||
|
||||
def format(
|
||||
self,
|
||||
|
|
|
@ -7,7 +7,7 @@ from typing import Self
|
|||
import patchouli
|
||||
from common.deserialize import from_dict_checked, load_json_data, rename
|
||||
from common.formatting import FormatTree
|
||||
from common.types import LocalizedStr, Sortable
|
||||
from common.types import LocalizedStr, Sortable, sorted_dict
|
||||
from minecraft.resource import ItemStack, ResourceLocation
|
||||
|
||||
|
||||
|
@ -28,23 +28,37 @@ class Category(Sortable, patchouli.BookHelpers):
|
|||
icon: ItemStack
|
||||
|
||||
# optional (category.json)
|
||||
parent_id: ResourceLocation | None = field(default=None, metadata=rename("parent"))
|
||||
_parent_id: ResourceLocation | None = field(default=None, metadata=rename("parent"))
|
||||
parent: Category | None = field(default=None, init=False)
|
||||
flag: str | None = None
|
||||
sortnum: int = 0
|
||||
secret: bool = False
|
||||
|
||||
def __post_init__(self):
|
||||
self.entries: list[patchouli.Entry] = []
|
||||
|
||||
@classmethod
|
||||
def load(cls, path: Path, book: patchouli.Book) -> Self:
|
||||
def _load(cls, path: Path, book: patchouli.Book) -> Self:
|
||||
# load the raw data from json, and add our extra fields
|
||||
data = load_json_data(cls, path, {"path": path, "book": book})
|
||||
return from_dict_checked(cls, data, book.config(), path)
|
||||
|
||||
def __post_init__(self):
|
||||
# load entries
|
||||
entry_dir = self.book.entries_dir / self.id.path
|
||||
self.entries: list[patchouli.Entry] = sorted(
|
||||
patchouli.Entry.load(path, self) for path in entry_dir.glob("*.json")
|
||||
)
|
||||
@classmethod
|
||||
def load_all(cls, book: patchouli.Book):
|
||||
categories: dict[ResourceLocation, Self] = {}
|
||||
|
||||
# load
|
||||
for path in book.categories_dir.rglob("*.json"):
|
||||
category = cls._load(path, book)
|
||||
categories[category.id] = category
|
||||
|
||||
# late-init parent
|
||||
for category in categories.values():
|
||||
if category._parent_id is not None:
|
||||
category.parent = categories[category._parent_id]
|
||||
|
||||
# return sorted by sortnum, which requires parent to be initialized
|
||||
return sorted_dict(categories)
|
||||
|
||||
@property
|
||||
def id(self) -> ResourceLocation:
|
||||
|
@ -54,16 +68,9 @@ class Category(Sortable, patchouli.BookHelpers):
|
|||
self.path,
|
||||
)
|
||||
|
||||
def parent(self) -> Category | None:
|
||||
"""Get this category's parent from the book. Must not be called until the book
|
||||
is fully initialized."""
|
||||
if self.parent_id is None:
|
||||
return None
|
||||
return self.book.categories[self.parent_id]
|
||||
|
||||
@property
|
||||
def _cmp_key(self) -> tuple[int, ...]:
|
||||
# implement Sortable
|
||||
if parent := self.parent():
|
||||
if parent := self.parent:
|
||||
return parent._cmp_key + (self.sortnum,)
|
||||
return (self.sortnum,)
|
||||
|
|
|
@ -19,11 +19,11 @@ class Entry(Sortable, patchouli.BookHelpers):
|
|||
|
||||
# non-json fields
|
||||
path: Path
|
||||
category: patchouli.Category
|
||||
category: patchouli.Category = field(init=False)
|
||||
|
||||
# required (entry.json)
|
||||
name: LocalizedStr
|
||||
category_id: ResourceLocation = field(metadata=rename("category"))
|
||||
_category_id: ResourceLocation = field(metadata=rename("category"))
|
||||
icon: ItemStack
|
||||
pages: list[patchouli.Page]
|
||||
|
||||
|
@ -39,19 +39,14 @@ class Entry(Sortable, patchouli.BookHelpers):
|
|||
entry_color: Color | None = None # this is undocumented lmao
|
||||
|
||||
@classmethod
|
||||
def load(cls, path: Path, category: patchouli.Category) -> Self:
|
||||
# load the raw data from json, and add our extra fields
|
||||
data = load_json_data(cls, path, {"path": path, "category": category})
|
||||
config = category.book.config()
|
||||
return from_dict_checked(cls, data, config, path)
|
||||
def load(cls, path: Path, book: patchouli.Book) -> Self:
|
||||
# load and convert the raw data from json
|
||||
data = load_json_data(cls, path, {"path": path})
|
||||
entry = from_dict_checked(cls, data, book.config(), path)
|
||||
|
||||
def __post_init__(self):
|
||||
# check the category id, just for fun
|
||||
# note the _ and . on the left and right respectively
|
||||
if self.category_id != self.category.id:
|
||||
raise ValueError(
|
||||
f"Entry {self.name} has category {self.category_id} but was initialized by {self.category.id}"
|
||||
)
|
||||
# now that it's been type hooked, use the id to get the category
|
||||
entry.category = book.categories[entry._category_id]
|
||||
return entry
|
||||
|
||||
@property
|
||||
def book(self) -> patchouli.Book:
|
||||
|
|
Loading…
Reference in a new issue