Skip to content

Commit 2873a40

Browse files
committed
Fix AttributeError when creating custom signal
Fixes #269
1 parent 85b0e71 commit 2873a40

4 files changed

Lines changed: 118 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ See DataLab [roadmap page](https://datalab-platform.com/en/contributing/roadmap.
66

77
### 🛠️ Bug Fixes ###
88

9+
**Custom signal creation:**
10+
11+
* Fixed `AttributeError: 'NoneType' object has no attribute 'T'` error when creating a custom signal from the menu
12+
* This closes [Issue #269](https://github.com/datalab-platform/datalab/issues/269) - Custom Signal Creation: `AttributeError` when creating signal from menu
13+
914
**Macro execution:**
1015

1116
* Fixed `UnicodeEncodeError` when executing macros that print Unicode characters (e.g., arrows ``) on Windows systems with certain locales, e.g. cp1252 (closes [Issue #263](https://github.com/datalab-platform/datalab/issues/263))

datalab/gui/newobject.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,13 @@ def create_signal_gui(
122122
param = NewSignalParam()
123123
edit = True # Default to editing if no parameters provided
124124

125+
# CustomSignalParam requires edit mode to initialize the xyarray.
126+
# Without this, if edit=False (the default in new_object), the setup_array
127+
# call would be skipped, leaving xyarray as None, which would cause an
128+
# AttributeError when trying to access param.xyarray.T later.
129+
if isinstance(param, OrigCustomSignalParam):
130+
edit = True
131+
125132
if isinstance(param, OrigCustomSignalParam) and edit:
126133
p_init = NewSignalParam(_("Custom signal"))
127134
p_init.size = 10 # Set smaller default size for initial input
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2+
3+
"""
4+
Test for Custom Signal creation bug fix
5+
========================================
6+
7+
This test verifies that creating a Custom signal doesn't crash with AttributeError
8+
when xyarray is None.
9+
10+
Bug report: "Créer un signal Custom déclenche immédiatement l'erreur
11+
AttributeError: 'NoneType' object has no attribute 'T'."
12+
"""
13+
14+
import pytest
15+
from guidata.qthelpers import qt_app_context
16+
17+
from datalab.gui.newobject import CustomSignalParam, create_signal_gui
18+
19+
20+
def test_custom_signal_param_initialization():
21+
"""Test that CustomSignalParam initializes properly"""
22+
with qt_app_context():
23+
param = CustomSignalParam()
24+
# Initially, xyarray should be None
25+
assert param.xyarray is None
26+
# But other defaults should exist
27+
assert param.size == 10
28+
assert param.xmin == 0.0
29+
assert param.xmax == 1.0
30+
31+
32+
def test_custom_signal_param_setup_array():
33+
"""Test that setup_array creates the xyarray properly"""
34+
with qt_app_context():
35+
param = CustomSignalParam()
36+
assert param.xyarray is None
37+
38+
# Call setup_array to initialize
39+
param.setup_array(size=10, xmin=0.0, xmax=1.0)
40+
41+
# Now xyarray should exist and be transposable
42+
assert param.xyarray is not None
43+
assert param.xyarray.shape == (10, 2)
44+
45+
# Should be able to transpose without error
46+
transposed = param.xyarray.T
47+
assert transposed.shape == (2, 10)
48+
49+
50+
def test_custom_signal_param_generate_1d_data():
51+
"""Test that generate_1d_data works even with None xyarray"""
52+
with qt_app_context():
53+
param = CustomSignalParam()
54+
assert param.xyarray is None
55+
56+
# generate_1d_data should call setup_array internally
57+
x, y = param.generate_1d_data()
58+
59+
# Should succeed without AttributeError
60+
assert x is not None
61+
assert y is not None
62+
assert len(x) == param.size
63+
assert len(y) == param.size
64+
65+
66+
def test_custom_signal_creation_forces_edit_mode():
67+
"""Test that creating a custom signal with edit=False forces edit=True
68+
69+
This test verifies the bug fix for:
70+
"Créer un signal Custom déclenche immédiatement l'erreur
71+
AttributeError: 'NoneType' object has no attribute 'T'."
72+
73+
The bug occurred when edit=False was passed (the default), which caused
74+
setup_array to not be called, leaving xyarray as None, which then crashed
75+
when trying to access xyarray.T.
76+
77+
The fix forces edit=True for CustomSignalParam to ensure the user is always
78+
prompted to set up the array properly.
79+
"""
80+
# This test can't actually test the dialog interaction, but we can verify
81+
# that the code doesn't crash immediately with AttributeError due to None xyarray
82+
# The test framework will handle the unattended mode appropriately
83+
with qt_app_context():
84+
# In unattended mode, the dialogs will be auto-canceled, so this should
85+
# return None rather than crashing
86+
param = CustomSignalParam()
87+
# In actual usage with GUI, this would show dialogs
88+
# In unattended test mode, dialogs are auto-canceled
89+
# The important thing is it doesn't crash with AttributeError
90+
_signal = create_signal_gui(param, edit=False, parent=None)
91+
# In unattended mode, this will be None because dialogs are canceled
92+
# But it shouldn't have crashed with AttributeError
93+
94+
95+
if __name__ == "__main__":
96+
pytest.main([__file__, "-v"])

doc/locale/fr/LC_MESSAGES/changelog.po

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ msgid ""
77
msgstr ""
88
"Project-Id-Version: DataLab \n"
99
"Report-Msgid-Bugs-To: \n"
10-
"POT-Creation-Date: 2025-11-30 11:51+0100\n"
10+
"POT-Creation-Date: 2025-11-30 12:22+0100\n"
1111
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1212
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313
"Language: fr\n"
@@ -30,6 +30,15 @@ msgstr "DataLab Version 1.0.2 (non publiée)"
3030
msgid "🛠️ Bug Fixes"
3131
msgstr "🛠️ Correctifs"
3232

33+
msgid "**Custom signal creation:**"
34+
msgstr "**Création de signaux personnalisés :**"
35+
36+
msgid "Fixed `AttributeError: 'NoneType' object has no attribute 'T'` error when creating a custom signal from the menu"
37+
msgstr "Correction de l'erreur `AttributeError: 'NoneType' object has no attribute 'T'` lors de la création d'un signal personnalisé à partir du menu"
38+
39+
msgid "This closes [Issue #269](https://github.com/datalab-platform/datalab/issues/269) - Custom Signal Creation: `AttributeError` when creating signal from menu"
40+
msgstr "Ceci clôture [Issue #269](https://github.com/datalab-platform/datalab/issues/269) - Création de signaux personnalisés : `AttributeError` lors de la création d'un signal à partir du menu"
41+
3342
msgid "**Macro execution:**"
3443
msgstr "**Exécution des macros :**"
3544

0 commit comments

Comments
 (0)