Add stricter pattern page validation

This commit is contained in:
object-Object 2023-08-23 08:34:06 -04:00
parent 2fa96babde
commit 036579607c
8 changed files with 71 additions and 39 deletions

View file

@ -599,9 +599,7 @@
append: "Integration Distillation",
unappend: "Derivation Distillation",
concat: "Combination Distillation",
index: "Selection Distillation",
list_size: "Abacus Purification",
singleton: "Single's Purification",
empty_list: "Vacant Reflection",
reverse: "Retrograde Purification",
@ -1604,7 +1602,7 @@
numlist: "Set operations are odd, in that some of them can accept two numbers or two lists, but not a combination thereof. Such arguments will be written as \"(num, num)|(list, list)\".$(br2)When numbers are used in those operations, they are being used as so-called binary \"bitsets\", lists of 1 and 0, true and false, \"on\" and \"off\".",
"or.1": "Unifies two sets.",
"or.2": "As such:$(li)With two numbers at the top of the stack, combines them into a bitset containing every \"on\" bit in either bitset.$(li)With two lists, this creates a list of every element from the first list, plus every element from the second list that is not in the first list. This is similar to $(l:patterns/lists#hexcasting:concat)$(action)Combination Distillation/$.",
"or.2": "As such:$(li)With two numbers at the top of the stack, combines them into a bitset containing every \"on\" bit in either bitset.$(li)With two lists, this creates a list of every element from the first list, plus every element from the second list that is not in the first list. This is similar to $(l:patterns/lists#hexcasting:add)$(action)Combination Distillation/$.",
"and.1": "Takes the intersection of two sets.",
"and.2": "As such:$(li)With two numbers at the top of the stack, combines them into a bitset containing every \"on\" bit present in $(italics)both/$ bitsets.$(li)With two lists, this creates a list of every element from the first list that is also in the second list.",
@ -1709,10 +1707,10 @@
slice: "Remove the two numbers at the top of the stack, then take a sublist of the list at the top of the stack between those indices, lower bound inclusive, upper bound exclusive. For example, the 0, 2 sublist of [0, 1, 2, 3, 4] would be [0, 1].",
append: "Remove the top of the stack, then add it to the end of the list at the top of the stack.",
unappend: "Remove the iota on the end of the list at the top of the stack, and add it to the top of the stack.",
concat: "Remove the list at the top of the stack, then add all its elements to the end of the list at the top of the stack.",
add: "Remove the list at the top of the stack, then add all its elements to the end of the list at the top of the stack.",
empty_list: "Push an empty list to the top of the stack.",
singleton: "Remove the top of the stack, then push a list containing only that element.",
list_size: "Remove the list at the top of the stack, then push the number of elements in the list to the stack.",
abs: "Remove the list at the top of the stack, then push the number of elements in the list to the stack.",
reverse: "Reverse the list at the top of the stack.",
index_of: "Remove the iota at the top of the stack, then replace the list at the top with the first index of that iota within the list (starting from 0). Replaces the list with -1 if the iota doesn't exist in the list.",
remove_from: "Remove the number at the top of the stack, then remove the nth element of the list at the top of the stack (where n is the number you removed).",

View file

@ -9,6 +9,7 @@
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:sentinel/create/great",
"anchor": "hexcasting:sentinel/create/great",
"text": "hexcasting.page.greater_sentinel.1",
"input": "vector",
"output": ""

View file

