Skip to content

Commit 13d3f7b

Browse files
alwaysintrebleNewSoupVi
authored andcommitted
Core: add unit tests and more documentation for numeric options (ArchipelagoMW#2926)
* Core: add unit tests for the numeric options * document using a collection and the hashing quirk * add another example for the footgun --------- Co-authored-by: NewSoupVi <[email protected]>
1 parent 1bed996 commit 13d3f7b

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

docs/options api.md

+18-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ or if I need a boolean object, such as in my slot_data I can access it as:
132132
start_with_sword = bool(self.options.starting_sword.value)
133133
```
134134
All numeric options (i.e. Toggle, Choice, Range) can be compared to integers, strings that match their attributes,
135-
strings that match the option attributes after "option_" is stripped, and the attributes themselves.
135+
strings that match the option attributes after "option_" is stripped, and the attributes themselves. The option can
136+
also be checked to see if it exists within a collection, but this will fail for a set of strings due to hashing.
136137
```python
137138
# options.py
138139
class Logic(Choice):
@@ -144,6 +145,12 @@ class Logic(Choice):
144145
alias_extra_hard = 2
145146
crazy = 4 # won't be listed as an option and only exists as an attribute on the class
146147

148+
class Weapon(Choice):
149+
option_none = 0
150+
option_sword = 1
151+
option_bow = 2
152+
option_hammer = 3
153+
147154
# __init__.py
148155
from .options import Logic
149156

@@ -157,6 +164,16 @@ elif self.options.logic == Logic.option_extreme:
157164
do_extreme_things()
158165
elif self.options.logic == "crazy":
159166
do_insane_things()
167+
168+
# check if the current option is in a collection of integers using the class attributes
169+
if self.options.weapon in {Weapon.option_bow, Weapon.option_sword}:
170+
do_stuff()
171+
# in order to make a set of strings work, we have to compare against current_key
172+
elif self.options.weapon.current_key in {"none", "hammer"}:
173+
do_something_else()
174+
# though it's usually better to just use a tuple instead
175+
elif self.options.weapon in ("none", "hammer"):
176+
do_something_else()
160177
```
161178
## Generic Option Classes
162179
These options are generically available to every game automatically, but can be overridden for slightly different

test/options/__init__.py

Whitespace-only changes.

test/options/test_option_classes.py

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import unittest
2+
3+
from Options import Choice, DefaultOnToggle, Toggle
4+
5+
6+
class TestNumericOptions(unittest.TestCase):
7+
def test_numeric_option(self) -> None:
8+
"""Tests the initialization and equivalency comparisons of the base Numeric Option class."""
9+
class TestChoice(Choice):
10+
option_zero = 0
11+
option_one = 1
12+
option_two = 2
13+
alias_three = 1
14+
non_option_attr = 2
15+
16+
class TestToggle(Toggle):
17+
pass
18+
19+
class TestDefaultOnToggle(DefaultOnToggle):
20+
pass
21+
22+
with self.subTest("choice"):
23+
choice_option_default = TestChoice.from_any(TestChoice.default)
24+
choice_option_string = TestChoice.from_any("one")
25+
choice_option_int = TestChoice.from_any(2)
26+
choice_option_alias = TestChoice.from_any("three")
27+
choice_option_attr = TestChoice.from_any(TestChoice.option_two)
28+
29+
self.assertEqual(choice_option_default, TestChoice.option_zero,
30+
"assigning default didn't match default value")
31+
self.assertEqual(choice_option_string, "one")
32+
self.assertEqual(choice_option_int, 2)
33+
self.assertEqual(choice_option_alias, TestChoice.alias_three)
34+
self.assertEqual(choice_option_attr, TestChoice.non_option_attr)
35+
36+
self.assertRaises(KeyError, TestChoice.from_any, "four")
37+
38+
self.assertIn(choice_option_int, [1, 2, 3])
39+
self.assertIn(choice_option_int, {2})
40+
self.assertIn(choice_option_int, (2,))
41+
42+
self.assertIn(choice_option_string, ["one", "two", "three"])
43+
# this fails since the hash is derived from the value
44+
self.assertNotIn(choice_option_string, {"one"})
45+
self.assertIn(choice_option_string, ("one",))
46+
47+
with self.subTest("toggle"):
48+
toggle_default = TestToggle.from_any(TestToggle.default)
49+
toggle_string = TestToggle.from_any("false")
50+
toggle_int = TestToggle.from_any(0)
51+
toggle_alias = TestToggle.from_any("off")
52+
53+
self.assertFalse(toggle_default)
54+
self.assertFalse(toggle_string)
55+
self.assertFalse(toggle_int)
56+
self.assertFalse(toggle_alias)
57+
58+
with self.subTest("on toggle"):
59+
toggle_default = TestDefaultOnToggle.from_any(TestDefaultOnToggle.default)
60+
toggle_string = TestDefaultOnToggle.from_any("true")
61+
toggle_int = TestDefaultOnToggle.from_any(1)
62+
toggle_alias = TestDefaultOnToggle.from_any("on")
63+
64+
self.assertTrue(toggle_default)
65+
self.assertTrue(toggle_string)
66+
self.assertTrue(toggle_int)
67+
self.assertTrue(toggle_alias)

0 commit comments

Comments
 (0)