Skip to content

Commit

Permalink
Add Nox and get cookiecutter test working
Browse files Browse the repository at this point in the history
  • Loading branch information
object-Object committed Nov 5, 2023
1 parent b324a1e commit 9dbb20b
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 39 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Run CI

on:
push:
branches: main

permissions:
contents: read

concurrency:
group: ci
cancel-in-progress: false

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install Nox
run: pip install nox

- name: Run tests
run: nox
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
<img alt="hexdoc logo" src="https://github.com/object-Object/hexdoc/raw/main/media/hexdoc.svg" height="200" />
<br /><br />
<a href="https://hexdoc.hexxy.media/"><img alt="Docs - hexdoc.hexxy.media" src="https://img.shields.io/badge/docs-hexdoc.hexxy.media-darkmagenta"></a>
<a href="https://github.com/object-Object/hexdoc/actions/workflows/ci.yml"><img alt="GitHub Workflow Status (with event)" src="https://img.shields.io/github/actions/workflow/status/object-Object/hexdoc/ci.yml?logo=github&label=CI"></a>
<a href="https://pypi.org/project/hexdoc/"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/hexdoc"></a>
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/hexdoc">
<a href="https://github.com/object-Object/hexdoc/actions"><img alt="GitHub deployments" src="https://img.shields.io/github/deployments/object-Object/hexdoc/pypi?logo=github&label=CI"></a>
<a href="https://pydantic.dev"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v2.json" alt="Pydantic Version 2" style="max-width:100%;"></a>
</p>

# hexdoc
Expand Down
6 changes: 6 additions & 0 deletions cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@
"output_directory": "",

"modid": "",
"book_id": "hexcasting:thehexbook",
"mod_display_name": "{{ cookiecutter.modid|capitalize }}",
"plugin_classname": "{{ cookiecutter.modid|capitalize }}Plugin",

"gradle_mod_version_key": "modVersion",
"multiloader": true,
"java_lang": ["java", "kotlin"],
"java_package": "com/example/{{ cookiecutter.modid }}",
"pattern_registry": "registry/{{ cookiecutter.modid|capitalize }}PatternRegistry.{{ 'java' if cookiecutter.java_lang == 'java' else 'kt' }}",

"github_repo": "{{ cookiecutter.modid|capitalize }}",
"author": "TODO",
Expand Down
19 changes: 19 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import nox


@nox.session
def lint(session: nox.Session):
session.install("favicons") # TODO: remove
session.install(".[test]", "nox", "pyright")

session.run("pyright", "--warnings")


@nox.session
def tests(session: nox.Session):
session.install("favicons") # TODO: remove
session.install(".[test]", "./test/_submodules/HexMod")

# test cookiecutter last so the extra package install doesn't interfere
session.run("pytest", "-k", "not test_cookiecutter")
session.run("pytest", "-k", "test_cookiecutter")
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ dev = [
"black==23.7.0",
"isort==5.12.0",
"hatch",
"build",
"nox",
]