@ -40,12 +40,12 @@
},
{
"type": "hexcasting:pattern",
"header": "hexcasting.action.hexcasting:concat",
"header": "hexcasting.action.hexcasting:add",
"op_id": "hexcasting:add",
"anchor": "hexcasting:concat",
"anchor": "hexcasting:add",
"input": "list, list",
"output": "list",
"text": "hexcasting.page.lists.concat"
"text": "hexcasting.page.lists.add"
},
{
"type": "hexcasting:pattern",
@ -65,12 +65,12 @@
},
{
"type": "hexcasting:pattern",
"header": "hexcasting.action.hexcasting:list_size",
"header": "hexcasting.action.hexcasting:abs",
"op_id": "hexcasting:abs",
"anchor": "hexcasting:list_size",
"anchor": "hexcasting:abs",
"input": "list",
"output": "num",
"text": "hexcasting.page.lists.list_size"
"text": "hexcasting.page.lists.abs"
},
{
"type": "hexcasting:pattern",

View file

@ -12,7 +12,6 @@ from hexdoc.utils.deserialize import cast_or_raise
from ..pattern import RawPatternInfo
# TODO: make anchor required (breaks because of Greater Sentinel)
class PageWithPattern(PageWithText, type=None):
header: LocalizedStr
patterns: list[RawPatternInfo]
@ -44,6 +43,7 @@ class PageWithPattern(PageWithText, type=None):
class PageWithOpPattern(PageWithPattern, type=None):
op_id: ResourceLocation
anchor: str
@model_validator(mode="before")
def _pre_root_header(cls, values: Any, info: ValidationInfo):

View file

@ -1,4 +1,4 @@
from typing import Any
from typing import Any, Self
from pydantic import ValidationInfo, model_validator
@ -32,6 +32,12 @@ class LookupPatternPage(PageWithOpPattern, type="hexcasting:pattern"):
case _:
return values
@model_validator(mode="after")
def _check_anchor(self) -> Self:
if str(self.op_id) != self.anchor:
raise ValueError(f"op_id={self.op_id} does not equal anchor={self.anchor}")
return self
class ManualOpPatternPage(
PageWithOpPattern,

View file

@ -32,7 +32,7 @@ class Args:
properties_file: Path
output_file: Path | None
verbose: bool
verbose: int
ci: bool
@classmethod
@ -41,7 +41,7 @@ class Args:
parser.add_argument("properties_file", type=Path)
parser.add_argument("--output_file", "-o", type=Path)
parser.add_argument("--verbose", "-v", action="store_true")
parser.add_argument("--verbose", "-v", action="count", default=0)
parser.add_argument("--ci", action="store_true")
return cls(**vars(parser.parse_args(args)))
@ -55,6 +55,16 @@ class Args:
if self.ci and os.getenv("RUNNER_DEBUG") == "1":
self.verbose = True
@property
def log_level(self) -> int:
match self.verbose:
case 0:
return logging.WARNING
case 1:
return logging.INFO
case _:
return logging.DEBUG
def main(args: Args | None = None) -> None:
# allow passing Args for test cases, but parse by default
@ -72,11 +82,8 @@ def main(args: Args | None = None) -> None:
logging.basicConfig(
style="{",
format="\033[1m[{relativeCreated:.02f} | {levelname} | {name}]\033[0m {message}",
level=args.log_level,
)
logger = logging.getLogger(__name__)
if args.verbose:
logging.getLogger().setLevel(logging.DEBUG)
logger.debug("Log level set to DEBUG")
# load the book
props = Properties.load(args.properties_file)

View file

@ -202,7 +202,9 @@ class ModResourceLoader:
if not path.is_file():
raise FileNotFoundError(path)
logging.getLogger(__name__).debug(f"Loading {path}")
logger = logging.getLogger(__name__)
logger.info(f"Loading {path}")
data = path.read_text("utf-8")
value = decode(data)
@ -210,7 +212,7 @@ class ModResourceLoader:
out_path = self.props.export_dir / path.relative_to(resource_dir.path)
out_path.parent.mkdir(parents=True, exist_ok=True)
logging.getLogger(__name__).debug(f"Exporting {path} to {out_path}")
logger.debug(f"Exporting {path} to {out_path}")
match export:
case None:
out_data = data

View file

@ -3762,9 +3762,9 @@
<p>Remove the iota on the end of the list at the top of the stack, and add it to the top of the stack.</p>
</div>
<br />
<div id="patterns/lists@hexcasting:concat">
<div id="patterns/lists@hexcasting:add">
<h4 class="pattern-title">Additive Distillation (list, list → list)<a
href="#patterns/lists@hexcasting:concat"
href="#patterns/lists@hexcasting:add"
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h4>
@ -3822,9 +3822,9 @@
<p>Remove the top of the stack, then push a list containing only that element.</p>
</div>
<br />
<div id="patterns/lists@hexcasting:list_size">
<div id="patterns/lists@hexcasting:abs">
<h4 class="pattern-title">Length Purification (list → num)<a
href="#patterns/lists@hexcasting:list_size"
href="#patterns/lists@hexcasting:abs"
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h4>
@ -4530,7 +4530,7 @@
<p>Unifies two sets.</p>
</div>
<br />
<p>As such:</p><p class='fake-li'>With two numbers at the top of the stack, combines them into a bitset containing every &#34;on&#34; bit in either bitset.</p><p class='fake-li'>With two lists, this creates a list of every element from the first list, plus every element from the second list that is not in the first list. This is similar to <a href='#patterns/lists@hexcasting:concat'><span style='color: #fc77be'>Combination Distillation</span></a>.</p>
<p>As such:</p><p class='fake-li'>With two numbers at the top of the stack, combines them into a bitset containing every &#34;on&#34; bit in either bitset.</p><p class='fake-li'>With two lists, this creates a list of every element from the first list, plus every element from the second list that is not in the first list. This is similar to <a href='#patterns/lists@hexcasting:add'><span style='color: #fc77be'>Combination Distillation</span></a>.</p>
<br />
<div id="patterns/sets@hexcasting:and">
<h4 class="pattern-title">Conjunction Distillation ((num, num)|(list, list) → num|list)<a
@ -5943,7 +5943,12 @@
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h3>
<h4 class="pattern-title">Summon Greater Sentinel (vector →)</h4>
<div id="patterns/great_spells/greater_sentinel@hexcasting:sentinel/create/great">
<h4 class="pattern-title">Summon Greater Sentinel (vector →)<a
href="#patterns/great_spells/greater_sentinel@hexcasting:sentinel/create/great"
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h4>
<details class="spell-collapsible">
<summary class="collapse-spell"></summary>
<canvas
@ -5956,6 +5961,7 @@
>Your browser does not support visualizing patterns. Pattern code: waeawaeqqqwqwqqwq</canvas>
</details>
<p>Summon a greater version of my <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>Sentinel</span></a>. Costs about two <a href='#items/amethyst'><span style='color: #b0b'>Amethyst Dust</span></a>.</p>
</div>
<br />
<p>The stronger <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>sentinel</span></a> acts like the normal one I can summon without the use of a Great Spell, if a little more visually interesting. However, the range in which my spells can work is extended to a small region around my greater <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>sentinel</span></a>, about 16 blocks. In other words, no matter where in the world I am, I can interact with things around my <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>sentinel</span></a> (the mysterious forces of chunkloading notwithstanding).</p>
<br />
@ -9794,9 +9800,9 @@
<p>Remove the iota on the end of the list at the top of the stack, and add it to the top of the stack.</p>
</div>
<br />
<div id="patterns/lists@hexcasting:concat">
<div id="patterns/lists@hexcasting:add">
<h4 class="pattern-title">Additive Distillation (list, list → list)<a
href="#patterns/lists@hexcasting:concat"
href="#patterns/lists@hexcasting:add"
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h4>
@ -9854,9 +9860,9 @@
<p>Remove the top of the stack, then push a list containing only that element.</p>
</div>
<br />
<div id="patterns/lists@hexcasting:list_size">
<div id="patterns/lists@hexcasting:abs">
<h4 class="pattern-title">Length Purification (list → num)<a
href="#patterns/lists@hexcasting:list_size"
href="#patterns/lists@hexcasting:abs"
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h4>
@ -10562,7 +10568,7 @@
<p>Unifies two sets.</p>
</div>
<br />
<p>As such:</p><p class='fake-li'>With two numbers at the top of the stack, combines them into a bitset containing every &#34;on&#34; bit in either bitset.</p><p class='fake-li'>With two lists, this creates a list of every element from the first list, plus every element from the second list that is not in the first list. This is similar to <a href='#patterns/lists@hexcasting:concat'><span style='color: #fc77be'>Combination Distillation</span></a>.</p>
<p>As such:</p><p class='fake-li'>With two numbers at the top of the stack, combines them into a bitset containing every &#34;on&#34; bit in either bitset.</p><p class='fake-li'>With two lists, this creates a list of every element from the first list, plus every element from the second list that is not in the first list. This is similar to <a href='#patterns/lists@hexcasting:add'><span style='color: #fc77be'>Combination Distillation</span></a>.</p>
<br />
<div id="patterns/sets@hexcasting:and">
<h4 class="pattern-title">Conjunction Distillation ((num, num)|(list, list) → num|list)<a
@ -11975,7 +11981,12 @@
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h3>
<h4 class="pattern-title">Summon Greater Sentinel (vector →)</h4>
<div id="patterns/great_spells/greater_sentinel@hexcasting:sentinel/create/great">
<h4 class="pattern-title">Summon Greater Sentinel (vector →)<a
href="#patterns/great_spells/greater_sentinel@hexcasting:sentinel/create/great"
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h4>
<details class="spell-collapsible">
<summary class="collapse-spell"></summary>
<canvas
@ -11988,6 +11999,7 @@
>Your browser does not support visualizing patterns. Pattern code: waeawaeqqqwqwqqwq</canvas>
</details>
<p>Summon a greater version of my <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>Sentinel</span></a>. Costs about two <a href='#items/amethyst'><span style='color: #b0b'>Amethyst Dust</span></a>.</p>
</div>
<br />
<p>The stronger <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>sentinel</span></a> acts like the normal one I can summon without the use of a Great Spell, if a little more visually interesting. However, the range in which my spells can work is extended to a small region around my greater <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>sentinel</span></a>, about 16 blocks. In other words, no matter where in the world I am, I can interact with things around my <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>sentinel</span></a> (the mysterious forces of chunkloading notwithstanding).</p>
<br />
@ -15828,9 +15840,9 @@
<p>Remove the iota on the end of the list at the top of the stack, and add it to the top of the stack.</p>
</div>
<br />
<div id="patterns/lists@hexcasting:concat">
<div id="patterns/lists@hexcasting:add">
<h4 class="pattern-title">Additive Distillation (list, list → list)<a
href="#patterns/lists@hexcasting:concat"
href="#patterns/lists@hexcasting:add"
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h4>
@ -15888,9 +15900,9 @@
<p>Remove the top of the stack, then push a list containing only that element.</p>
</div>
<br />
<div id="patterns/lists@hexcasting:list_size">
<div id="patterns/lists@hexcasting:abs">
<h4 class="pattern-title">Length Purification (list → num)<a
href="#patterns/lists@hexcasting:list_size"
href="#patterns/lists@hexcasting:abs"
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h4>
@ -16596,7 +16608,7 @@
<p>Unifies two sets.</p>
</div>
<br />
<p>As such:</p><p class='fake-li'>With two numbers at the top of the stack, combines them into a bitset containing every &#34;on&#34; bit in either bitset.</p><p class='fake-li'>With two lists, this creates a list of every element from the first list, plus every element from the second list that is not in the first list. This is similar to <a href='#patterns/lists@hexcasting:concat'><span style='color: #fc77be'>Combination Distillation</span></a>.</p>
<p>As such:</p><p class='fake-li'>With two numbers at the top of the stack, combines them into a bitset containing every &#34;on&#34; bit in either bitset.</p><p class='fake-li'>With two lists, this creates a list of every element from the first list, plus every element from the second list that is not in the first list. This is similar to <a href='#patterns/lists@hexcasting:add'><span style='color: #fc77be'>Combination Distillation</span></a>.</p>
<br />
<div id="patterns/sets@hexcasting:and">
<h4 class="pattern-title">Conjunction Distillation ((num, num)|(list, list) → num|list)<a
@ -18009,7 +18021,12 @@
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h3>
<h4 class="pattern-title">Summon Greater Sentinel (vector →)</h4>
<div id="patterns/great_spells/greater_sentinel@hexcasting:sentinel/create/great">
<h4 class="pattern-title">Summon Greater Sentinel (vector →)<a
href="#patterns/great_spells/greater_sentinel@hexcasting:sentinel/create/great"
class="permalink small"
title="Permalink"
><i class="bi bi-link-45deg"></i></a></h4>
<details class="spell-collapsible">
<summary class="collapse-spell"></summary>
<canvas
@ -18022,6 +18039,7 @@
>Your browser does not support visualizing patterns. Pattern code: waeawaeqqqwqwqqwq</canvas>
</details>
<p>Summon a greater version of my <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>Sentinel</span></a>. Costs about two <a href='#items/amethyst'><span style='color: #b0b'>Amethyst Dust</span></a>.</p>
</div>
<br />
<p>The stronger <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>sentinel</span></a> acts like the normal one I can summon without the use of a Great Spell, if a little more visually interesting. However, the range in which my spells can work is extended to a small region around my greater <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>sentinel</span></a>, about 16 blocks. In other words, no matter where in the world I am, I can interact with things around my <a href='#patterns/spells/sentinels'><span style='color: #8d6acc'>sentinel</span></a> (the mysterious forces of chunkloading notwithstanding).</p>
<br />