mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-06-13 12:42:03 +00:00
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:
0
tests/core/__init__.py
Normal file
0
tests/core/__init__.py
Normal file
29
tests/core/test_fps.py
Normal file
29
tests/core/test_fps.py
Normal 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")
|
||||||
@@ -726,8 +726,10 @@ class FPS(ast.NodeVisitor):
|
|||||||
return self.visit(node.left) / self.visit(node.right)
|
return self.visit(node.left) / self.visit(node.right)
|
||||||
raise ValueError(f"Invalid operation: {node.op}")
|
raise ValueError(f"Invalid operation: {node.op}")
|
||||||
|
|
||||||
def visit_Num(self, node: ast.Num) -> complex:
|
def visit_Constant(self, node: ast.Constant) -> float:
|
||||||
return node.n
|
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:
|
def visit_Expr(self, node: ast.Expr) -> float:
|
||||||
return self.visit(node.value)
|
return self.visit(node.value)
|
||||||
|
|||||||
Reference in New Issue
Block a user