Add hatch-gradle-version and restructure a lot of things
This commit is contained in:
parent
fec6702946
commit
8b32827c7e
50 changed files with 332 additions and 6331 deletions
2
.github/workflows/build_docs.yml
vendored
2
.github/workflows/build_docs.yml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
|||
python-version: "3.11"
|
||||
|
||||
- name: Install docgen
|
||||
run: pip install ./doc
|
||||
run: pip install .
|
||||
|
||||
- name: Generate file
|
||||
run: hexdoc doc/properties.toml -o index.html.uncommitted --ci
|
||||
|
|
157
.gitignore
vendored
157
.gitignore
vendored
|
@ -26,3 +26,160 @@ forge*changelog.txt
|
|||
|
||||
Session.vim
|
||||
plot/
|
||||
|
||||
|
||||
# Python
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
|
20
.vscode/settings.json
vendored
20
.vscode/settings.json
vendored
|
@ -1,4 +1,18 @@
|
|||
{
|
||||
"python.analysis.exclude": ["**"],
|
||||
"python.analysis.indexing": false,
|
||||
}
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "ms-python.black-formatter",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true,
|
||||
},
|
||||
"editor.rulers": [88],
|
||||
},
|
||||
"isort.importStrategy": "fromEnvironment",
|
||||
"python.languageServer": "Pylance",
|
||||
"python.analysis.diagnosticMode": "workspace",
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"[html][jinja-html]": {
|
||||
"editor.rulers": [120],
|
||||
},
|
||||
}
|
||||
|
|
156
doc/.gitignore
vendored
156
doc/.gitignore
vendored
|
@ -1,158 +1,2 @@
|
|||
/*.html
|
||||
/src/hexdoc/_export/generated/
|
||||
|
||||
# Python
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
|
15
doc/.vscode/HexMod_doc.code-workspace
vendored
15
doc/.vscode/HexMod_doc.code-workspace
vendored
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"name": "doc",
|
||||
"path": ".."
|
||||
},
|
||||
{
|
||||
"name": "HexMod",
|
||||
"path": "../.."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"python.languageServer": "Pylance",
|
||||
}
|
||||
}
|
18
doc/.vscode/settings.json
vendored
18
doc/.vscode/settings.json
vendored
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "ms-python.black-formatter",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true,
|
||||
},
|
||||
"editor.rulers": [88],
|
||||
},
|
||||
"isort.importStrategy": "fromEnvironment",
|
||||
"python.languageServer": "Pylance",
|
||||
"python.analysis.diagnosticMode": "workspace",
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"[html][jinja-html]": {
|
||||
"editor.rulers": [120],
|
||||
},
|
||||
}
|
|
@ -37,7 +37,7 @@ hexcasting = "https://raw.githubusercontent.com/gamma-delta/HexMod/main/Common/s
|
|||
[template]
|
||||
main = "main.html.jinja"
|
||||
packages = [
|
||||
"hexdoc_templates",
|
||||
"hexdoc",
|
||||
]
|
||||
|
||||
[template.args]
|
||||
|
|
|
@ -3,16 +3,15 @@ from pathlib import Path
|
|||
|
||||
from pydantic import Field, model_validator
|
||||
|
||||
from hexdoc.minecraft.tags import Tag
|
||||
from hexdoc.patchouli.book import BookContext
|
||||
from hexdoc.utils import ResourceLocation
|
||||
from hexdoc.utils.model import HexDocModel
|
||||
from hexdoc.minecraft import Tag
|
||||
from hexdoc.patchouli import BookContext
|
||||
from hexdoc.utils import HexdocModel, ResourceLocation
|
||||
from hexdoc.utils.properties import PatternStubProps
|
||||
|
||||
from .pattern import Direction, PatternInfo
|
||||
|
||||
|
||||
class PatternMetadata(HexDocModel):
|
||||
class PatternMetadata(HexdocModel):
|
||||
"""Automatically generated at `export_dir/modid.patterns.hexdoc.json`."""
|
||||
|
||||
patterns: dict[ResourceLocation, PatternInfo]
|
||||
|
|
|
@ -6,7 +6,7 @@ from hexdoc.minecraft.recipe import (
|
|||
MinecraftItemIdIngredient,
|
||||
MinecraftItemTagIngredient,
|
||||
)
|
||||
from hexdoc.utils import HexDocModel, ResourceLocation, TypeTaggedUnion
|
||||
from hexdoc.utils import HexdocModel, ResourceLocation, TypeTaggedUnion
|
||||
|
||||
# ingredients
|
||||
|
||||
|
@ -34,7 +34,7 @@ class EntityTagIngredient(BrainsweepeeIngredient, type="entity_tag"):
|
|||
tag: ResourceLocation
|
||||
|
||||
|
||||
class BlockStateIngredient(HexDocModel):
|
||||
class BlockStateIngredient(HexdocModel):
|
||||
# TODO: tagged union
|
||||
type: Literal["block"]
|
||||
block: ResourceLocation
|
||||
|
@ -58,7 +58,7 @@ class ModConditionalIngredient(
|
|||
# results
|
||||
|
||||
|
||||
class BlockState(HexDocModel):
|
||||
class BlockState(HexdocModel):
|
||||
name: LocalizedItem
|
||||
properties: dict[str, Any] | None = None
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ from typing import Annotated, Any
|
|||
|
||||
from pydantic import BeforeValidator
|
||||
|
||||
from hexdoc.utils import HexDocModel, ResourceLocation
|
||||
from hexdoc.utils import HexdocModel, ResourceLocation
|
||||
|
||||
|
||||
class Direction(Enum):
|
||||
|
@ -28,7 +28,7 @@ class Direction(Enum):
|
|||
DirectionField = Annotated[Direction, BeforeValidator(Direction.validate)]
|
||||
|
||||
|
||||
class RawPatternInfo(HexDocModel):
|
||||
class RawPatternInfo(HexdocModel):
|
||||
startdir: DirectionField
|
||||
signature: str
|
||||
is_per_world: bool = False
|
||||
|
|
|
@ -14,7 +14,7 @@ from hexdoc.hexcasting.hex_book import HexContext
|
|||
from hexdoc.patchouli.book import Book
|
||||
from hexdoc.utils import Properties
|
||||
from hexdoc.utils.cd import cd
|
||||
from hexdoc.utils.model import HexDocModel, init_context
|
||||
from hexdoc.utils.model import HexdocModel, init_context
|
||||
from hexdoc.utils.resource_loader import ModResourceLoader
|
||||
|
||||
from .jinja_extensions import IncludeRawExtension, hexdoc_block, hexdoc_wrap
|
||||
|
@ -25,7 +25,7 @@ def strip_empty_lines(text: str) -> str:
|
|||
|
||||
|
||||
# CLI arguments
|
||||
class Args(HexDocModel):
|
||||
class Args(HexdocModel):
|
||||
"""example: main.py properties.toml -o out.html"""
|
||||
|
||||
properties_file: Path
|
||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||
import json
|
||||
from dataclasses import InitVar
|
||||
from functools import total_ordering
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Self
|
||||
|
||||
from pydantic import Field, ValidationInfo, model_validator
|
||||
|
@ -11,7 +12,7 @@ from pydantic.functional_validators import ModelWrapValidatorHandler
|
|||
|
||||
from hexdoc.utils import (
|
||||
DEFAULT_CONFIG,
|
||||
HexDocModel,
|
||||
HexdocModel,
|
||||
ItemStack,
|
||||
ModResourceLoader,
|
||||
Properties,
|
||||
|
@ -23,10 +24,11 @@ from hexdoc.utils.deserialize import (
|
|||
isinstance_or_raise,
|
||||
)
|
||||
from hexdoc.utils.resource_loader import LoaderContext
|
||||
from hexdoc.utils.types import replace_suffixes
|
||||
|
||||
|
||||
@total_ordering
|
||||
class LocalizedStr(HexDocModel):
|
||||
class LocalizedStr(HexdocModel):
|
||||
"""Represents a string which has been localized."""
|
||||
|
||||
key: str
|
||||
|
@ -137,8 +139,15 @@ class I18n:
|
|||
for key, value in raw_lookup.items()
|
||||
}
|
||||
|
||||
def _export(self, new: dict[str, str], current: dict[str, str] | None):
|
||||
return json.dumps((current or {}) | new)
|
||||
def _export(
|
||||
self,
|
||||
new: dict[str, str],
|
||||
current: dict[str, str] | None,
|
||||
path: Path,
|
||||
):
|
||||
data = json.dumps((current or {}) | new)
|
||||
path = replace_suffixes(path, ".json")
|
||||
return data, path
|
||||
|
||||
def localize(self, *keys: str, default: str | None = None) -> LocalizedStr:
|
||||
"""Looks up the given string in the lang table if i18n is enabled. Otherwise,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from hexdoc.utils import HexDocModel
|
||||
from hexdoc.utils import HexdocModel
|
||||
|
||||
from ..i18n import LocalizedItem
|
||||
from .abstract_recipes import Recipe
|
||||
from .ingredients import ItemIngredientOrList
|
||||
|
||||
|
||||
class ItemResult(HexDocModel):
|
||||
class ItemResult(HexdocModel):
|
||||
item: LocalizedItem
|
||||
count: int | None = None
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import Iterator, Self
|
||||
from typing import Any, Iterator, Self
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from hexdoc.utils import HexDocModel, LoaderContext, ResourceLocation
|
||||
from hexdoc.utils import HexdocModel, LoaderContext, ResourceLocation
|
||||
from hexdoc.utils.deserialize import decode_json_dict
|
||||
|
||||
|
||||
class OptionalTagValue(HexDocModel, frozen=True):
|
||||
class OptionalTagValue(HexdocModel, frozen=True):
|
||||
id: ResourceLocation
|
||||
required: bool
|
||||
|
||||
|
@ -16,7 +16,7 @@ class OptionalTagValue(HexDocModel, frozen=True):
|
|||
TagValue = ResourceLocation | OptionalTagValue
|
||||
|
||||
|
||||
class Tag(HexDocModel):
|
||||
class Tag(HexdocModel):
|
||||
registry: str = Field(exclude=True)
|
||||
raw_values: set[TagValue] = Field(alias="values")
|
||||
replace: bool
|
||||
|
@ -63,7 +63,7 @@ class Tag(HexDocModel):
|
|||
case OptionalTagValue(id=id):
|
||||
yield id
|
||||
|
||||
def _export(self, current: Self | None):
|
||||
def _export(self, current: Self | None, *_: Any):
|
||||
if self.replace or current is None:
|
||||
tag = self
|
||||
else:
|
||||
|
|
|
@ -6,7 +6,7 @@ from hexdoc.minecraft import I18n, LocalizedStr
|
|||
from hexdoc.minecraft.i18n import I18nContext
|
||||
from hexdoc.utils import (
|
||||
Color,
|
||||
HexDocModel,
|
||||
HexdocModel,
|
||||
ItemStack,
|
||||
ModResourceLoader,
|
||||
ResLoc,
|
||||
|
@ -20,7 +20,7 @@ from .entry import Entry
|
|||
from .text import FormatTree
|
||||
|
||||
|
||||
class Book(HexDocModel):
|
||||
class Book(HexdocModel):
|
||||
"""Main Patchouli book class.
|
||||
|
||||
Includes all data from book.json, categories/entries/pages, and i18n.
|
||||
|
|
|
@ -4,14 +4,14 @@ from pydantic import Field
|
|||
|
||||
from hexdoc.minecraft import LocalizedStr
|
||||
from hexdoc.utils import ItemStack, LoaderContext, ResourceLocation
|
||||
from hexdoc.utils.resource import HexDocIDModel
|
||||
from hexdoc.utils.resource import HexdocIDModel
|
||||
from hexdoc.utils.types import Sortable, sorted_dict
|
||||
|
||||
from .entry import Entry
|
||||
from .text import FormatTree
|
||||
|
||||
|
||||
class Category(HexDocIDModel, Sortable):
|
||||
class Category(HexdocIDModel, Sortable):
|
||||
"""Category with pages and localizations.
|
||||
|
||||
See: https://vazkiimods.github.io/Patchouli/docs/reference/category-json
|
||||
|
|
|
@ -5,14 +5,14 @@ from pydantic import Field, ValidationInfo, model_validator
|
|||
from hexdoc.minecraft import LocalizedStr
|
||||
from hexdoc.utils import Color, ItemStack, ResourceLocation
|
||||
from hexdoc.utils.deserialize import cast_or_raise
|
||||
from hexdoc.utils.resource import HexDocIDModel
|
||||
from hexdoc.utils.resource import HexdocIDModel
|
||||
from hexdoc.utils.types import Sortable
|
||||
|
||||
from .book_context import BookContext
|
||||
from .page.pages import Page
|
||||
|
||||
|
||||
class Entry(HexDocIDModel, Sortable):
|
||||
class Entry(HexdocIDModel, Sortable):
|
||||
"""Entry json file, with pages and localizations.
|
||||
|
||||
See: https://vazkiimods.github.io/Patchouli/docs/reference/entry-json
|
||||
|
|
|
@ -15,7 +15,7 @@ from pydantic.functional_validators import ModelWrapValidatorHandler
|
|||
from hexdoc.minecraft import LocalizedStr
|
||||
from hexdoc.minecraft.i18n import I18nContext
|
||||
from hexdoc.patchouli.text.html import HTMLElement, HTMLStream
|
||||
from hexdoc.utils import DEFAULT_CONFIG, HexDocModel
|
||||
from hexdoc.utils import DEFAULT_CONFIG, HexdocModel
|
||||
from hexdoc.utils.deserialize import cast_or_raise
|
||||
from hexdoc.utils.properties import Properties
|
||||
from hexdoc.utils.resource import ResourceLocation
|
||||
|
@ -82,7 +82,7 @@ class FormattingContext(
|
|||
return self
|
||||
|
||||
|
||||
class BookLink(HexDocModel):
|
||||
class BookLink(HexdocModel):
|
||||
raw_value: str
|
||||
id: ResourceLocation
|
||||
anchor: str | None
|
||||
|
@ -150,7 +150,7 @@ class SpecialStyleType(Enum):
|
|||
link = "l"
|
||||
|
||||
|
||||
class Style(ABC, HexDocModel, frozen=True):
|
||||
class Style(ABC, HexdocModel, frozen=True):
|
||||
type: CommandStyleType | FunctionStyleType | SpecialStyleType
|
||||
|
||||
@staticmethod
|
||||
|
@ -311,7 +311,7 @@ class LinkStyle(Style, frozen=True):
|
|||
|
||||
# intentionally not inheriting from Style, because this is basically an implementation
|
||||
# detail of the parser and should not be returned or exposed anywhere
|
||||
class _CloseTag(HexDocModel, frozen=True):
|
||||
class _CloseTag(HexdocModel, frozen=True):
|
||||
type: FunctionStyleType | Literal[SpecialStyleType.base, SpecialStyleType.color]
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
__all__ = [
|
||||
"HexDocModel",
|
||||
"HexdocModel",
|
||||
"InternallyTaggedUnion",
|
||||
"Color",
|
||||
"ValidationContext",
|
||||
|
@ -18,7 +18,7 @@ __all__ = [
|
|||
"init_context",
|
||||
]
|
||||
|
||||
from .model import DEFAULT_CONFIG, HexDocModel, ValidationContext, init_context
|
||||
from .model import DEFAULT_CONFIG, HexdocModel, ValidationContext, init_context
|
||||
from .properties import Properties
|
||||
from .resource import Entity, ItemStack, ResLoc, ResourceLocation
|
||||
from .resource_loader import LoaderContext, ModResourceLoader
|
||||
|
|
|
@ -25,9 +25,9 @@ def init_context(value: Any) -> Iterator[None]:
|
|||
|
||||
|
||||
@dataclass_transform()
|
||||
class HexDocBaseModel(BaseModel):
|
||||
class HexdocBaseModel(BaseModel):
|
||||
"""Base class for all Pydantic models in hexdoc. You should probably use
|
||||
`HexDocModel` or `ValidationContext` instead.
|
||||
`HexdocModel` or `ValidationContext` instead.
|
||||
|
||||
Sets the default model config, and overrides __init__ to allow using the
|
||||
`init_context` context manager to set validation context for constructors.
|
||||
|
@ -47,12 +47,12 @@ class HexDocBaseModel(BaseModel):
|
|||
|
||||
|
||||
@dataclass_transform()
|
||||
class ValidationContext(HexDocBaseModel):
|
||||
"""Base class for Pydantic validation context for `HexDocModel`."""
|
||||
class ValidationContext(HexdocBaseModel):
|
||||
"""Base class for Pydantic validation context for `HexdocModel`."""
|
||||
|
||||
|
||||
@dataclass_transform()
|
||||
class HexDocModel(HexDocBaseModel):
|
||||
class HexdocModel(HexdocBaseModel):
|
||||
"""Base class for most Pydantic models in hexdoc.
|
||||
|
||||
Includes type overrides to require using subclasses of `ValidationContext` for
|
||||
|
@ -87,7 +87,7 @@ class HexDocModel(HexDocBaseModel):
|
|||
|
||||
|
||||
@dataclass_transform()
|
||||
class StripHiddenModel(HexDocModel):
|
||||
class StripHiddenModel(HexdocModel):
|
||||
"""Base model which removes all keys starting with _ before validation."""
|
||||
|
||||
@model_validator(mode="before")
|
||||
|
|
|
@ -35,7 +35,7 @@ class TemplateProps(StripHiddenModel):
|
|||
|
||||
for i, value in enumerate(values):
|
||||
if isinstance(value, str):
|
||||
values[i] = (value, Path())
|
||||
values[i] = (value, Path("_templates"))
|
||||
return values
|
||||
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ from pydantic.dataclasses import dataclass
|
|||
from pydantic.functional_validators import ModelWrapValidatorHandler
|
||||
|
||||
from .deserialize import JSONDict
|
||||
from .model import DEFAULT_CONFIG, HexDocModel, ValidationContext
|
||||
from .model import DEFAULT_CONFIG, HexdocModel, ValidationContext
|
||||
|
||||
HEXDOC_EXPORTS_GROUP = "hexdoc.export"
|
||||
"""Entry point group name for bundled hexdoc data."""
|
||||
|
@ -211,7 +211,7 @@ class Entity(BaseResourceLocation, regex=_make_regex(nbt=True)):
|
|||
return s
|
||||
|
||||
|
||||
class BaseResourceDir(HexDocModel, ABC):
|
||||
class BaseResourceDir(HexdocModel, ABC):
|
||||
external: bool
|
||||
reexport: bool
|
||||
"""If not set, the default value will be `not self.external`.
|
||||
|
@ -321,7 +321,7 @@ ResourceDir = PathResourceDir | EntryPointResourceDir
|
|||
|
||||
|
||||
@dataclass_transform()
|
||||
class HexDocIDModel(HexDocModel, ABC):
|
||||
class HexdocIDModel(HexdocModel, ABC):
|
||||
id: ResourceLocation
|
||||
resource_dir: PathResourceDir
|
||||
|
||||
|
|
|
@ -10,19 +10,21 @@ from typing import Callable, Literal, Self, TypeVar, overload
|
|||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from hexdoc.utils.deserialize import JSONDict, decode_json_dict
|
||||
from hexdoc.utils.model import DEFAULT_CONFIG, HexDocModel, ValidationContext
|
||||
from hexdoc.utils.types import without_suffix
|
||||
from hexdoc.utils.model import DEFAULT_CONFIG, HexdocModel, ValidationContext
|
||||
from hexdoc.utils.types import strip_suffixes
|
||||
|
||||
from .properties import Properties
|
||||
from .resource import PathResourceDir, ResourceLocation, ResourceType
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_T_Model = TypeVar("_T_Model", bound=HexDocModel)
|
||||
|
||||
METADATA_SUFFIX = ".hexdoc.json"
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_T_Model = TypeVar("_T_Model", bound=HexdocModel)
|
||||
|
||||
class HexDocMetadata(HexDocModel):
|
||||
ExportFn = Callable[[_T, _T | None, Path], str | tuple[str, Path]]
|
||||
|
||||
|
||||
class HexdocMetadata(HexdocModel):
|
||||
"""Automatically generated at `export_dir/modid.hexdoc.json`."""
|
||||
|
||||
book_url: str
|
||||
|
@ -55,8 +57,8 @@ class ModResourceLoader:
|
|||
|
||||
# export this mod's metadata
|
||||
loader.export(
|
||||
path=HexDocMetadata.path(props.modid),
|
||||
data=HexDocMetadata(
|
||||
path=HexdocMetadata.path(props.modid),
|
||||
data=HexdocMetadata(
|
||||
book_url=props.url,
|
||||
).model_dump_json(),
|
||||
)
|
||||
|
@ -64,7 +66,7 @@ class ModResourceLoader:
|
|||
yield loader
|
||||
|
||||
def __post_init__(self):
|
||||
self.mod_metadata = self.load_metadata("{modid}", HexDocMetadata)
|
||||
self.mod_metadata = self.load_metadata("{modid}", HexdocMetadata)
|
||||
|
||||
def get_link_base(self, resource_dir: PathResourceDir) -> str:
|
||||
modid = resource_dir.modid
|
||||
|
@ -114,7 +116,7 @@ class ModResourceLoader:
|
|||
id: ResourceLocation,
|
||||
*,
|
||||
decode: Callable[[str], _T] = decode_json_dict,
|
||||
export: Callable[[_T, _T | None], str] | Literal[False] | None = None,
|
||||
export: ExportFn[_T] | Literal[False] | None = None,
|
||||
) -> tuple[PathResourceDir, _T]:
|
||||
...
|
||||
|
||||
|
@ -125,7 +127,7 @@ class ModResourceLoader:
|
|||
/,
|
||||
*,
|
||||
decode: Callable[[str], _T] = decode_json_dict,
|
||||
export: Callable[[_T, _T | None], str] | Literal[False] | None = None,
|
||||
export: ExportFn[_T] | Literal[False] | None = None,
|
||||
) -> tuple[PathResourceDir, _T]:
|
||||
...
|
||||
|
||||
|
@ -136,7 +138,7 @@ class ModResourceLoader:
|
|||
id: ResourceLocation | None = None,
|
||||
*,
|
||||
decode: Callable[[str], _T] = decode_json_dict,
|
||||
export: Callable[[_T, _T | None], str] | Literal[False] | None = None,
|
||||
export: ExportFn[_T] | Literal[False] | None = None,
|
||||
) -> tuple[PathResourceDir, _T]:
|
||||
"""Find the first file with this resource location in `resource_dirs`.
|
||||
|
||||
|
@ -174,7 +176,7 @@ class ModResourceLoader:
|
|||
namespace: str,
|
||||
glob: str | list[str] = "**/*",
|
||||
decode: Callable[[str], _T] = decode_json_dict,
|
||||
export: Callable[[_T, _T | None], str] | Literal[False] | None = None,
|
||||
export: ExportFn[_T] | Literal[False] | None = None,
|
||||
) -> Iterator[tuple[PathResourceDir, ResourceLocation, _T]]:
|
||||
...
|
||||
|
||||
|
@ -186,7 +188,7 @@ class ModResourceLoader:
|
|||
id: ResourceLocation,
|
||||
*,
|
||||
decode: Callable[[str], _T] = decode_json_dict,
|
||||
export: Callable[[_T, _T | None], str] | Literal[False] | None = None,
|
||||
export: ExportFn[_T] | Literal[False] | None = None,
|
||||
) -> Iterator[tuple[PathResourceDir, ResourceLocation, _T]]:
|
||||
...
|
||||
|
||||
|
@ -199,7 +201,7 @@ class ModResourceLoader:
|
|||
namespace: str | None = None,
|
||||
glob: str | list[str] = "**/*",
|
||||
decode: Callable[[str], _T] = decode_json_dict,
|
||||
export: Callable[[_T, _T | None], str] | Literal[False] | None = None,
|
||||
export: ExportFn[_T] | Literal[False] | None = None,
|
||||
) -> Iterator[tuple[PathResourceDir, ResourceLocation, _T]]:
|
||||
"""Search for a glob under a given resource location in all of `resource_dirs`.
|
||||
|
||||
|
@ -252,7 +254,7 @@ class ModResourceLoader:
|
|||
id = ResourceLocation(
|
||||
# eg. ["assets", "hexcasting", "lang", ...][1]
|
||||
namespace=path.relative_to(resource_dir.path).parts[1],
|
||||
path=without_suffix(path.relative_to(base_path)).as_posix(),
|
||||
path=strip_suffixes(path.relative_to(base_path)).as_posix(),
|
||||
)
|
||||
|
||||
try:
|
||||
|
@ -279,7 +281,7 @@ class ModResourceLoader:
|
|||
path: Path,
|
||||
*,
|
||||
decode: Callable[[str], _T] = decode_json_dict,
|
||||
export: Callable[[_T, _T | None], str] | Literal[False] | None = None,
|
||||
export: ExportFn[_T] | Literal[False] | None = None,
|
||||
) -> _T:
|
||||
if not path.is_file():
|
||||
raise FileNotFoundError(path)
|
||||
|
@ -313,7 +315,7 @@ class ModResourceLoader:
|
|||
value: _T,
|
||||
*,
|
||||
decode: Callable[[str], _T] = decode_json_dict,
|
||||
export: Callable[[_T, _T | None], str] | None = None,
|
||||
export: ExportFn[_T] | None = None,
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
@ -324,22 +326,26 @@ class ModResourceLoader:
|
|||
value: _T = None,
|
||||
*,
|
||||
decode: Callable[[str], _T] = decode_json_dict,
|
||||
export: Callable[[_T, _T | None], str] | None = None,
|
||||
export: ExportFn[_T] | None = None,
|
||||
) -> None:
|
||||
out_path = self.props.export_dir / path
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
logging.getLogger(__name__).debug(f"Exporting {path} to {out_path}")
|
||||
match export:
|
||||
case None:
|
||||
out_data = data
|
||||
case _:
|
||||
try:
|
||||
old_value = decode(out_path.read_text("utf-8"))
|
||||
except FileNotFoundError:
|
||||
old_value = None
|
||||
out_data = export(value, old_value)
|
||||
if export is None:
|
||||
out_data = data
|
||||
else:
|
||||
try:
|
||||
old_value = decode(out_path.read_text("utf-8"))
|
||||
except FileNotFoundError:
|
||||
old_value = None
|
||||
|
||||
match export(value, old_value, out_path):
|
||||
case str(out_data):
|
||||
pass
|
||||
case (str(out_data), Path() as out_path):
|
||||
pass
|
||||
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
out_path.write_text(out_data, "utf-8")
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from pkg_resources import iter_entry_points
|
|||
from pydantic import ValidationInfo, model_validator
|
||||
from pydantic.functional_validators import ModelWrapValidatorHandler
|
||||
|
||||
from .model import HexDocModel
|
||||
from .model import HexdocModel
|
||||
from .resource import ResourceLocation
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ def load_entry_points(group: str):
|
|||
raise
|
||||
|
||||
|
||||
class InternallyTaggedUnion(HexDocModel):
|
||||
class InternallyTaggedUnion(HexdocModel):
|
||||
"""Implements [internally tagged unions](https://serde.rs/enum-representations.html#internally-tagged)
|
||||
using the [Registry pattern](https://charlesreid1.github.io/python-patterns-the-registry.html).
|
||||
|
||||
|
|
|
@ -103,7 +103,31 @@ class TryGetEnum(Enum):
|
|||
return None
|
||||
|
||||
|
||||
def without_suffix(path: Path) -> Path:
|
||||
def strip_suffixes(path: Path) -> Path:
|
||||
"""Removes all suffixes from a path. This is helpful because `path.with_suffix("")`
|
||||
only removes the last suffix.
|
||||
|
||||
For example:
|
||||
```py
|
||||
path = Path("lang/en_us.flatten.json5")
|
||||
strip_suffixes(path) # lang/en_us
|
||||
path.with_suffix("") # lang/en_us.flatten
|
||||
```
|
||||
"""
|
||||
while path.suffix:
|
||||
path = path.with_suffix("")
|
||||
return path
|
||||
|
||||
|
||||
def replace_suffixes(path: Path, suffix: str) -> Path:
|
||||
"""Replaces all suffixes of a path. This is helpful because `path.with_suffix()`
|
||||
only replaces the last suffix.
|
||||
|
||||
For example:
|
||||
```py
|
||||
path = Path("lang/en_us.flatten.json5")
|
||||
replace_suffixes(path, ".json") # lang/en_us.json
|
||||
path.with_suffix(".json") # lang/en_us.flatten.json
|
||||
```
|
||||
"""
|
||||
return strip_suffixes(path).with_suffix(suffix)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,16 +2,17 @@ import subprocess
|
|||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from hexdoc.hexdoc import Args, main
|
||||
|
||||
PROPS = "doc/properties.toml"
|
||||
|
||||
|
||||
def test_file(tmp_path: Path, snapshot: SnapshotAssertion):
|
||||
# generate output docs html file and assert it hasn't changed vs. the snapshot
|
||||
out_path = tmp_path / "out.html"
|
||||
main(Args.parse_args(["properties.toml", "-o", out_path.as_posix()]))
|
||||
main(Args.parse_args([PROPS, "-o", out_path.as_posix()]))
|
||||
assert out_path.read_text("utf-8") == snapshot
|
||||
|
||||
|
||||
|
@ -19,13 +20,8 @@ def test_cmd(tmp_path: Path, snapshot: SnapshotAssertion):
|
|||
# as above, but running the command we actually want to be using
|
||||
out_path = tmp_path / "out.html"
|
||||
subprocess.run(
|
||||
["hexdoc", "properties.toml", "-o", out_path.as_posix()],
|
||||
["hexdoc", PROPS, "-o", out_path.as_posix()],
|
||||
stdout=sys.stdout,
|
||||
stderr=sys.stderr,
|
||||
)
|
||||
assert out_path.read_text("utf-8") == snapshot
|
||||
|
||||
|
||||
def test_stdout(capsys: pytest.CaptureFixture[str], snapshot: SnapshotAssertion):
|
||||
main(Args.parse_args(["properties.toml"]))
|
||||
assert capsys.readouterr() == snapshot
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
requires = ["hatchling", "hatch-gradle-version>=0.2.0"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
# project metadata
|
||||
|
||||
[project]
|
||||
name = "hexdoc"
|
||||
version = "0.11.0.1.0" # TODO: make a Hatch plugin to auto-set the mod version after the +
|
||||
dynamic = ["version"]
|
||||
authors = [
|
||||
{ name="object-Object", email="object@objectobject.ca" },
|
||||
{ name="Alwinfy" },
|
||||
]
|
||||
readme = "README.md"
|
||||
readme = "doc/README.md"
|
||||
classifiers = [
|
||||
"Framework :: Hatch",
|
||||
]
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"typing_extensions>=4.7.0",
|
||||
|
@ -26,18 +30,32 @@ dev = [
|
|||
"isort==5.12.0",
|
||||
"pytest>=7.3.1",
|
||||
"syrupy>=4.0.2",
|
||||
"hatchling",
|
||||
]
|
||||
|
||||
[tool.hatch.build]
|
||||
packages = [
|
||||
"src/hexdoc",
|
||||
"src/hexdoc_templates",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
hexdoc = "hexdoc.hexdoc:main"
|
||||
|
||||
# Gradle version/deps
|
||||
|
||||
[tool.hatch.version]
|
||||
source = "gradle-properties"
|
||||
py-version = "1.0"
|
||||
|
||||
# directory inclusion
|
||||
|
||||
[tool.hatch.build]
|
||||
only-include = [
|
||||
"doc/src/hexdoc",
|
||||
"gradle.properties",
|
||||
]
|
||||
artifacts = [
|
||||
"/doc/src/hexdoc/_export/generated",
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
sources = ["doc/src"]
|
||||
|
||||
# hexdoc entry points
|
||||
|
||||
[project.entry-points."hexdoc.export"]
|
||||
hexcasting = "hexdoc._export:__resources__"
|
||||
|
@ -57,6 +75,7 @@ hexcasting = "hexdoc.hexcasting.hex_recipes"
|
|||
[project.entry-points."hexdoc.BrainsweepeeIngredient"]
|
||||
hexcasting = "hexdoc.hexcasting.hex_recipes"
|
||||
|
||||
# Pytest
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = ["--import-mode=importlib"]
|
||||
|
@ -64,14 +83,22 @@ addopts = ["--import-mode=importlib"]
|
|||
[tool.coverage.report]
|
||||
include_namespace_packages = true
|
||||
|
||||
# formatting and linting
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
combine_as_imports = true
|
||||
known_first_party = ["hexdoc"]
|
||||
|
||||
[tool.pyright]
|
||||
pythonVersion = "3.11"
|
||||
pythonPlatform = "All"
|
||||
|
||||
include = [
|
||||
"doc/src/hexdoc",
|
||||
"doc/src/hexdoc_templates",
|
||||
]
|
||||
|
||||
# mostly we use strict mode
|
||||
# but pyright doesn't allow decreasing error severity in strict mode
|
||||
# so we need to manually specify all of the strict mode overrides so we can do that :/
|
Loading…
Reference in a new issue