Skip to content

Commit 9dbb20b

Browse files
committed
Add Nox and get cookiecutter test working
1 parent b324a1e commit 9dbb20b

File tree

13 files changed

+201
-39
lines changed

13 files changed

+201
-39
lines changed

.github/workflows/ci.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Run CI
2+
3+
on:
4+
push:
5+
branches: main
6+
7+
permissions:
8+
contents: read
9+
10+
concurrency:
11+
group: ci
12+
cancel-in-progress: false
13+
14+
jobs:
15+
test:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
- uses: actions/setup-python@v4
20+
with:
21+
python-version: '3.11'
22+
23+
- name: Install Nox
24+
run: pip install nox
25+
26+
- name: Run tests
27+
run: nox

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
<img alt="hexdoc logo" src="https://github.com/object-Object/hexdoc/raw/main/media/hexdoc.svg" height="200" />
33
<br /><br />
44
<a href="https://hexdoc.hexxy.media/"><img alt="Docs - hexdoc.hexxy.media" src="https://img.shields.io/badge/docs-hexdoc.hexxy.media-darkmagenta"></a>
5+
<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>
56
<a href="https://pypi.org/project/hexdoc/"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/hexdoc"></a>
67
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/hexdoc">
7-
<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>
8+
<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>
89
</p>
910

1011
# hexdoc

cookiecutter.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@
22
"output_directory": "",
33

44
"modid": "",
5+
"book_id": "hexcasting:thehexbook",
56
"mod_display_name": "{{ cookiecutter.modid|capitalize }}",
67
"plugin_classname": "{{ cookiecutter.modid|capitalize }}Plugin",
8+
79
"gradle_mod_version_key": "modVersion",
10+
"multiloader": true,
11+
"java_lang": ["java", "kotlin"],
12+
"java_package": "com/example/{{ cookiecutter.modid }}",
13+
"pattern_registry": "registry/{{ cookiecutter.modid|capitalize }}PatternRegistry.{{ 'java' if cookiecutter.java_lang == 'java' else 'kt' }}",
814

915
"github_repo": "{{ cookiecutter.modid|capitalize }}",
1016
"author": "TODO",

noxfile.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import nox
2+
3+
4+
@nox.session
5+
def lint(session: nox.Session):
6+
session.install("favicons") # TODO: remove
7+
session.install(".[test]", "nox", "pyright")
8+
9+
session.run("pyright", "--warnings")
10+
11+
12+
@nox.session
13+
def tests(session: nox.Session):
14+
session.install("favicons") # TODO: remove
15+
session.install(".[test]", "./test/_submodules/HexMod")
16+
17+
# test cookiecutter last so the extra package install doesn't interfere
18+
session.run("pytest", "-k", "not test_cookiecutter")
19+
session.run("pytest", "-k", "test_cookiecutter")

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ dev = [
7070
"black==23.7.0",
7171
"isort==5.12.0",
7272
"hatch",
73-
"build",
73+
"nox",
7474
]
7575

7676
[project.urls]

