Skip to content

Commit 2093cf1

Browse files
committed
chore: Misc; Optimization TODO
1 parent 80f09d6 commit 2093cf1

6 files changed

Lines changed: 72 additions & 43 deletions

File tree

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v2.3.0
3+
rev: v4.6.0
44
hooks:
55
- id: check-yaml
66
- id: end-of-file-fixer
@@ -9,7 +9,7 @@ repos:
99
exclude: docs/auto_examples
1010
- repo: https://github.com/charliermarsh/ruff-pre-commit
1111
# Ruff version.
12-
rev: v0.3.7
12+
rev: v0.8.1
1313
hooks:
1414
# Run the linter.
1515
- id: ruff

docs/guards.md

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ The mini-language is based on Python's built-in language and the [`ast`](https:/
7777
4. `!=` — Not equal.
7878
5. `<` — Lower than.
7979
6. `<=` — Lower than or equal.
80-
- See the [comparisons](https://docs.python.org/3/reference/expressions.html#comparisons) from Python's.
80+
- All comparison operations in Python have the same priority.
8181

8282
3. **Parentheses for precedence**:
8383
- When operators with the same precedence appear in the expression, evaluation proceeds from left to right, unless parentheses specify a different order.
@@ -100,19 +100,6 @@ Being used on a transition definition:
100100
start.to(end, cond="frodo_has_ring and gandalf_present or !sauron_alive")
101101
```
102102

103-
#### Summary of grammar rules
104-
105-
The mini-language is formally specified as follows:
106-
107-
```
108-
Name: [A-Za-z_][A-Za-z0-9_]*
109-
Boolean Expression:
110-
111-
<boolean_expr> ::= <term> | <boolean_expr> 'or' <term> | <boolean_expr> 'v' <term>
112-
<term> ::= <factor> | <term> 'and' <factor> | <term> '^' <factor>
113-
<factor> ::= 'not' <factor> | '!' <factor> | '(' <boolean_expr> ')' | <name>
114-
115-
```
116103

117104
```{seealso}
118105
See {ref}`sphx_glr_auto_examples_lor_machine.py` for an example of

pyproject.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ diagrams = ["pydot >= 2.0.0"]
3333

3434
[dependency-groups]
3535
dev = [
36-
"ruff >=0.4.8",
36+
"ruff >=0.8.1",
3737
"pre-commit",
3838
"mypy",
3939
"pytest",
@@ -82,6 +82,7 @@ doctest_optionflags = "ELLIPSIS IGNORE_EXCEPTION_DETAIL NORMALIZE_WHITESPACE IGN
8282
asyncio_mode = "auto"
8383
markers = ["""slow: marks tests as slow (deselect with '-m "not slow"')"""]
8484
python_files = ["tests.py", "test_*.py", "*_tests.py"]
85+
xfail_strict = true
8586

8687
[tool.coverage.run]
8788
branch = true
@@ -112,7 +113,7 @@ directory = "tmp/htmlcov"
112113
show_contexts = true
113114

114115
[tool.mypy]
115-
python_version = "3.12"
116+
python_version = "3.13"
116117
warn_return_any = true
117118
warn_unused_configs = true
118119
disable_error_code = "annotation-unchecked"
@@ -126,7 +127,7 @@ ignore_missing_imports = true
126127
src = ["statemachine"]
127128

128129
line-length = 99
129-
target-version = "py312"
130+
target-version = "py313"
130131

131132
# Exclude a variety of commonly ignored directories.
132133
exclude = [
@@ -178,7 +179,7 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
178179
"tests/examples/**.py" = ["B018"]
179180

180181
[tool.ruff.lint.mccabe]
181-
max-complexity = 6
182+
max-complexity = 10
182183

183184
[tool.ruff.lint.isort]
184185
force-single-line = true

statemachine/state.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def __call__(self, *states: "State", **kwargs):
3636

3737
class _FromState(_TransitionBuilder):
3838
def any(self, **kwargs):
39-
"""Create transitions from all non-finalstates (reversed)."""
39+
"""Create transitions from all non-final states (reversed)."""
4040
return self.__call__(AnyState(), **kwargs)
4141

4242
def __call__(self, *states: "State", **kwargs):

tests/test_spec_parser.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,44 @@ def variable_hook(var_name):
218218
parsed_expr = parse_boolean_expr(expr, variable_hook, operator_mapping)
219219

220220
assert parsed_expr is original_callback
221+
222+
223+
@pytest.mark.parametrize(
224+
("expression", "expected", "hooks_called"),
225+
[
226+
("49 < frodo_age < 51", True, ["frodo_age"]),
227+
("49 < frodo_age > 50", False, ["frodo_age"]),
228+
(
229+
"aragorn_age < legolas_age < gimli_age",
230+
False,
231+
["aragorn_age", "legolas_age", "gimli_age"],
232+
), # 87 < 2931 and 2931 < 139
233+
(
234+
"gimli_age > aragorn_age < legolas_age",
235+
True,
236+
["gimli_age", "aragorn_age", "legolas_age"],
237+
), # 139 > 87 and 87 < 2931
238+
(
239+
"sword_power < ring_power > bow_power",
240+
True,
241+
["sword_power", "ring_power", "bow_power"],
242+
), # 80 < 100 and 100 > 75
243+
(
244+
"axe_power > sword_power == bow_power",
245+
False,
246+
["axe_power", "sword_power", "bow_power"],
247+
), # 85 > 80 and 80 == 75
248+
("height > 1 and height < 2", True, ["height"]),
249+
],
250+
)
251+
@pytest.mark.xfail(reason="TODO: Optimize so that expressios are evaluated only once")
252+
def test_should_evaluate_values_only_once(expression, expected, caplog, hooks_called):
253+
caplog.set_level(logging.DEBUG, logger="tests")
254+
255+
parsed_expr = parse_boolean_expr(expression, variable_hook, operator_mapping)
256+
assert parsed_expr() is expected, expression
257+
258+
if hooks_called:
259+
assert caplog.record_tuples == [
260+
("tests.test_spec_parser", DEBUG, f"variable_hook({hook})") for hook in hooks_called
261+
]

uv.lock

Lines changed: 22 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)