Use pluggy for fetching mod version

This commit is contained in:
object-Object 2023-09-05 01:26:00 -04:00
parent 6493f56b83
commit 1e64a589a9
10 changed files with 84 additions and 33 deletions

2
.vscode/launch.json vendored
View file

@ -16,7 +16,7 @@
"name": "Python: Generate Docs",
"type": "python",
"request": "launch",
"module": "hexdoc.hexdoc",
"module": "hexdoc.scripts.hexdoc",
"args": [
"doc/properties.toml", "-o", "out", "--lang", "en_us",
],

View file

@ -0,0 +1,7 @@
from hexdoc.__gradle_version__ import GRADLE_VERSION
from hexdoc.plugin import hookimpl
@hookimpl
def hexdoc_mod_version():
return GRADLE_VERSION

View file

@ -0,0 +1,5 @@
__all__ = ["hookimpl"]
from pluggy import HookimplMarker
hookimpl = HookimplMarker("hexdoc")

View file

@ -0,0 +1,10 @@
from pluggy import PluginManager
def name_hook_caller(pm: PluginManager, method_name: str, plugin_name: str):
return pm.subset_hook_caller(
name=method_name,
remove_plugins=(
plugin for name, plugin in pm.list_name_plugin() if name != plugin_name
),
)

View file

@ -0,0 +1,8 @@
from pluggy import HookspecMarker
hookspec = HookspecMarker("hexdoc")
@hookspec(firstresult=True)
def hexdoc_mod_version():
"""Return the mod version (aka `GRADLE_VERSION`) from `__gradle_version__.py`."""

View file