src/hexdoc/minecraft/assets/textures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def find(
8686
for missing_id in props.textures.missing:
8787
for id in ids:
8888
if id.match(missing_id):
89-
logging.getLogger(__name__).warn(message)
89+
logging.getLogger(__name__).warning(message)
9090
return Texture(file_id=id, url=MISSING_TEXTURE)
9191

9292
raise KeyError(message)

test/test_cookiecutter.py

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,117 @@
11
# pyright: reportUnknownMemberType=false
22

3+
import json
4+
import subprocess
5+
import sys
6+
from pathlib import Path
7+
from textwrap import dedent
8+
39
from pytest import MonkeyPatch
410
from pytest_cookies.plugin import Cookies
511

12+
from hexdoc._cli.app import render
13+
14+
from .conftest import longrun
615

16+
17+
@longrun
718
def test_cookiecutter(cookies: Cookies, monkeypatch: MonkeyPatch):
819
result = cookies.bake(
920
{
1021
"output_directory": "output",
1122
"modid": "mod",
1223
"pattern_regex": "hex_latest",
24+
"multiloader": False,
25+
"java_package": "com/package",
26+
"pattern_registry": "Patterns.java",
1327
}
1428
)
1529

1630
assert result.exception is None
1731
assert result.project_path is not None
1832

33+
monkeypatch.chdir(result.project_path)
34+
subprocess.run(["git", "init"], check=True)
35+
36+
Path("gradle.properties").write_text(
37+
dedent(
38+
f"""\
39+
modVersion=1.0.0
40+
hexcastingVersion=0.11.1-7
41+
minecraftVersion=1.20.1
42+
"""
43+
)
44+
)
45+
46+
java_root = Path("src/main/java/com/package")
47+
java_root.mkdir(parents=True)
48+
(java_root / "Patterns.java").touch()
49+
50+
Path("src/generated/resources").mkdir(parents=True)
51+
52+
book_root = Path(
53+
"src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us"
54+
)
55+
book_root.mkdir(parents=True)
56+
57+
category_root = book_root / "categories"
58+
category_root.mkdir(parents=True)
59+
with open(category_root / "foo.json", "w") as f:
60+
json.dump(
61+
{
62+
"name": "hexdoc.mod.title",
63+
"icon": "minecraft:amethyst_shard",
64+
"description": "hexcasting.category.basics.desc",
65+
"sortnum": 0,
66+
},
67+
f,
68+
)
69+
70+
entry_root = book_root / "entries"
71+
(entry_root / "foo").mkdir(parents=True)
72+
with open(entry_root / "foo" / "bar.json", "w") as f:
73+
json.dump(
74+
{
75+
"name": "hexdoc.welcome.header",
76+
"category": "hexcasting:foo",
77+
"icon": "minecraft:textures/mob_effect/nausea.png",
78+
"sortnum": 0,
79+
"advancement": "hexcasting:y_u_no_cast_angy",
80+
"pages": [
81+
{
82+
"type": "patchouli:text",
83+
"text": "hexcasting.page.couldnt_cast.1",
84+
},
85+
],
86+
},
87+
f,
88+
)
89+
90+
(result.project_path / ".env").write_text(
91+
dedent(
92+
f"""\
93+
GITHUB_REPOSITORY=GITHUB/REPOSITORY
94+
GITHUB_SHA=GITHUB_SHA
95+
GITHUB_PAGES_URL=GITHUB_PAGES_URL"""
96+
)
97+
)
98+
99+
# TODO: remove when textures stop being broken
100+
with open(result.project_path / "doc" / "properties.toml", "a") as f:
101+
f.write(
102+
dedent(
103+
"""
104+
[textures]
105+
missing = [
106+
"minecraft:*",
107+
"hexcasting:*",
108+
]
109+
"""
110+
)
111+
)
112+
19113
monkeypatch.syspath_prepend(result.project_path / "doc" / "src")
20114

21-
import hexdoc_mod # type: ignore
115+
subprocess.run([sys.executable, "-m", "pip", "install", "-e", "."])
116+
117+
render()

{{cookiecutter.output_directory}}/doc/nodemon.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"doc/src",
44
"doc/resources",
55
"doc/properties.toml",
6-
"Common/src/main/resources/assets/*/lang"
6+
"{{ 'common/src' if cookiecutter.multiloader else 'src' }}/main/resources/assets/*/lang"
77
],
88
"ignore": ["**/generated/**"],
99
"ext": "jinja,html,css,js,ts,toml,json,json5,py",
Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,73 @@
11
modid = "{{ cookiecutter.modid }}"
2-
book = "hexcasting:thehexbook"
2+
book = "{{ cookiecutter.book_id }}"
33
default_lang = "en_us"
44

5-
_export_root = "{{ cookiecutter.__export_root }}"
65
resource_dirs = [ # top takes priority
7-
{ path="{^_export_root}/resources", reexport=false },
6+
"resources",
87
"{_common.src}/main/resources",
98
"{_common.src}/generated/resources",
9+
{% if cookiecutter.multiloader -%}
1010
"{_fabric.src}/main/resources",
1111
"{_fabric.src}/generated/resources",
1212
"{_forge.src}/main/resources",
1313
"{_forge.src}/generated/resources",
14+
{%- endif %}
1415
{ modid="hexcasting" },
16+
{ modid="hexdoc" },
1517
]
16-
export_dir = "{_export_root}/generated"
18+
export_dir = "{{ cookiecutter.__export_root }}/generated"
1719

