From d7541afe21356a3ab0f8d292678896ef7762552a Mon Sep 17 00:00:00 2001 From: Sergio Aguirre Date: Sat, 31 Oct 2026 20:17:40 +0100 Subject: [PATCH] [FIX] create a SignalObj from any calling function SignalObj looks for the name it is assigned to by walking the call stack and comparing the first local variable of each frame with the new object. The comparison used `in`, that is equality, so a caller whose first local variable was a NumPy array raised "The truth value of an array is ambiguous", and a caller whose first local variable was not yet assigned raised KeyError. The comparison is now by identity, and an unset variable counts as a different object. Co-Authored-By: Claude Fable 5.1 --- pytta/classes/_instanceinfo.py | 3 ++- tests/test_signalobj_creation.py | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/test_signalobj_creation.py diff --git a/pytta/classes/_instanceinfo.py b/pytta/classes/_instanceinfo.py index ab2a11c..5e4aad2 100644 --- a/pytta/classes/_instanceinfo.py +++ b/pytta/classes/_instanceinfo.py @@ -28,7 +28,8 @@ def __init__(self): varnames = frame.f_code.co_varnames if varnames == (): break - if frame.f_locals[varnames[0]] not in (self, self.__class__): + first = frame.f_locals.get(varnames[0]) + if first is not self and first is not self.__class__: break # if the frame is inside a method of this instance, # the first argument usually contains either the instance or diff --git a/tests/test_signalobj_creation.py b/tests/test_signalobj_creation.py new file mode 100644 index 0000000..e07cee7 --- /dev/null +++ b/tests/test_signalobj_creation.py @@ -0,0 +1,40 @@ +""" +Tests for the creation of a SignalObj from inside a function. + +SignalObj reads the name of the variable it is assigned to from the call +stack (classes/_instanceinfo.py). The lookup must not depend on what the +calling function holds in its first local variable. Each test pins one +case that used to raise. +""" +import os +import unittest + +os.environ.setdefault('MPLBACKEND', 'Agg') + +import numpy as np + +import pytta + + +def from_array(data): + # first local variable: a NumPy array + return pytta.SignalObj(data, 'time', 48000) + + +def before_first_local_is_set(): + # first local variable not assigned yet when SignalObj is created + sig = pytta.SignalObj(np.ones(8), 'time', 48000) + return sig + + +class TestSignalObjCreation(unittest.TestCase): + + def test_caller_holding_an_array(self): + self.assertEqual(from_array(np.ones(8)).numSamples, 8) + + def test_caller_whose_first_local_is_not_set(self): + self.assertEqual(before_first_local_is_set().numSamples, 8) + + +if __name__ == '__main__': + unittest.main()