Skip to content

Commit 3d3dd67

Browse files
authored
Merge pull request #127 from ManualForArchipelago/req-function-tweaks
Better req function exception messages
2 parents f202923 + 27f6c72 commit 3d3dd67

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

src/Rules.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from typing import TYPE_CHECKING, Optional
22
from enum import IntEnum
3-
from worlds.generic.Rules import set_rule, add_rule
3+
44
from .Regions import regionMap
55
from .hooks import Rules
6+
from .Helpers import clamp, is_item_enabled, get_items_with_value, is_option_enabled, get_option_value, convert_string_to_type, format_to_valid_identifier
67

78
from BaseClasses import MultiWorld, CollectionState
8-
from .Helpers import clamp, is_item_enabled, get_items_with_value, is_option_enabled, get_option_value, convert_string_to_type
99
from worlds.AutoWorld import World
10+
from worlds.generic.Rules import set_rule, add_rule
1011

1112
import re
1213
import math
@@ -35,7 +36,7 @@ def construct_logic_error(location_or_region: dict, source: LogicErrorSource) ->
3536
elif source == LogicErrorSource.EVALUATE_POSTFIX:
3637
source_text = "There may be missing || around item names, or an AND/OR that is missing a value on one side, or other invalid syntax for the requires."
3738
elif source == LogicErrorSource.EVALUATE_STACK_SIZE:
38-
source_text = "There may be missing {} around requirement functions like YamlEnabled() / YamlDisabled(), or other invalid syntax for the requires."
39+
source_text = "There may be missing {} around requirement functions like YamlEnabled() / YamlDisabled(), or other invalid syntax for the requires."
3940
else:
4041
source_text = "This requires includes invalid syntax."
4142

@@ -105,14 +106,18 @@ def checkRequireStringForArea(state: CollectionState, area: dict):
105106
# Get the "real" item counts of item in the pool/placed/starting_items
106107
items_counts = world.get_item_counts(player)
107108

109+
# Preparing some variables for exception messages
110+
area_type = "region" if area.get("is_region",False) else "location"
111+
area_name = area.get("name", f"unknown with these parameters: {area}")
112+
108113
if requires_list == "":
109114
return True
110115

111116
def findAndRecursivelyExecuteFunctions(requires_list: str, recursionDepth: int = 0) -> str:
112117
found_functions = re.findall(r'\{(\w+)\((.*?)\)\}', requires_list)
113118
if found_functions:
114-
if recursionDepth >= world.rules_functions_maximum_recursion:
115-
raise RecursionError(f'One or more functions in "{area.get("name", f"An area with these parameters: {area}")}"\'s requires looped too many time (maximum recursion is {world.rules_functions_maximum_recursion}) \
119+
if recursionDepth > world.rules_functions_maximum_recursion:
120+
raise RecursionError(f'One or more functions in {area_type} "{area_name}"\'s requires looped too many time (maximum recursion is {world.rules_functions_maximum_recursion}) \
116121
\n As of this Exception the following function(s) are waiting to run: {[f[0] for f in found_functions]} \
117122
\n And the currently processed requires look like this: "{requires_list}"')
118123
else:
@@ -128,10 +133,16 @@ def findAndRecursivelyExecuteFunctions(requires_list: str, recursionDepth: int =
128133
func = getattr(Rules, func_name, None)
129134

130135
if not callable(func):
131-
raise ValueError(f"Invalid function `{func_name}` in {area}.")
132-
133-
convert_req_function_args(func, func_args, area.get("name", f"An area with these parameters: {area}"))
134-
result = func(world, multiworld, state, player, *func_args)
136+
raise ValueError(f'Invalid function "{func_name}" in {area_type} "{area_name}".')
137+
138+
convert_req_function_args(func, func_args, area_name)
139+
try:
140+
result = func(world, multiworld, state, player, *func_args)
141+
except Exception as ex:
142+
raise RuntimeError(f'A call to the function "{func_name}" in {area_type} "{area_name}"\'s requires raised an Exception. \
143+
\nUnless it was called by another function, it should look something like "{{{func_name}({item[1]})}}" in {area_type}s.json. \
144+
\nFull error message: \
145+
\n\n{type(ex).__name__}: {ex}')
135146
if isinstance(result, bool):
136147
requires_list = requires_list.replace("{" + func_name + "(" + item[1] + ")}", "1" if result else "0")
137148
else:

0 commit comments

Comments
 (0)