70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
import ast
|
|
from pathlib import Path
|
|
|
|
|
|
NODE_SOURCE = Path(__file__).resolve().parents[1] / "nodes.py"
|
|
TIMED_CLASSES = {
|
|
"BIMVFIInterpolate",
|
|
"BIMVFISegmentInterpolate",
|
|
"EMAVFIInterpolate",
|
|
"EMAVFISegmentInterpolate",
|
|
"SGMVFIInterpolate",
|
|
"SGMVFISegmentInterpolate",
|
|
"LDFVFIInterpolate",
|
|
"SPEEDVFIInterpolate",
|
|
"SPEEDVFISegmentInterpolate",
|
|
"GIMMVFIInterpolate",
|
|
"GIMMVFISegmentInterpolate",
|
|
}
|
|
DIRECTLY_DECORATED = TIMED_CLASSES - {
|
|
"SPEEDVFIInterpolate",
|
|
"SPEEDVFISegmentInterpolate",
|
|
}
|
|
|
|
|
|
def _class_definitions():
|
|
tree = ast.parse(NODE_SOURCE.read_text(encoding="utf-8"))
|
|
return {
|
|
node.name: node
|
|
for node in tree.body
|
|
if isinstance(node, ast.ClassDef) and node.name in TIMED_CLASSES
|
|
}
|
|
|
|
|
|
def _literal_assignment(class_node, name):
|
|
for statement in class_node.body:
|
|
if (
|
|
isinstance(statement, ast.Assign)
|
|
and len(statement.targets) == 1
|
|
and isinstance(statement.targets[0], ast.Name)
|
|
and statement.targets[0].id == name
|
|
):
|
|
return ast.literal_eval(statement.value)
|
|
raise AssertionError(f"{class_node.name} does not define {name}")
|
|
|
|
|
|
def test_all_interpolation_nodes_expose_elapsed_seconds_last():
|
|
classes = _class_definitions()
|
|
assert classes.keys() == TIMED_CLASSES
|
|
|
|
for class_node in classes.values():
|
|
assert _literal_assignment(class_node, "RETURN_TYPES")[-1] == "FLOAT"
|
|
assert _literal_assignment(class_node, "RETURN_NAMES")[-1] == "elapsed_seconds"
|
|
|
|
|
|
def test_direct_interpolation_methods_append_timing_output():
|
|
classes = _class_definitions()
|
|
for class_name in DIRECTLY_DECORATED:
|
|
interpolate = next(
|
|
statement
|
|
for statement in classes[class_name].body
|
|
if isinstance(statement, ast.FunctionDef)
|
|
and statement.name == "interpolate"
|
|
)
|
|
assert any(
|
|
isinstance(decorator, ast.Call)
|
|
and isinstance(decorator.func, ast.Name)
|
|
and decorator.func.id == "_with_elapsed_seconds"
|
|
for decorator in interpolate.decorator_list
|
|
)
|