[project.urls]
Expand Down
2 changes: 1 addition & 1 deletion src/hexdoc/minecraft/assets/textures.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def find(
for missing_id in props.textures.missing:
for id in ids:
if id.match(missing_id):
logging.getLogger(__name__).warn(message)
logging.getLogger(__name__).warning(message)
return Texture(file_id=id, url=MISSING_TEXTURE)

raise KeyError(message)
Expand Down
98 changes: 97 additions & 1 deletion test/test_cookiecutter.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,117 @@
# pyright: reportUnknownMemberType=false

import json
import subprocess
import sys
from pathlib import Path
from textwrap import dedent

from pytest import MonkeyPatch
from pytest_cookies.plugin import Cookies

from hexdoc._cli.app import render

from .conftest import longrun


@longrun
def test_cookiecutter(cookies: Cookies, monkeypatch: MonkeyPatch):
result = cookies.bake(
{
"output_directory": "output",
"modid": "mod",
"pattern_regex": "hex_latest",
"multiloader": False,
"java_package": "com/package",
"pattern_registry": "Patterns.java",
}
)

assert result.exception is None
assert result.project_path is not None

monkeypatch.chdir(result.project_path)
subprocess.run(["git", "init"], check=True)

Path("gradle.properties").write_text(
dedent(
f"""\
modVersion=1.0.0
hexcastingVersion=0.11.1-7
minecraftVersion=1.20.1
"""
)
)

java_root = Path("src/main/java/com/package")
java_root.mkdir(parents=True)
(java_root / "Patterns.java").touch()

Path("src/generated/resources").mkdir(parents=True)

book_root = Path(
"src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us"
)
book_root.mkdir(parents=True)

category_root = book_root / "categories"
category_root.mkdir(parents=True)
with open(category_root / "foo.json", "w") as f:
json.dump(
{
"name": "hexdoc.mod.title",
"icon": "minecraft:amethyst_shard",
"description": "hexcasting.category.basics.desc",
"sortnum": 0,
},
f,
)

entry_root = book_root / "entries"
(entry_root / "foo").mkdir(parents=True)
with open(entry_root / "foo" / "bar.json", "w") as f:
json.dump(
{
"name": "hexdoc.welcome.header",
"category": "hexcasting:foo",
"icon": "minecraft:textures/mob_effect/nausea.png",
"sortnum": 0,
"advancement": "hexcasting:y_u_no_cast_angy",
"pages": [
{
"type": "patchouli:text",
"text": "hexcasting.page.couldnt_cast.1",
},
],
},
f,
)

(result.project_path / ".env").write_text(
dedent(
f"""\
GITHUB_REPOSITORY=GITHUB/REPOSITORY
GITHUB_SHA=GITHUB_SHA
GITHUB_PAGES_URL=GITHUB_PAGES_URL"""
)
)

# TODO: remove when textures stop being broken
with open(result.project_path / "doc" / "properties.toml", "a") as f:
f.write(
dedent(
"""
[textures]
missing = [
"minecraft:*",
"hexcasting:*",
]
"""
)
)

monkeypatch.syspath_prepend(result.project_path / "doc" / "src")

import hexdoc_mod # type: ignore
subprocess.run([sys.executable, "-m", "pip", "install", "-e", "."])

render()
2 changes: 1 addition & 1 deletion {{cookiecutter.output_directory}}/doc/nodemon.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"doc/src",
"doc/resources",
"doc/properties.toml",
"Common/src/main/resources/assets/*/lang"
"{{ 'common/src' if cookiecutter.multiloader else 'src' }}/main/resources/assets/*/lang"
],
"ignore": ["**/generated/**"],
"ext": "jinja,html,css,js,ts,toml,json,json5,py",
Expand Down
66 changes: 37 additions & 29 deletions {{cookiecutter.output_directory}}/doc/properties.toml
Original file line number Diff line number Diff line change
@@ -1,65 +1,73 @@
modid = "{{ cookiecutter.modid }}"
book = "hexcasting:thehexbook"
book = "{{ cookiecutter.book_id }}"
default_lang = "en_us"

_export_root = "{{ cookiecutter.__export_root }}"
resource_dirs = [ # top takes priority
{ path="{^_export_root}/resources", reexport=false },
"resources",
"{_common.src}/main/resources",
"{_common.src}/generated/resources",
{% if cookiecutter.multiloader -%}
"{_fabric.src}/main/resources",
"{_fabric.src}/generated/resources",
"{_forge.src}/main/resources",
"{_forge.src}/generated/resources",
{%- endif %}
{ modid="hexcasting" },
{ modid="hexdoc" },
]
export_dir = "{_export_root}/generated"
export_dir = "{{ cookiecutter.__export_root }}/generated"