@ -6,6 +6,7 @@ import shutil
import sys
from argparse import ArgumentParser
from pathlib import Path
from types import NoneType
from typing import Self, Sequence
from jinja2 import (
@ -16,13 +17,16 @@ from jinja2 import (
Template,
)
from jinja2.sandbox import SandboxedEnvironment
from pluggy import PluginManager
from pydantic import model_validator
from hexdoc.__gradle_version__ import GRADLE_VERSION
from hexdoc.hexcasting.hex_book import load_hex_book
from hexdoc.minecraft import I18n
from hexdoc.patchouli import Book
from hexdoc.plugin import hookspecs
from hexdoc.plugin.helpers import name_hook_caller
from hexdoc.utils import HexdocModel, ModResourceLoader, Properties
from hexdoc.utils.deserialize import cast_or_raise, isinstance_or_raise
from hexdoc.utils.jinja_extensions import IncludeRawExtension, hexdoc_block, hexdoc_wrap
from hexdoc.utils.path import write_to_path
@ -113,15 +117,15 @@ class SitemapMarker(HexdocModel):
def main(args: Args | None = None) -> None:
# set stdout to utf-8 so printing to pipe or redirect doesn't break on Windows
# (common windows L)
cast_or_raise(sys.stdout, io.TextIOWrapper).reconfigure(encoding="utf-8")
cast_or_raise(sys.stderr, io.TextIOWrapper).reconfigure(encoding="utf-8")
# allow passing Args for test cases, but parse by default
if args is None:
args = Args.parse_args()
# set stdout to utf-8 so printing to pipe or redirect doesn't break on Windows
# (common windows L)
assert isinstance(sys.stdout, io.TextIOWrapper)
sys.stdout.reconfigure(encoding="utf-8")
# set up logging
logging.basicConfig(
style="{",
@ -130,18 +134,34 @@ def main(args: Args | None = None) -> None:
)
logger = logging.getLogger(__name__)
# Properties is the main config file for hexdoc
props = Properties.load(args.properties_file)
logger.debug(props)
# load plugins
# load entry points for props.modid first to make sure its version is added last
pm = PluginManager("hexdoc")
pm.add_hookspecs(hookspecs)
pm.load_setuptools_entrypoints("hexdoc")
pm.check_pending()
# get the current mod version
version = name_hook_caller(pm, "hexdoc_mod_version", props.modid)()
assert isinstance_or_raise(version, (str, NoneType))
if version is None:
raise ValueError(f"Missing hexdoc_mod_version hookimpl for {props.modid}")
print(f"Building docs for {props.modid} {version}")
# just list the languages and exit
if args.list_langs:
with ModResourceLoader.load_all(props, export=False) as loader:
with ModResourceLoader.load_all(props, version, export=False) as loader:
langs = sorted(I18n.list_all(loader))
print(json.dumps(langs))
return
# load everything
with ModResourceLoader.clean_and_load_all(props) as loader:
with ModResourceLoader.clean_and_load_all(props, version) as loader:
books = dict[str, Book]()
if args.lang:
@ -181,7 +201,8 @@ def main(args: Args | None = None) -> None:
if args.export_only:
return
# set up Jinja environment
# set up Jinja
env = SandboxedEnvironment(
# search order: template_dirs, template_packages
loader=ChoiceLoader(
@ -204,6 +225,8 @@ def main(args: Args | None = None) -> None:
template = env.get_template(props.template.main)
# render everything
assert (output_dir := args.output_dir)
if args.clean:
shutil.rmtree(output_dir, ignore_errors=True)
@ -212,11 +235,11 @@ def main(args: Args | None = None) -> None:
render_books(props, books, template, output_dir, "latest")
if args.is_release:
render_books(props, books, template, output_dir, GRADLE_VERSION)
render_books(props, books, template, output_dir, version)
# the default book should be the latest released version
if args.update_latest and args.is_release:
render_books(props, books, template, output_dir, GRADLE_VERSION, is_root=True)
render_books(props, books, template, output_dir, version, is_root=True)
def render_books(

View file

@ -6,7 +6,6 @@ from typing import Self, Sequence
from pydantic import Field, TypeAdapter
from hexdoc.__gradle_version__ import GRADLE_VERSION
from hexdoc.utils import DEFAULT_CONFIG, HexdocModel
from hexdoc.utils.path import write_to_path
@ -57,10 +56,11 @@ def main():
args = Args.parse_args()
# ensure at least the default language was built successfully
if args.is_release:
assert_version_exists(args.src, GRADLE_VERSION)
if args.update_latest:
assert_version_exists(args.src, "latest")
# TODO: figure out how to do this with pluggy
# if args.is_release:
# assert_version_exists(args.src, GRADLE_VERSION)
args.dst.mkdir(parents=True, exist_ok=True)

View file

@ -2,7 +2,7 @@ from enum import Enum
from functools import total_ordering
from typing import Any, Callable, Self
from hexdoc.__gradle_version__ import GRADLE_VERSION
from hexdoc.__gradle_version__ import GRADLE_VERSION as HEX_VERSION
@total_ordering
@ -14,9 +14,9 @@ class HexVersion(Enum):
@classmethod
def get(cls):
for version in cls:
if GRADLE_VERSION.startswith(version.value):
if HEX_VERSION.startswith(version.value):
return version
raise ValueError(f"Unknown mod version: {GRADLE_VERSION}")
raise ValueError(f"Unknown mod version: {HEX_VERSION}")
@classmethod
def check(cls, version: Self | Callable[[Self], bool] | bool, typ: type[Any] | str):
@ -33,7 +33,7 @@ class HexVersion(Enum):
if not isinstance(typ, str):
typ = typ.__name__
raise ValueError(f"{typ} is not supported in {GRADLE_VERSION}")
raise ValueError(f"{typ} is not supported in {HEX_VERSION}")
@property
def _sort_by(self):

View file

@ -9,7 +9,6 @@ from typing import Callable, Literal, Self, TypeVar, overload
from pydantic.dataclasses import dataclass
from hexdoc.__gradle_version__ import GRADLE_VERSION
from hexdoc.utils.deserialize import JSONDict, decode_json_dict
from hexdoc.utils.model import DEFAULT_CONFIG, HexdocModel, ValidationContext
from hexdoc.utils.path import strip_suffixes, write_to_path
@ -45,19 +44,21 @@ class ModResourceLoader:
def clean_and_load_all(
cls,
props: Properties,
version: str,
*,
export: bool = True,
):
# clear the export dir so we start with a clean slate
if props.export_dir and export:
subprocess.run(["git", "clean", "-fdX", props.export_dir])
return cls.load_all(props, export=export)
return cls.load_all(props, version, export=export)
@classmethod
@contextmanager
def load_all(
cls,
props: Properties,
version: str,
*,
export: bool = True,
) -> Iterator[Self]:
@ -78,7 +79,7 @@ class ModResourceLoader:
loader.export(
path=HexdocMetadata.path(props.modid),
data=HexdocMetadata(
book_url=f"{props.url}/v/{GRADLE_VERSION}",
book_url=f"{props.url}/v/{version}",
).model_dump_json(),
)

View file

@ -1,5 +1,5 @@
[build-system]
requires = ["hatchling"]
requires = ["hatchling", "hatch-gradle-version>=0.6.0"]
build-backend = "hatchling.build"
# project metadata
@ -8,7 +8,7 @@ build-backend = "hatchling.build"
name = "hexdoc"
dynamic = ["version"]
authors = [
{ name="object-Object", email="object@objectobject.ca" },
{ name="object-Object" },
{ name="Alwinfy" },
]
readme = "doc/README.md"
@ -17,18 +17,15 @@ classifiers = [
]
requires-python = ">=3.11"
dependencies = [
"hexdoc[build]", # required optional dependency i guess
"typing_extensions>=4.6.1",
"importlib_resources>=6.0.1",
"pydantic>=2.3.0",
"Jinja2>=3.1.2",
"pyjson5>=1.6.3",
"pluggy>=1.3.0",
]
[project.optional-dependencies]
build = [ # need these for build AND runtime
"hatch-gradle-version>=0.6.0",
]
dev = [
"black==23.7.0",
"isort==5.12.0",
@ -52,9 +49,6 @@ py-path = "doc/src/hexdoc/__version__.py"
# directory inclusion
[tool.hatch.build]
require-runtime-features = [
"build",
]
artifacts = [
"/doc/src/hexdoc/_export/generated",
"/doc/src/hexdoc/__gradle_version__.py",
@ -73,6 +67,9 @@ packages = [
# hexdoc entry points
[project.entry-points.hexdoc]
hexcasting = "hexdoc.hexcasting.hooks"
[project.entry-points."hexdoc.export"]
hexcasting = "hexdoc._export:__resources__"
@ -110,8 +107,8 @@ known_first_party = ["hexdoc"]
pythonVersion = "3.11"
pythonPlatform = "All"
include = [
"doc/src/hexdoc",
extraPaths = [
"doc/src",
]
# mostly we use strict mode