diff --git a/doc/.vscode/launch.json b/doc/.vscode/launch.json index 112c35e4..4274cd09 100644 --- a/doc/.vscode/launch.json +++ b/doc/.vscode/launch.json @@ -16,8 +16,7 @@ "name": "Python: Generate Docs", "type": "python", "request": "launch", - "cwd": "${workspaceFolder}/doc", - "module": "hexdoc", + "module": "hexdoc.hexdoc", "args": [ "properties.toml", ], diff --git a/doc/pyproject.toml b/doc/pyproject.toml index 0fa9dd67..255810ee 100644 --- a/doc/pyproject.toml +++ b/doc/pyproject.toml @@ -18,7 +18,7 @@ requires-python = ">=3.11" dependencies = [ "typing_extensions~=4.7.0", "typed-argument-parser~=1.8.0", - "pydantic~=2.0", + "pydantic~=2.0.3", "Jinja2~=3.1.2", ] @@ -31,7 +31,7 @@ dev = [ ] [project.scripts] -hexdoc = "hexdoc.scripts.hexdoc:main" +hexdoc = "hexdoc.hexdoc:main" [project.entry-points."hexdoc.Page"] hexdoc-patchouli = "hexdoc.patchouli.page.pages" diff --git a/doc/src/hexdoc/hexcasting/hex_book.py b/doc/src/hexdoc/hexcasting/hex_book.py index 4adf28dc..670c303a 100644 --- a/doc/src/hexdoc/hexcasting/hex_book.py +++ b/doc/src/hexdoc/hexcasting/hex_book.py @@ -2,9 +2,7 @@ from pathlib import Path from typing import Any, Generic, TypeVar from hexdoc.patchouli import AnyBookContext, Book, BookContext -from hexdoc.properties import Properties -from hexdoc.resource import ResourceLocation -from hexdoc.utils import AnyContext +from hexdoc.utils import AnyContext, Properties, ResourceLocation from .pattern import Direction, PatternInfo diff --git a/doc/src/hexdoc/hexcasting/hex_recipes.py b/doc/src/hexdoc/hexcasting/hex_recipes.py index 706477a1..6bdbea98 100644 --- a/doc/src/hexdoc/hexcasting/hex_recipes.py +++ b/doc/src/hexdoc/hexcasting/hex_recipes.py @@ -6,8 +6,7 @@ from hexdoc.minecraft.recipe import ( MinecraftItemIdIngredient, MinecraftItemTagIngredient, ) -from hexdoc.resource import ResourceLocation -from hexdoc.utils import HexDocModel +from hexdoc.utils import HexDocModel, ResourceLocation from .hex_book import HexContext diff --git a/doc/src/hexdoc/hexcasting/page/abstract_hex_pages.py b/doc/src/hexdoc/hexcasting/page/abstract_hex_pages.py index 8fecdc0f..117cb1cc 100644 --- a/doc/src/hexdoc/hexcasting/page/abstract_hex_pages.py +++ b/doc/src/hexdoc/hexcasting/page/abstract_hex_pages.py @@ -5,7 +5,7 @@ from pydantic import ValidationInfo, model_validator from hexdoc.minecraft import LocalizedStr from hexdoc.patchouli.page import PageWithText -from hexdoc.resource import ResourceLocation +from hexdoc.utils import ResourceLocation from ..hex_book import AnyHexContext, HexContext from ..pattern import RawPatternInfo diff --git a/doc/src/hexdoc/hexcasting/page/hex_pages.py b/doc/src/hexdoc/hexcasting/page/hex_pages.py index e7615317..f76568b2 100644 --- a/doc/src/hexdoc/hexcasting/page/hex_pages.py +++ b/doc/src/hexdoc/hexcasting/page/hex_pages.py @@ -5,7 +5,7 @@ from pydantic import ValidationInfo, model_validator from hexdoc.minecraft import LocalizedStr from hexdoc.minecraft.recipe import CraftingRecipe from hexdoc.patchouli.page import PageWithText, PageWithTitle -from hexdoc.resource import ResourceLocation +from hexdoc.utils import ResourceLocation from ..hex_book import HexContext from ..hex_recipes import BrainsweepRecipe diff --git a/doc/src/hexdoc/hexcasting/pattern.py b/doc/src/hexdoc/hexcasting/pattern.py index f050113a..22689b42 100644 --- a/doc/src/hexdoc/hexcasting/pattern.py +++ b/doc/src/hexdoc/hexcasting/pattern.py @@ -3,8 +3,7 @@ from typing import Annotated, Any from pydantic import BeforeValidator -from hexdoc.resource import ResourceLocation -from hexdoc.utils import HexDocModel +from hexdoc.utils import HexDocModel, ResourceLocation class Direction(Enum): diff --git a/doc/src/hexdoc/scripts/hexdoc.py b/doc/src/hexdoc/hexdoc.py similarity index 94% rename from doc/src/hexdoc/scripts/hexdoc.py rename to doc/src/hexdoc/hexdoc.py index d49140b0..4b41ea9b 100644 --- a/doc/src/hexdoc/scripts/hexdoc.py +++ b/doc/src/hexdoc/hexdoc.py @@ -15,8 +15,9 @@ from jinja2 import ( from tap import Tap from hexdoc.hexcasting import HexBook -from hexdoc.properties import Properties -from hexdoc.utils.jinja_extensions import IncludeRawExtension, hexdoc_block, hexdoc_wrap +from hexdoc.utils import Properties + +from .jinja_extensions import IncludeRawExtension, hexdoc_block, hexdoc_wrap def strip_empty_lines(text: str) -> str: diff --git a/doc/src/hexdoc/utils/jinja_extensions.py b/doc/src/hexdoc/jinja_extensions.py similarity index 100% rename from doc/src/hexdoc/utils/jinja_extensions.py rename to doc/src/hexdoc/jinja_extensions.py diff --git a/doc/src/hexdoc/minecraft/i18n.py b/doc/src/hexdoc/minecraft/i18n.py index 00747167..e93ba824 100644 --- a/doc/src/hexdoc/minecraft/i18n.py +++ b/doc/src/hexdoc/minecraft/i18n.py @@ -9,9 +9,13 @@ from pydantic.dataclasses import dataclass from pydantic.functional_validators import ModelWrapValidatorHandler from typing_extensions import TypedDict -from hexdoc.properties import Properties -from hexdoc.resource import ItemStack, ResourceLocation -from hexdoc.utils import DEFAULT_CONFIG, HexDocModel +from hexdoc.utils import ( + DEFAULT_CONFIG, + HexDocModel, + ItemStack, + Properties, + ResourceLocation, +) from hexdoc.utils.deserialize import isinstance_or_raise, load_json diff --git a/doc/src/hexdoc/minecraft/recipe/abstract_recipes.py b/doc/src/hexdoc/minecraft/recipe/abstract_recipes.py index 3ad0348b..42f5eb83 100644 --- a/doc/src/hexdoc/minecraft/recipe/abstract_recipes.py +++ b/doc/src/hexdoc/minecraft/recipe/abstract_recipes.py @@ -2,8 +2,7 @@ from typing import Any, Self, cast from pydantic import ValidationInfo, model_validator -from hexdoc.properties import AnyPropsContext -from hexdoc.resource import ResourceLocation, TypeTaggedUnion +from hexdoc.utils import AnyPropsContext, ResourceLocation, TypeTaggedUnion from hexdoc.utils.deserialize import load_json diff --git a/doc/src/hexdoc/minecraft/recipe/ingredients.py b/doc/src/hexdoc/minecraft/recipe/ingredients.py index 5b4e1a2b..16bf4b59 100644 --- a/doc/src/hexdoc/minecraft/recipe/ingredients.py +++ b/doc/src/hexdoc/minecraft/recipe/ingredients.py @@ -1,7 +1,6 @@ from typing import Any -from hexdoc.resource import ResourceLocation, TypeTaggedUnion -from hexdoc.utils import AnyContext, NoValue +from hexdoc.utils import AnyContext, NoValue, ResourceLocation, TypeTaggedUnion class ItemIngredient( diff --git a/doc/src/hexdoc/patchouli/__init__.py b/doc/src/hexdoc/patchouli/__init__.py index 793e5c4f..e1a596f8 100644 --- a/doc/src/hexdoc/patchouli/__init__.py +++ b/doc/src/hexdoc/patchouli/__init__.py @@ -9,8 +9,8 @@ __all__ = [ ] from .book import Book +from .book_models import AnyBookContext, BookContext from .category import Category from .entry import Entry -from .model import AnyBookContext, BookContext from .page import Page from .text import FormatTree diff --git a/doc/src/hexdoc/patchouli/book.py b/doc/src/hexdoc/patchouli/book.py index 4cf4c6d1..c075191b 100644 --- a/doc/src/hexdoc/patchouli/book.py +++ b/doc/src/hexdoc/patchouli/book.py @@ -3,14 +3,20 @@ from typing import Any, Generic, Literal, Self, cast from pydantic import Field, ValidationInfo, model_validator from hexdoc.minecraft import I18n, LocalizedStr -from hexdoc.properties import Properties -from hexdoc.resource import ItemStack, ResLoc, ResourceLocation -from hexdoc.utils import AnyContext, Color, HexDocModel +from hexdoc.utils import ( + AnyContext, + Color, + HexDocModel, + ItemStack, + Properties, + ResLoc, + ResourceLocation, +) from hexdoc.utils.deserialize import isinstance_or_raise, load_json +from .book_models import AnyBookContext, BookContext from .category import Category from .entry import Entry -from .model import AnyBookContext, BookContext from .text import DEFAULT_MACROS, FormatTree diff --git a/doc/src/hexdoc/patchouli/model.py b/doc/src/hexdoc/patchouli/book_models.py similarity index 88% rename from doc/src/hexdoc/patchouli/model.py rename to doc/src/hexdoc/patchouli/book_models.py index 8cd4ef39..a67657b9 100644 --- a/doc/src/hexdoc/patchouli/model.py +++ b/doc/src/hexdoc/patchouli/book_models.py @@ -4,9 +4,7 @@ from typing import Any, Generic, TypeVar, cast, dataclass_transform from pydantic import ValidationInfo, model_validator -from hexdoc.properties import Properties -from hexdoc.resource import ResourceLocation -from hexdoc.utils import AnyContext, HexDocFileModel +from hexdoc.utils import AnyContext, HexDocFileModel, Properties, ResourceLocation from .text.formatting import FormatContext diff --git a/doc/src/hexdoc/patchouli/category.py b/doc/src/hexdoc/patchouli/category.py index 431a1f1e..03d2a4f3 100644 --- a/doc/src/hexdoc/patchouli/category.py +++ b/doc/src/hexdoc/patchouli/category.py @@ -4,12 +4,11 @@ from typing import Self from pydantic import Field from hexdoc.minecraft import LocalizedStr -from hexdoc.properties import Properties -from hexdoc.resource import ItemStack, ResourceLocation +from hexdoc.utils import ItemStack, Properties, ResourceLocation from hexdoc.utils.types import Sortable, sorted_dict +from .book_models import BookContext, BookFileModel from .entry import Entry -from .model import BookContext, BookFileModel from .text import FormatTree diff --git a/doc/src/hexdoc/patchouli/entry.py b/doc/src/hexdoc/patchouli/entry.py index 76283c69..e7e12d0a 100644 --- a/doc/src/hexdoc/patchouli/entry.py +++ b/doc/src/hexdoc/patchouli/entry.py @@ -4,12 +4,10 @@ from typing import cast from pydantic import Field, ValidationInfo, model_validator from hexdoc.minecraft import LocalizedStr -from hexdoc.properties import Properties -from hexdoc.resource import ItemStack, ResourceLocation -from hexdoc.utils import Color +from hexdoc.utils import Color, ItemStack, Properties, ResourceLocation from hexdoc.utils.types import Sortable -from .model import BookContext, BookFileModel +from .book_models import BookContext, BookFileModel from .page.pages import Page diff --git a/doc/src/hexdoc/patchouli/page/abstract_pages.py b/doc/src/hexdoc/patchouli/page/abstract_pages.py index da7e650a..92d149d6 100644 --- a/doc/src/hexdoc/patchouli/page/abstract_pages.py +++ b/doc/src/hexdoc/patchouli/page/abstract_pages.py @@ -4,9 +4,9 @@ from pydantic import model_validator from pydantic.functional_validators import ModelWrapValidatorHandler from hexdoc.minecraft import LocalizedStr -from hexdoc.resource import ResourceLocation, TypeTaggedUnion +from hexdoc.utils import ResourceLocation, TypeTaggedUnion -from ..model import AnyBookContext +from ..book_models import AnyBookContext from ..text import FormatTree diff --git a/doc/src/hexdoc/patchouli/page/pages.py b/doc/src/hexdoc/patchouli/page/pages.py index 142df807..bd2beddd 100644 --- a/doc/src/hexdoc/patchouli/page/pages.py +++ b/doc/src/hexdoc/patchouli/page/pages.py @@ -2,9 +2,9 @@ from typing import Any from hexdoc.minecraft import LocalizedItem, LocalizedStr from hexdoc.minecraft.recipe import CraftingRecipe -from hexdoc.resource import Entity, ItemStack, ResourceLocation +from hexdoc.utils import Entity, ItemStack, ResourceLocation -from ..model import BookContext +from ..book_models import BookContext from ..text import FormatTree from .abstract_pages import Page, PageWithText, PageWithTitle diff --git a/doc/src/hexdoc/patchouli/text/formatting.py b/doc/src/hexdoc/patchouli/text/formatting.py index 3e8cd61c..05190099 100644 --- a/doc/src/hexdoc/patchouli/text/formatting.py +++ b/doc/src/hexdoc/patchouli/text/formatting.py @@ -14,8 +14,7 @@ from pydantic.functional_validators import ModelWrapValidatorHandler from hexdoc.minecraft import LocalizedStr from hexdoc.minecraft.i18n import I18nContext -from hexdoc.properties import PropsContext -from hexdoc.utils import DEFAULT_CONFIG, HexDocModel +from hexdoc.utils import DEFAULT_CONFIG, HexDocModel, PropsContext from hexdoc.utils.types import TryGetEnum from .html import HTMLElement, HTMLStream diff --git a/doc/src/hexdoc/scripts/__init__.py b/doc/src/hexdoc/scripts/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/doc/src/hexdoc/utils/__init__.py b/doc/src/hexdoc/utils/__init__.py index b15c43e5..e90cc5cb 100644 --- a/doc/src/hexdoc/utils/__init__.py +++ b/doc/src/hexdoc/utils/__init__.py @@ -9,6 +9,14 @@ __all__ = [ "NoValue", "NoValueType", "TagValue", + "AnyPropsContext", + "Properties", + "PropsContext", + "Entity", + "ItemStack", + "ResLoc", + "ResourceLocation", + "TypeTaggedUnion", ] from .model import ( @@ -18,5 +26,13 @@ from .model import ( HexDocFileModel, HexDocModel, ) -from .tagged_union import InternallyTaggedUnion, NoValue, NoValueType, TagValue +from .properties import AnyPropsContext, Properties, PropsContext +from .resource import Entity, ItemStack, ResLoc, ResourceLocation +from .tagged_union import ( + InternallyTaggedUnion, + NoValue, + NoValueType, + TagValue, + TypeTaggedUnion, +) from .types import Color diff --git a/doc/src/hexdoc/properties.py b/doc/src/hexdoc/utils/properties.py similarity index 96% rename from doc/src/hexdoc/properties.py rename to doc/src/hexdoc/utils/properties.py index 4f97dc99..aa35aeb1 100644 --- a/doc/src/hexdoc/properties.py +++ b/doc/src/hexdoc/utils/properties.py @@ -13,9 +13,9 @@ from pydantic import ( ) from typing_extensions import TypedDict -from hexdoc.resource import ResourceLocation -from hexdoc.utils.model import HexDocModel -from hexdoc.utils.toml_placeholders import load_toml +from .model import HexDocModel +from .resource import ResourceLocation +from .toml_placeholders import load_toml NoTrailingSlashHttpUrl = Annotated[ str, diff --git a/doc/src/hexdoc/resource.py b/doc/src/hexdoc/utils/resource.py similarity index 85% rename from doc/src/hexdoc/resource.py rename to doc/src/hexdoc/utils/resource.py index 515424ae..c6e34525 100644 --- a/doc/src/hexdoc/resource.py +++ b/doc/src/hexdoc/utils/resource.py @@ -12,13 +12,7 @@ from pydantic import field_validator, model_serializer, model_validator from pydantic.dataclasses import dataclass from pydantic.functional_validators import ModelWrapValidatorHandler -from hexdoc.utils import ( - DEFAULT_CONFIG, - AnyContext, - InternallyTaggedUnion, - NoValueType, - TagValue, -) +from .model import DEFAULT_CONFIG def _make_regex(count: bool = False, nbt: bool = False) -> re.Pattern[str]: @@ -128,20 +122,3 @@ class Entity(BaseResourceLocation, regex=_make_regex(nbt=True)): if self.nbt is not None: s += self.nbt return s - - -class TypeTaggedUnion(InternallyTaggedUnion[AnyContext], key="type", value=None): - type: ResourceLocation | NoValueType | None - - def __init_subclass__( - cls, - *, - group: str | None = None, - type: TagValue | None, - ) -> None: - super().__init_subclass__(group=group, value=type) - match type: - case str(): - cls.type = ResourceLocation.from_str(type) - case _: - cls.type = type diff --git a/doc/src/hexdoc/utils/tagged_union.py b/doc/src/hexdoc/utils/tagged_union.py index 5ee84aa9..551669d6 100644 --- a/doc/src/hexdoc/utils/tagged_union.py +++ b/doc/src/hexdoc/utils/tagged_union.py @@ -1,22 +1,17 @@ # pyright: reportPrivateUsage=false -from __future__ import annotations +# from __future__ import annotations from collections import defaultdict from enum import Enum -from typing import TYPE_CHECKING, Any, ClassVar, Generator, Self, cast +from typing import Any, ClassVar, Generator, Self, cast from pkg_resources import iter_entry_points from pydantic import ValidationInfo, model_validator from pydantic.functional_validators import ModelWrapValidatorHandler from .model import AnyContext, HexDocModel - -# from hexdoc.minecraft import ResourceLocation - - -if TYPE_CHECKING: - from pydantic.root_model import Model +from .resource import ResourceLocation class NoValueType(Enum): @@ -28,12 +23,9 @@ class NoValueType(Enum): NoValue = NoValueType._token """A singleton (like None) representing the value of a nonexistent dict key.""" - TagValue = str | NoValueType - _loaded_groups: set[str] = set() -_rebuilt_models: set[type[Any]] = set() def load_entry_points(group: str): @@ -122,9 +114,7 @@ class InternallyTaggedUnion(HexDocModel[AnyContext]): return tag_key @classmethod - def _supertypes( - cls, - ) -> Generator[type[InternallyTaggedUnion[AnyContext]], None, None]: + def _supertypes(cls) -> Generator[type[Self], None, None]: tag_key = cls._tag_key_or_raise() # we consider a type to be its own supertype/subtype @@ -145,31 +135,6 @@ class InternallyTaggedUnion(HexDocModel[AnyContext]): def _concrete_subtypes(cls): return cls.__concrete_subtypes - @classmethod - def model_validate( - cls: type[Model], - obj: Any, - *, - strict: bool | None = None, - from_attributes: bool | None = None, - context: AnyContext | None = None, - ) -> Model: - # resolve forward references, because apparently we need to do this - # if cls not in _rebuilt_models: - # _rebuilt_models.add(cls) - # cls.model_rebuild( - # _types_namespace={ - # "ResourceLocation": ResourceLocation, - # } - # ) - - return super().model_validate( - obj, - strict=strict, - from_attributes=from_attributes, - context=context, - ) - @model_validator(mode="wrap") @classmethod def _resolve_from_dict( @@ -233,3 +198,20 @@ class InternallyTaggedUnion(HexDocModel[AnyContext]): f"Failed to match {cls} with {cls._tag_key}={tag_value} to any of {tag_types}: {data}", exceptions, ) + + +class TypeTaggedUnion(InternallyTaggedUnion[AnyContext], key="type", value=None): + type: ResourceLocation | NoValueType | None + + def __init_subclass__( + cls, + *, + group: str | None = None, + type: TagValue | None, + ) -> None: + super().__init_subclass__(group=group, value=type) + match type: + case str(): + cls.type = ResourceLocation.from_str(type) + case _: + cls.type = type diff --git a/doc/test/minecraft/test_resource.py b/doc/test/minecraft/test_resource.py index 4f149f09..563ea0b1 100644 --- a/doc/test/minecraft/test_resource.py +++ b/doc/test/minecraft/test_resource.py @@ -1,6 +1,6 @@ import pytest -from hexdoc.resource import ItemStack, ResLoc, ResourceLocation +from hexdoc.utils import ItemStack, ResLoc, ResourceLocation resource_locations: list[tuple[str, ResourceLocation, str]] = [ ( diff --git a/doc/test/test_snapshots.py b/doc/test/test_snapshots.py index f87cb3bf..389d6e04 100644 --- a/doc/test/test_snapshots.py +++ b/doc/test/test_snapshots.py @@ -5,7 +5,7 @@ from pathlib import Path import pytest from syrupy.assertion import SnapshotAssertion -from hexdoc.scripts.hexdoc import Args, main +from hexdoc.hexdoc import Args, main _RUN = ["hexdoc"] _ARGV = ["properties.toml", "-o"]