{# beware of eldritch abombinations lurking beneath these waters -#}
[extra.hexcasting]
# regexes for parsing pattern registry files - try uncommenting a different one if your patterns aren't loading
# NOTE: "!Raw" means "don't apply variable interpolation to this value"
{% if cookiecutter.pattern_regex == "hex_latest" -%}
_pattern_regex = { "!Raw"='make\(\s*"(?P<name>[a-zA-Z0-9_\/]+)",\s*(?:new )?(?:ActionRegistryEntry|OperationAction)\(\s*HexPattern\.fromAngles\(\s*"(?P<signature>[aqweds]+)",\s*HexDir.(?P<startdir>\w+)\)' }
{% elif cookiecutter.pattern_regex == "hex_0.10.3" -%}
_pattern_regex = { "!Raw"='HexPattern\.fromAngles\("(?P<signature>[qweasd]+)", HexDir\.(?P<startdir>\w+)\),\s*modLoc\("(?P<name>[^"]+)"\)[^;]+?(?:makeConstantOp|Op\w+|Widget\.\w+)(?:[^;]*(?P<is_per_world>true)\);)?' }
{% elif cookiecutter.pattern_regex == "hexal_0.3.0" -%}
_pattern_regex = { "!Raw"='make\(\s*"(?P<name>[a-zA-Z0-9_\/]+)",\s*HexPattern\.fromAngles\(\s*"(?P<signature>[aqweds]+)",\s*HexDir.(?P<startdir>\w+)\)' }
{% elif cookiecutter.pattern_regex == "hexal_0.2.18" -%}
{#- :yea: -#}
_pattern_regex = { "!Raw"='(?s-m:HexPattern\.fromAngles\("(?P<signature>[qweasd]+)", HexDir\.(?P<startdir>\w+)\),\s*modLoc\("(?P<name>[^"]+)"\),[^,]+?(?:makeConstantOp|Op\w+).*?(?P<is_per_world>\btrue)?\)(?:[^\)]+?\bval\b|(?:(?!\bval\b)(?:.))+$))' }
{% else %}
{# intentionally crash the template because we got an unhandled value #}
{{ 0/0 }}
{% endif %}

[[pattern_stubs]]
path = "{^_common.package}/TODO/TODO.java"
# Hex Casting (0.11.0)
{{ "# " if cookiecutter.pattern_regex != "hex_latest" }}_pattern_regex = { "!Raw"='make\(\s*"(?P<name>[a-zA-Z0-9_\/]+)",\s*(?:new )?(?:ActionRegistryEntry|OperationAction)\(\s*HexPattern\.fromAngles\(\s*"(?P<signature>[aqweds]+)",\s*HexDir.(?P<startdir>\w+)\)' }

# Hex Casting (0.10.3)
{{ "# " if cookiecutter.pattern_regex != "hex_0.10.3" }}_pattern_regex = { "!Raw"='HexPattern\.fromAngles\("(?P<signature>[qweasd]+)", HexDir\.(?P<startdir>\w+)\),\s*modLoc\("(?P<name>[^"]+)"\)[^;]+?(?:makeConstantOp|Op\w+|Widget\.\w+)(?:[^;]*(?P<is_per_world>true)\);)?' }

# Hexal (0.3.0)
{{ "# " if cookiecutter.pattern_regex != "hexal_0.3.0" }}_pattern_regex = { "!Raw"='make\(\s*"(?P<name>[a-zA-Z0-9_\/]+)",\s*HexPattern\.fromAngles\(\s*"(?P<signature>[aqweds]+)",\s*HexDir.(?P<startdir>\w+)\)' }

# Hexal (0.2.18)
{{ "# " if cookiecutter.pattern_regex != "hexal_0.2.18" }}_pattern_regex = { "!Raw"='(?s-m:HexPattern\.fromAngles\("(?P<signature>[qweasd]+)", HexDir\.(?P<startdir>\w+)\),\s*modLoc\("(?P<name>[^"]+)"\),[^,]+?(?:makeConstantOp|Op\w+).*?(?P<is_per_world>\btrue)?\)(?:[^\)]+?\bval\b|(?:(?!\bval\b)(?:.))+$))' }

[[extra.hexcasting.pattern_stubs]]
path = "{^^^_common.package}/{{ cookiecutter.pattern_registry }}"
regex = "{^_pattern_regex}"

[minecraft_assets]
# https://github.com/PrismarineJS/minecraft-assets/tree/83e2169afbbce40990d69fc53e5962e4a793d467/data/1.19.1
ref = "83e2169afbbce40990d69fc53e5962e4a793d467"
version = "1.19.1"

[template]
static_dir = "static"
icon = "icon.png"
include = [
"{{ cookiecutter.modid }}",
"hexcasting",
"patchouli",
"hexdoc",
]

[template.args]
mod_name = "{{ cookiecutter.mod_display_name }}"
author = "{{ cookiecutter.author }}"
icon_href = "icon.png"
show_landing_text = false


# platforms

[_common]
src = "../Common/src"
package = "{src}/main/java/TODO/{{ cookiecutter.modid }}"
src = "../{{ 'common/src' if cookiecutter.multiloader else 'src' }}"
package = "{src}/main/{{ cookiecutter.java_lang }}/{{ cookiecutter.java_package }}"

{% if cookiecutter.multiloader -%}
[_fabric]
src = "../Fabric/src"
package = "{src}/main/java/TODO/{{ cookiecutter.modid }}/fabric"
src = "../fabric/src"
package = "{src}/main/{{ cookiecutter.java_lang }}/{{ cookiecutter.java_package }}/fabric"

[_forge]
src = "../Forge/src"
package = "{src}/main/java/TODO/{{ cookiecutter.modid }}/forge"
src = "../forge/src"
package = "{src}/main/{{ cookiecutter.java_lang }}/{{ cookiecutter.java_package }}/forge"
{%- endif %}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,39 @@
LoadJinjaTemplatesImpl,
LoadResourceDirsImpl,
ModVersionImpl,
MinecraftVersionImpl,
hookimpl,
)

import {{ cookiecutter.__project_slug }}

from .__gradle_version__ import GRADLE_VERSION
from .__gradle_version__ import GRADLE_VERSION, MINECRAFT_VERSION


class {{ cookiecutter.plugin_classname }}(
LoadJinjaTemplatesImpl,
LoadResourceDirsImpl,
ModVersionImpl,
MinecraftVersionImpl,
):
@staticmethod
@hookimpl
def hexdoc_mod_version() -> str:
return GRADLE_VERSION

@staticmethod
@hookimpl
def hexdoc_minecraft_version() -> str:
return MINECRAFT_VERSION

@staticmethod
@hookimpl
def hexdoc_load_resource_dirs() -> HookReturn[Package]:
# This needs to be a lazy import because they may not exist when this file is
# first loaded, eg. when generating the contents of generated.
from ._export import generated, resources
from ._export import generated

return [generated, resources]
return generated

@staticmethod
@hookimpl
Expand Down

0 comments on commit 9dbb20b

Please sign in to comment.