fix(core): replace deprecated ast.Num visitor in FPS parser

ast.Num/node.n deprecated since Python 3.8; NodeVisitor falls back to visit_Num with a DeprecationWarning per dispatch. Under -W error this surfaced as a misleading fps ValueError in Video.init. Replace with visit_Constant, reject non-numeric constants, and pin parse results for int/fraction/float inputs in a regression test.
This commit is contained in:
imSp4rky
2026-06-05 15:21:39 -06:00
parent 23cc8c9ec9
commit c03ff01c32
3 changed files with 33 additions and 2 deletions

0
tests/core/__init__.py Normal file
View File

29
tests/core/test_fps.py Normal file
View File

@@ -0,0 +1,29 @@
import warnings
import pytest
from unshackle.core.utilities import FPS
@pytest.mark.parametrize(
("expr", "expected"),
[
("24", 24),
("23.976", pytest.approx(23.976)),
("30000/1001", pytest.approx(29.97, abs=0.001)),
],
)
def test_parse_pins_results_without_deprecation_warnings(expr: str, expected: object) -> None:
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
assert FPS.parse(expr) == expected
def test_parse_rejects_non_numeric_constant() -> None:
with pytest.raises(ValueError, match="Invalid fps value"):
FPS.parse("'24'")
def test_parse_rejects_non_division_operation() -> None:
with pytest.raises(ValueError, match="Invalid operation"):
FPS.parse("24+1")

View File

@@ -726,8 +726,10 @@ class FPS(ast.NodeVisitor):
return self.visit(node.left) / self.visit(node.right)
raise ValueError(f"Invalid operation: {node.op}")
def visit_Num(self, node: ast.Num) -> complex:
return node.n
def visit_Constant(self, node: ast.Constant) -> float:
if not isinstance(node.value, (int, float)):
raise ValueError(f"Invalid fps value: {node.value!r}")
return node.value
def visit_Expr(self, node: ast.Expr) -> float:
return self.visit(node.value)