18-
{# beware of eldritch abombinations lurking beneath these waters -#}
20+
[extra.hexcasting]
21+
# regexes for parsing pattern registry files - try uncommenting a different one if your patterns aren't loading
1922
# NOTE: "!Raw" means "don't apply variable interpolation to this value"
20-
{% if cookiecutter.pattern_regex == "hex_latest" -%}
21-
_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+)\)' }
22-
{% elif cookiecutter.pattern_regex == "hex_0.10.3" -%}
23-
_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)\);)?' }
24-
{% elif cookiecutter.pattern_regex == "hexal_0.3.0" -%}
25-
_pattern_regex = { "!Raw"='make\(\s*"(?P<name>[a-zA-Z0-9_\/]+)",\s*HexPattern\.fromAngles\(\s*"(?P<signature>[aqweds]+)",\s*HexDir.(?P<startdir>\w+)\)' }
26-
{% elif cookiecutter.pattern_regex == "hexal_0.2.18" -%}
27-
{#- :yea: -#}
28-
_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)(?:.))+$))' }
29-
{% else %}
30-
{# intentionally crash the template because we got an unhandled value #}
31-
{{ 0/0 }}
32-
{% endif %}
3323

34-
[[pattern_stubs]]
35-
path = "{^_common.package}/TODO/TODO.java"
24+
# Hex Casting (0.11.0)
25+
{{ "# " 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+)\)' }
26+
27+
# Hex Casting (0.10.3)
28+
{{ "# " 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)\);)?' }
29+
30+
# Hexal (0.3.0)
31+
{{ "# " 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+)\)' }
32+
33+
# Hexal (0.2.18)
34+
{{ "# " 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)(?:.))+$))' }
35+
36+
[[extra.hexcasting.pattern_stubs]]
37+
path = "{^^^_common.package}/{{ cookiecutter.pattern_registry }}"
3638
regex = "{^_pattern_regex}"
3739

40+
[minecraft_assets]
41+
# https://github.com/PrismarineJS/minecraft-assets/tree/83e2169afbbce40990d69fc53e5962e4a793d467/data/1.19.1
42+
ref = "83e2169afbbce40990d69fc53e5962e4a793d467"
43+
version = "1.19.1"
44+
3845
[template]
39-
static_dir = "static"
46+
icon = "icon.png"
4047
include = [
4148
"{{ cookiecutter.modid }}",
4249
"hexcasting",
4350
"patchouli",
51+
"hexdoc",
4452
]
4553

4654
[template.args]
4755
mod_name = "{{ cookiecutter.mod_display_name }}"
4856
author = "{{ cookiecutter.author }}"
49-
icon_href = "icon.png"
5057
show_landing_text = false
5158

52-
5359
# platforms
5460

5561
[_common]
56-
src = "../Common/src"
57-
package = "{src}/main/java/TODO/{{ cookiecutter.modid }}"
62+
src = "../{{ 'common/src' if cookiecutter.multiloader else 'src' }}"
63+
package = "{src}/main/{{ cookiecutter.java_lang }}/{{ cookiecutter.java_package }}"
5864

65+
{% if cookiecutter.multiloader -%}
5966
[_fabric]
60-
src = "../Fabric/src"
61-
package = "{src}/main/java/TODO/{{ cookiecutter.modid }}/fabric"
67+
src = "../fabric/src"
68+
package = "{src}/main/{{ cookiecutter.java_lang }}/{{ cookiecutter.java_package }}/fabric"
6269

6370
[_forge]
64-
src = "../Forge/src"
65-
package = "{src}/main/java/TODO/{{ cookiecutter.modid }}/forge"
71+
src = "../forge/src"
72+
package = "{src}/main/{{ cookiecutter.java_lang }}/{{ cookiecutter.java_package }}/forge"
73+
{%- endif %}

{{cookiecutter.output_directory}}/doc/src/{{cookiecutter.__project_slug}}/_export/resources/__init__.py

Lines changed: 0 additions & 2 deletions
This file was deleted.

{{cookiecutter.output_directory}}/doc/src/{{cookiecutter.__project_slug}}/_hooks.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,39 @@
55
LoadJinjaTemplatesImpl,
66
LoadResourceDirsImpl,
77
ModVersionImpl,
8+
MinecraftVersionImpl,
89
hookimpl,
910
)
1011

1112
import {{ cookiecutter.__project_slug }}
1213

13-
from .__gradle_version__ import GRADLE_VERSION
14+
from .__gradle_version__ import GRADLE_VERSION, MINECRAFT_VERSION
1415

1516

1617
class {{ cookiecutter.plugin_classname }}(
1718
LoadJinjaTemplatesImpl,
1819
LoadResourceDirsImpl,
1920
ModVersionImpl,
21+
MinecraftVersionImpl,
2022
):
2123
@staticmethod
2224
@hookimpl
2325
def hexdoc_mod_version() -> str:
2426
return GRADLE_VERSION
2527

28+
@staticmethod
29+
@hookimpl
30+
def hexdoc_minecraft_version() -> str:
31+
return MINECRAFT_VERSION
32+
2633
@staticmethod
2734
@hookimpl
2835
def hexdoc_load_resource_dirs() -> HookReturn[Package]:
2936
# This needs to be a lazy import because they may not exist when this file is
3037
# first loaded, eg. when generating the contents of generated.
31-
from ._export import generated, resources
38+
from ._export import generated
3239

33-
return [generated, resources]
40+
return generated
3441

3542
@staticmethod
3643
@hookimpl

0 commit comments

Comments
 (0)