datalab-platform 1.0.1__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- datalab/__init__.py +1 -1
- datalab/adapters_plotpy/converters.py +3 -1
- datalab/adapters_plotpy/coordutils.py +157 -0
- datalab/adapters_plotpy/roi/image.py +35 -6
- datalab/adapters_plotpy/roi/signal.py +8 -1
- datalab/config.py +2 -0
- datalab/data/doc/DataLab_en.pdf +0 -0
- datalab/data/doc/DataLab_fr.pdf +0 -0
- datalab/gui/actionhandler.py +3 -2
- datalab/gui/macroeditor.py +18 -1
- datalab/gui/main.py +2 -0
- datalab/gui/newobject.py +7 -0
- datalab/gui/panel/base.py +80 -13
- datalab/gui/plothandler.py +10 -1
- datalab/gui/processor/base.py +29 -16
- datalab/gui/processor/signal.py +10 -0
- datalab/gui/roieditor.py +2 -2
- datalab/tests/features/common/coordutils_unit_test.py +212 -0
- datalab/tests/features/common/roi_plotitem_unit_test.py +4 -2
- datalab/tests/features/macro/macroeditor_unit_test.py +102 -1
- datalab/tests/features/signal/custom_signal_bug_unit_test.py +96 -0
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.2.dist-info}/METADATA +3 -3
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.2.dist-info}/RECORD +27 -24
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.2.dist-info}/WHEEL +0 -0
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.2.dist-info}/entry_points.txt +0 -0
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.2.dist-info}/top_level.txt +0 -0
datalab/gui/processor/signal.py
CHANGED
|
@@ -164,6 +164,16 @@ class SignalProcessor(BaseProcessor[SignalROI, ROI1DParam]):
|
|
|
164
164
|
icon_name="convolution.svg",
|
|
165
165
|
obj2_name=_("signal to convolve with"),
|
|
166
166
|
)
|
|
167
|
+
self.register_2_to_1(
|
|
168
|
+
sips.replace_x_by_other_y,
|
|
169
|
+
_("Replace X by other signal's Y"),
|
|
170
|
+
comment=_(
|
|
171
|
+
"Replace X coordinates using Y values from another signal.\n"
|
|
172
|
+
"Useful for calibration: plot data vs wavelength scale."
|
|
173
|
+
),
|
|
174
|
+
obj2_name=_("signal providing Y values for X axis"),
|
|
175
|
+
skip_xarray_compat=True,
|
|
176
|
+
)
|
|
167
177
|
self.register_2_to_1(
|
|
168
178
|
sips.deconvolution,
|
|
169
179
|
_("Deconvolution"),
|
datalab/gui/roieditor.py
CHANGED
|
@@ -186,7 +186,7 @@ class ROIPolygonTool(PolygonTool):
|
|
|
186
186
|
|
|
187
187
|
def __init__(self, manager: PlotManager, obj: ImageObj) -> None:
|
|
188
188
|
super().__init__(manager, switch_to_default_tool=False, toolbar_id=None)
|
|
189
|
-
self.roi = PolygonalROI([
|
|
189
|
+
self.roi = PolygonalROI([0, 0, 1, 0, 1, 1, 0, 1], False)
|
|
190
190
|
self.obj = obj
|
|
191
191
|
|
|
192
192
|
def activate(self):
|
|
@@ -385,7 +385,7 @@ class BaseROIEditor(
|
|
|
385
385
|
"""Parent dialog was accepted: updating ROI Editor data"""
|
|
386
386
|
self.__roi.empty()
|
|
387
387
|
for roi_item in self.roi_items:
|
|
388
|
-
self.__roi.add_roi(plotitem_to_singleroi(roi_item))
|
|
388
|
+
self.__roi.add_roi(plotitem_to_singleroi(roi_item, self.obj))
|
|
389
389
|
if self.singleobj_btn is not None:
|
|
390
390
|
Conf.proc.extract_roi_singleobj.set(self.singleobj_btn.isChecked())
|
|
391
391
|
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Coordinate utilities unit tests
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pytest
|
|
9
|
+
from sigima.objects import (
|
|
10
|
+
CircularROI,
|
|
11
|
+
PolygonalROI,
|
|
12
|
+
RectangularROI,
|
|
13
|
+
SegmentROI,
|
|
14
|
+
create_image,
|
|
15
|
+
create_signal,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from datalab.adapters_plotpy.coordutils import (
|
|
19
|
+
round_image_coords,
|
|
20
|
+
round_image_roi_param,
|
|
21
|
+
round_signal_coords,
|
|
22
|
+
round_signal_roi_param,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_round_signal_coords():
|
|
27
|
+
"""Test signal coordinate rounding"""
|
|
28
|
+
# Create a signal with sampling period of 0.1
|
|
29
|
+
x = np.arange(0, 10, 0.1)
|
|
30
|
+
y = np.sin(x)
|
|
31
|
+
sig = create_signal("test", x, y)
|
|
32
|
+
|
|
33
|
+
# Test basic rounding
|
|
34
|
+
coords = [1.23456789, 5.87654321]
|
|
35
|
+
rounded = round_signal_coords(sig, coords)
|
|
36
|
+
# With sampling period 0.1 and precision_factor 0.1, precision = 0.01
|
|
37
|
+
# Should round to 2 decimal places
|
|
38
|
+
assert rounded == [1.23, 5.88]
|
|
39
|
+
|
|
40
|
+
# Test with custom precision factor
|
|
41
|
+
rounded = round_signal_coords(sig, coords, precision_factor=1.0)
|
|
42
|
+
# precision = 0.1, should round to 1 decimal place
|
|
43
|
+
assert rounded == [1.2, 5.9]
|
|
44
|
+
|
|
45
|
+
# Test with signal that has too few points
|
|
46
|
+
sig_short = create_signal("test", np.array([1.0]), np.array([2.0]))
|
|
47
|
+
coords = [1.23456789]
|
|
48
|
+
rounded = round_signal_coords(sig_short, coords)
|
|
49
|
+
# Should return coords as-is
|
|
50
|
+
assert rounded == coords
|
|
51
|
+
|
|
52
|
+
# Test with constant x (zero sampling period)
|
|
53
|
+
sig_const = create_signal("test", np.ones(10), np.ones(10))
|
|
54
|
+
rounded = round_signal_coords(sig_const, coords)
|
|
55
|
+
# Should return coords as-is
|
|
56
|
+
assert rounded == coords
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_round_image_coords():
|
|
60
|
+
"""Test image coordinate rounding"""
|
|
61
|
+
# Create an image with dx=dy=1.0 (uniform)
|
|
62
|
+
data = np.ones((100, 100))
|
|
63
|
+
img = create_image("test", data)
|
|
64
|
+
|
|
65
|
+
# Test basic rounding
|
|
66
|
+
coords = [10.123456, 20.987654, 30.555555, 40.444444]
|
|
67
|
+
rounded = round_image_coords(img, coords)
|
|
68
|
+
# With pixel spacing 1.0 and precision_factor 0.1, precision = 0.1
|
|
69
|
+
# Should round to 1 decimal place
|
|
70
|
+
assert rounded == [10.1, 21.0, 30.6, 40.4]
|
|
71
|
+
|
|
72
|
+
# Test with custom precision factor
|
|
73
|
+
rounded = round_image_coords(img, coords, precision_factor=1.0)
|
|
74
|
+
# precision = 1.0, should round to 0 decimal places
|
|
75
|
+
assert rounded == [10.0, 21.0, 31.0, 40.0]
|
|
76
|
+
|
|
77
|
+
# Test with empty coords
|
|
78
|
+
assert round_image_coords(img, []) == []
|
|
79
|
+
|
|
80
|
+
# Test error for odd number of coordinates
|
|
81
|
+
with pytest.raises(ValueError, match="even number of elements"):
|
|
82
|
+
round_image_coords(img, [1.0, 2.0, 3.0])
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_round_signal_roi_param():
|
|
86
|
+
"""Test signal ROI parameter rounding"""
|
|
87
|
+
# Create a signal with sampling period of 0.1
|
|
88
|
+
x = np.arange(0, 10, 0.1)
|
|
89
|
+
y = np.sin(x)
|
|
90
|
+
sig = create_signal("test", x, y)
|
|
91
|
+
|
|
92
|
+
# Create a segment ROI
|
|
93
|
+
roi = SegmentROI([1.23456789, 5.87654321], False)
|
|
94
|
+
param = roi.to_param(sig, 0)
|
|
95
|
+
|
|
96
|
+
# Round the parameter
|
|
97
|
+
round_signal_roi_param(sig, param)
|
|
98
|
+
|
|
99
|
+
# Check that coordinates are rounded
|
|
100
|
+
assert param.xmin == 1.23
|
|
101
|
+
assert param.xmax == 5.88
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_round_image_roi_param_rectangle():
|
|
105
|
+
"""Test image ROI parameter rounding for rectangular ROI"""
|
|
106
|
+
# Create an image with dx=dy=1.0
|
|
107
|
+
data = np.ones((100, 100))
|
|
108
|
+
img = create_image("test", data)
|
|
109
|
+
|
|
110
|
+
# Create a rectangular ROI with floating-point errors
|
|
111
|
+
roi = RectangularROI([10.0, 20.0, 50.29999999999995, 75.19999999999999], False)
|
|
112
|
+
param = roi.to_param(img, 0)
|
|
113
|
+
|
|
114
|
+
# Verify we have the floating-point errors before rounding
|
|
115
|
+
assert param.dx == 50.29999999999995
|
|
116
|
+
assert param.dy == 75.19999999999999
|
|
117
|
+
|
|
118
|
+
# Round the parameter
|
|
119
|
+
round_image_roi_param(img, param)
|
|
120
|
+
|
|
121
|
+
# Check that coordinates are rounded
|
|
122
|
+
assert param.x0 == 10.0
|
|
123
|
+
assert param.y0 == 20.0
|
|
124
|
+
assert param.dx == 50.3
|
|
125
|
+
assert param.dy == 75.2
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_round_image_roi_param_circle():
|
|
129
|
+
"""Test image ROI parameter rounding for circular ROI"""
|
|
130
|
+
# Create an image with dx=dy=1.0
|
|
131
|
+
data = np.ones((100, 100))
|
|
132
|
+
img = create_image("test", data)
|
|
133
|
+
|
|
134
|
+
# Create a circular ROI with floating-point errors
|
|
135
|
+
roi = CircularROI([50.123456, 50.987654, 25.555555], False)
|
|
136
|
+
param = roi.to_param(img, 0)
|
|
137
|
+
|
|
138
|
+
# Round the parameter
|
|
139
|
+
round_image_roi_param(img, param)
|
|
140
|
+
|
|
141
|
+
# Check that coordinates are rounded
|
|
142
|
+
assert param.xc == 50.1
|
|
143
|
+
assert param.yc == 51.0
|
|
144
|
+
assert param.r == 25.6
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_round_image_roi_param_polygon():
|
|
148
|
+
"""Test image ROI parameter rounding for polygonal ROI"""
|
|
149
|
+
# Create an image with dx=dy=1.0
|
|
150
|
+
data = np.ones((100, 100))
|
|
151
|
+
img = create_image("test", data)
|
|
152
|
+
|
|
153
|
+
# Create a polygonal ROI with floating-point errors
|
|
154
|
+
coords = [10.123456, 20.987654, 30.555555, 40.444444, 50.111111, 60.999999]
|
|
155
|
+
roi = PolygonalROI(coords, False)
|
|
156
|
+
param = roi.to_param(img, 0)
|
|
157
|
+
|
|
158
|
+
# Round the parameter
|
|
159
|
+
round_image_roi_param(img, param)
|
|
160
|
+
|
|
161
|
+
# Check that coordinates are rounded
|
|
162
|
+
expected = np.array([10.1, 21.0, 30.6, 40.4, 50.1, 61.0])
|
|
163
|
+
np.testing.assert_array_equal(param.points, expected)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def test_round_coords_non_uniform_image():
|
|
167
|
+
"""Test coordinate rounding for non-uniform image coordinates"""
|
|
168
|
+
# Create an image with non-uniform coordinates
|
|
169
|
+
data = np.ones((10, 10))
|
|
170
|
+
img = create_image("test", data)
|
|
171
|
+
# Set non-uniform coordinates
|
|
172
|
+
img.xcoords = np.array([0, 1, 3, 6, 10, 15, 21, 28, 36, 45]) # varying spacing
|
|
173
|
+
img.ycoords = np.array([0, 2, 4, 6, 8, 10, 12, 14, 16, 18]) # uniform spacing of 2
|
|
174
|
+
|
|
175
|
+
# Test rounding - should use average spacing
|
|
176
|
+
coords = [5.123456, 7.987654, 25.555555, 13.444444]
|
|
177
|
+
rounded = round_image_coords(img, coords)
|
|
178
|
+
|
|
179
|
+
# Average dx ≈ 5.0, average dy = 2.0
|
|
180
|
+
# With precision_factor=0.1: precision_x=0.5, precision_y=0.2
|
|
181
|
+
# Should round to 1 decimal place for both
|
|
182
|
+
assert rounded == [5.1, 8.0, 25.6, 13.4]
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def test_round_coords_preserves_structure():
|
|
186
|
+
"""Test that coordinate rounding preserves the structure of coordinates"""
|
|
187
|
+
# Create an image
|
|
188
|
+
data = np.ones((100, 100))
|
|
189
|
+
img = create_image("test", data)
|
|
190
|
+
|
|
191
|
+
# Test with multiple coordinate pairs
|
|
192
|
+
coords = [
|
|
193
|
+
10.111,
|
|
194
|
+
20.222,
|
|
195
|
+
30.333,
|
|
196
|
+
40.444,
|
|
197
|
+
50.555,
|
|
198
|
+
60.666,
|
|
199
|
+
70.777,
|
|
200
|
+
80.888,
|
|
201
|
+
]
|
|
202
|
+
rounded = round_image_coords(img, coords)
|
|
203
|
+
|
|
204
|
+
# Should have same length
|
|
205
|
+
assert len(rounded) == len(coords)
|
|
206
|
+
|
|
207
|
+
# Each coordinate should be rounded independently
|
|
208
|
+
assert all(isinstance(c, (int, float)) for c in rounded)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
if __name__ == "__main__":
|
|
212
|
+
pytest.main([__file__, "-v"])
|
|
@@ -32,11 +32,13 @@ def __conversion_methods(
|
|
|
32
32
|
single_roi = roi.get_single_roi(0)
|
|
33
33
|
with qt_app_context(exec_loop=False):
|
|
34
34
|
plot_item = create_adapter_from_object(single_roi).to_plot_item(obj)
|
|
35
|
-
sroi_new = plotitem_to_singleroi(plot_item)
|
|
35
|
+
sroi_new = plotitem_to_singleroi(plot_item, obj)
|
|
36
36
|
orig_coords = [float(val) for val in single_roi.get_physical_coords(obj)]
|
|
37
37
|
new_coords = [float(val) for val in sroi_new.get_physical_coords(obj)]
|
|
38
38
|
execenv.print(f"{orig_coords} --> {new_coords}")
|
|
39
|
-
|
|
39
|
+
# Check that coordinates are close
|
|
40
|
+
# (allowing for rounding applied during conversion)
|
|
41
|
+
assert np.allclose(orig_coords, new_coords, rtol=1e-5, atol=1e-10)
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
def test_signal_roi_plotitem_conversion() -> None:
|
|
@@ -18,13 +18,15 @@ All other methods should be tested here.
|
|
|
18
18
|
# guitest: show
|
|
19
19
|
|
|
20
20
|
import os.path as osp
|
|
21
|
+
import time
|
|
21
22
|
|
|
22
23
|
from guidata.qthelpers import qt_app_context
|
|
24
|
+
from qtpy import QtWidgets as QW
|
|
23
25
|
|
|
24
26
|
from datalab.env import execenv
|
|
25
27
|
from datalab.gui.macroeditor import Macro
|
|
26
28
|
from datalab.gui.panel import macro
|
|
27
|
-
from datalab.tests import helpers
|
|
29
|
+
from datalab.tests import datalab_test_app_context, helpers
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def get_macro_example_path() -> str:
|
|
@@ -98,5 +100,104 @@ def test_macro_editor():
|
|
|
98
100
|
assert widget.get_macro_titles()[0] == osp.basename(macro_path)
|
|
99
101
|
|
|
100
102
|
|
|
103
|
+
def test_macro_unicode_encoding():
|
|
104
|
+
"""Test that macros can print Unicode characters without encoding errors.
|
|
105
|
+
|
|
106
|
+
This test verifies the fix for the UnicodeEncodeError that occurred on Windows
|
|
107
|
+
systems with locales like cp1252 when macros printed Unicode characters.
|
|
108
|
+
|
|
109
|
+
The test creates and runs a macro that prints various Unicode characters,
|
|
110
|
+
simulating the scenario where RemoteProxy connection messages (which contain
|
|
111
|
+
arrows →) would cause encoding errors on Windows with cp1252 locale.
|
|
112
|
+
|
|
113
|
+
Without the UTF-8 encoding fix in Macro.run(), this test would fail with:
|
|
114
|
+
UnicodeEncodeError: 'charmap' codec can't encode character '\u2192'
|
|
115
|
+
"""
|
|
116
|
+
with helpers.WorkdirRestoringTempDir():
|
|
117
|
+
with datalab_test_app_context(console=False) as win:
|
|
118
|
+
win.set_current_panel("macro")
|
|
119
|
+
|
|
120
|
+
# Create a macro that prints various Unicode characters
|
|
121
|
+
macro = win.macropanel.add_macro()
|
|
122
|
+
macro.title = "Unicode Test Macro"
|
|
123
|
+
|
|
124
|
+
# This test verifies that Unicode characters can be printed successfully.
|
|
125
|
+
# The macro prints Unicode characters without any encoding manipulation.
|
|
126
|
+
# With the UTF-8 fix in Macro.run(), these print statements work correctly.
|
|
127
|
+
# Without the fix, on systems with cp1252 locale, these would fail.
|
|
128
|
+
#
|
|
129
|
+
# Note: We cannot reliably simulate cp1252 locale in the test because:
|
|
130
|
+
# 1. Modern Python often defaults to UTF-8
|
|
131
|
+
# 2. If we manually reconfigure to cp1252 in the macro, it overrides
|
|
132
|
+
# any fix done before the macro code runs
|
|
133
|
+
# 3. The PYTHONIOENCODING env var might be set system-wide
|
|
134
|
+
#
|
|
135
|
+
# This test serves as a regression test - it will catch if the fix
|
|
136
|
+
# is removed, but only on systems that actually default to cp1252.
|
|
137
|
+
unicode_code = """
|
|
138
|
+
import sys
|
|
139
|
+
|
|
140
|
+
# Print encoding info for debugging
|
|
141
|
+
print(f"stdout encoding: {sys.stdout.encoding}")
|
|
142
|
+
print(f"stderr encoding: {sys.stderr.encoding}")
|
|
143
|
+
|
|
144
|
+
# Print various Unicode characters that are not in cp1252
|
|
145
|
+
# On systems with cp1252 default locale, without the UTF-8 fix,
|
|
146
|
+
# these would cause UnicodeEncodeError
|
|
147
|
+
print("Testing Unicode output:")
|
|
148
|
+
print(" → Arrow character (U+2192)")
|
|
149
|
+
print(" ✓ Check mark (U+2713)")
|
|
150
|
+
print(" • Bullet point (U+2022)")
|
|
151
|
+
print(" … Ellipsis (U+2026)")
|
|
152
|
+
print(" Emoji: 🎉 🚀 ⚡")
|
|
153
|
+
|
|
154
|
+
# Simulate RemoteProxy connection message format
|
|
155
|
+
print("Setting XML-RPC port... [input:None] →[execenv.xmlrpcport:None] OK")
|
|
156
|
+
|
|
157
|
+
print("All Unicode tests passed! ✓")
|
|
158
|
+
"""
|
|
159
|
+
macro.set_code(unicode_code)
|
|
160
|
+
|
|
161
|
+
# Run the macro and wait for completion
|
|
162
|
+
execenv.print("Running Unicode test macro...")
|
|
163
|
+
win.macropanel.run_macro()
|
|
164
|
+
|
|
165
|
+
# Wait for macro to complete (with timeout)
|
|
166
|
+
# We need to process Qt events for the QProcess signals to be delivered
|
|
167
|
+
max_wait = 10 # seconds
|
|
168
|
+
elapsed = 0
|
|
169
|
+
while macro.is_running() and elapsed < max_wait:
|
|
170
|
+
QW.QApplication.processEvents()
|
|
171
|
+
time.sleep(0.1)
|
|
172
|
+
elapsed += 0.1
|
|
173
|
+
|
|
174
|
+
# Verify the macro completed (not still running)
|
|
175
|
+
# If there was an encoding error, the process would have crashed
|
|
176
|
+
assert not macro.is_running(), (
|
|
177
|
+
"Macro did not complete within timeout - "
|
|
178
|
+
"likely failed with encoding error"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Check the exit code - should be 0 for success
|
|
182
|
+
# With the UTF-8 fix, the macro completes successfully (exit code 0)
|
|
183
|
+
# Without the fix, it crashes with UnicodeEncodeError (exit code 1)
|
|
184
|
+
exit_code = macro.get_exit_code()
|
|
185
|
+
assert exit_code == 0, (
|
|
186
|
+
f"Macro exited with error code {exit_code} - "
|
|
187
|
+
f"likely UnicodeEncodeError when trying to print Unicode characters"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
execenv.print("✓ Unicode test macro completed successfully!")
|
|
191
|
+
execenv.print(
|
|
192
|
+
"Note: This test verifies Unicode support works. On systems with "
|
|
193
|
+
"UTF-8 as default encoding, it may pass even without the fix. "
|
|
194
|
+
"The fix is critical for Windows systems with cp1252 locale."
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Clean up
|
|
198
|
+
win.macropanel.remove_all_objects()
|
|
199
|
+
|
|
200
|
+
|
|
101
201
|
if __name__ == "__main__":
|
|
102
202
|
test_macro_editor()
|
|
203
|
+
test_macro_unicode_encoding()
|
|
@@ -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"])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datalab-platform
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: DataLab is a data processing and analysis software for scientific and industrial applications
|
|
5
5
|
Author-email: Pierre Raybaut <p.raybaut@codra.fr>
|
|
6
6
|
Maintainer-email: DataLab Platform Developers <p.raybaut@codra.fr>
|
|
@@ -32,9 +32,9 @@ Classifier: Topic :: Software Development :: Widget Sets
|
|
|
32
32
|
Requires-Python: <4,>=3.9
|
|
33
33
|
Description-Content-Type: text/markdown
|
|
34
34
|
License-File: LICENSE
|
|
35
|
-
Requires-Dist: guidata>=3.13.
|
|
35
|
+
Requires-Dist: guidata>=3.13.4
|
|
36
36
|
Requires-Dist: PlotPy>=2.8.2
|
|
37
|
-
Requires-Dist: Sigima>=1.0.
|
|
37
|
+
Requires-Dist: Sigima>=1.0.3
|
|
38
38
|
Requires-Dist: NumPy>=1.22
|
|
39
39
|
Requires-Dist: SciPy>=1.10.1
|
|
40
40
|
Requires-Dist: scikit-image>=0.19.2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
datalab/__init__.py,sha256=
|
|
1
|
+
datalab/__init__.py,sha256=Tzx-iqJT13h7TNqdvHn_1uxpRhOMjhPpVo87OJtt6T4,1245
|
|
2
2
|
datalab/app.py,sha256=DEr6IQ211YfltLD8xdHngb5-Zv8Tng9G2t2snW-AowQ,3004
|
|
3
|
-
datalab/config.py,sha256=
|
|
3
|
+
datalab/config.py,sha256=C1jP6GLPvCG_9AgGgL5CVEDaHMddplLwk-PUbULbLYs,34386
|
|
4
4
|
datalab/env.py,sha256=gWfLH7wWdj7b7nTocvSi1ptEF1KkGZry5Sw9g7ND2N8,18769
|
|
5
5
|
datalab/objectmodel.py,sha256=v275fem6ZLK4xa4qvbES8dh9p90-ZwmCzTu-wuGh7HE,22410
|
|
6
6
|
datalab/plugins.py,sha256=hTkbeDDD2oGovKLWCcuuleEkTLZWI3dnyhqPQh7saZM,11950
|
|
@@ -12,7 +12,8 @@ datalab/adapters_metadata/table_adapter.py,sha256=DZ3kD3A-wiiXWzRQ2P-ld3v-Fv5EwX
|
|
|
12
12
|
datalab/adapters_plotpy/__init__.py,sha256=YKQa4-mB6TQPN8QVc4sknnmWb6muRWpnPrmbsx9W4Jw,1471
|
|
13
13
|
datalab/adapters_plotpy/annotations.py,sha256=zDMFw2OYzDUDq-yKDkDuWxHTxrDHc3mNBJEyCc7gCUc,3985
|
|
14
14
|
datalab/adapters_plotpy/base.py,sha256=xk4Zu0SamshK8Fb9htn-w2y4BPLLkiZOmJ3DXpQoI3Y,2906
|
|
15
|
-
datalab/adapters_plotpy/converters.py,sha256=
|
|
15
|
+
datalab/adapters_plotpy/converters.py,sha256=dRR-eno4iZjh56j9cuU1TVjISYC0FlqdgG67OtvOb9M,2682
|
|
16
|
+
datalab/adapters_plotpy/coordutils.py,sha256=noHhA8PI0fbqiRU2HoZcnSTSA_TXMsmK9KjVABKdSxA,5887
|
|
16
17
|
datalab/adapters_plotpy/factories.py,sha256=5_cb2mGNJPR2bS97J36XvNkuf9rwu4xHquP5T_hOnHg,2986
|
|
17
18
|
datalab/adapters_plotpy/objects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
19
|
datalab/adapters_plotpy/objects/base.py,sha256=MSWv2I057_2qtJhY02GslJ23TRdK_2GqWgD0Ap1eTjg,6914
|
|
@@ -22,14 +23,14 @@ datalab/adapters_plotpy/objects/signal.py,sha256=Bp8ahogAPzq_ndY2wK5t4MflhMoYKTA
|
|
|
22
23
|
datalab/adapters_plotpy/roi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
24
|
datalab/adapters_plotpy/roi/base.py,sha256=FbqYb9cf1FASWri901Jkf162GyUYn0FQp97tzTmGEo8,3992
|
|
24
25
|
datalab/adapters_plotpy/roi/factory.py,sha256=vH8ko4hWoxySSwQjpblOgU7PSGXZ0aa2_cl33nkKiqc,2908
|
|
25
|
-
datalab/adapters_plotpy/roi/image.py,sha256=
|
|
26
|
-
datalab/adapters_plotpy/roi/signal.py,sha256=
|
|
26
|
+
datalab/adapters_plotpy/roi/image.py,sha256=nhW60NPQJwUvx-cwJylzJp1kNg_SEY9NyjP-i5niIPs,8285
|
|
27
|
+
datalab/adapters_plotpy/roi/signal.py,sha256=ZPQehXVAw9rIEUmwUsAmM-6t9yU_2VHdNQTbLJUSJXA,2439
|
|
27
28
|
datalab/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
29
|
datalab/control/baseproxy.py,sha256=noCjpF-FcuvUg-7BpEQPgqde8RPMRTxvafA6douJSF0,24813
|
|
29
30
|
datalab/control/proxy.py,sha256=CNnX8u8VAfYvL1jUMRf0I8By5ugYVD2IE7nAKuhqzlE,10906
|
|
30
31
|
datalab/control/remote.py,sha256=f6PQkKpIlad32DVYxzX5UFfGtYWxxH24U4eYbVK0YHY,35350
|
|
31
|
-
datalab/data/doc/DataLab_en.pdf,sha256=
|
|
32
|
-
datalab/data/doc/DataLab_fr.pdf,sha256=
|
|
32
|
+
datalab/data/doc/DataLab_en.pdf,sha256=kIghKyun-feHg8pKxIeoJcJZ5GoDS97pla8yjUi1pTY,17204557
|
|
33
|
+
datalab/data/doc/DataLab_fr.pdf,sha256=nCZHYIN_icMr-J7OvUXtzTKcnSeMOqa1pzbwRiMEUm0,17244893
|
|
33
34
|
datalab/data/icons/analysis.svg,sha256=jDZAqd1UpSfyiIPXnk3AyUcxqYByYvcKlJ61PI3g7bE,6592
|
|
34
35
|
datalab/data/icons/apply.svg,sha256=VQQxY3a2UA7Chu5gJ7XQUwiRHdqfkOmmRNhv34PA0SY,471
|
|
35
36
|
datalab/data/icons/check_all.svg,sha256=pe7FtRiD64KvzBPh3JJpQN9tDmdwtbTHy3YHx90KGq8,4254
|
|
@@ -297,29 +298,29 @@ datalab/data/tutorials/laser_beam/TEM00_z_70.jpg,sha256=monLxXE8zwzHmv8i2eVwToEr
|
|
|
297
298
|
datalab/data/tutorials/laser_beam/TEM00_z_75.jpg,sha256=4sQ17VWtte7E6RbMWiUcluGCXjWYLmnfCW6I3b1lWHg,81376
|
|
298
299
|
datalab/data/tutorials/laser_beam/TEM00_z_80.jpg,sha256=5KMSrqB02sAyOqytQyRgMsTfrRT3Cna9vhcBRL4PWis,80464
|
|
299
300
|
datalab/gui/__init__.py,sha256=ueRKAHh4jpIM7psJWmn-ddRpTU9Yy7gUljWJb6uluJw,2923
|
|
300
|
-
datalab/gui/actionhandler.py,sha256=
|
|
301
|
+
datalab/gui/actionhandler.py,sha256=BWVbVI1C2cJSQ3LrxJxh6be4kdVvx8U8xbdnbmnMqwo,72948
|
|
301
302
|
datalab/gui/docks.py,sha256=Fan4Pv9vQ4xrZdFgB4KfqbM28E5JHK93_ZARSfGEXz8,17164
|
|
302
303
|
datalab/gui/h5io.py,sha256=786P-mxrFA0SAeA6YrH9F_xz8Nu01fMAtUd672bfMNU,5759
|
|
303
|
-
datalab/gui/macroeditor.py,sha256=
|
|
304
|
-
datalab/gui/main.py,sha256=
|
|
305
|
-
datalab/gui/newobject.py,sha256=
|
|
304
|
+
datalab/gui/macroeditor.py,sha256=HrndTN6Wz_kg01OlS6YFTKzryGl0We-Dm40X4Ny6AqI,10128
|
|
305
|
+
datalab/gui/main.py,sha256=wQDVIPQ3h-iy_yloONakY7VyPxTxFBEpqvFjKyb6RJ0,82052
|
|
306
|
+
datalab/gui/newobject.py,sha256=dfGWiQF13CeJ0LHDS3fcYjuVTpszl3e2XAc6xyUQXKc,7625
|
|
306
307
|
datalab/gui/objectview.py,sha256=ZHAn66Qkt_Fjld8uAYw0EGS8EiMR_xeRYmoLzQzbeM8,32122
|
|
307
|
-
datalab/gui/plothandler.py,sha256=
|
|
308
|
+
datalab/gui/plothandler.py,sha256=pcFOPSK5wqnteSxU8o9qkDi7B4JPojZNgitVV0xOFa4,33473
|
|
308
309
|
datalab/gui/profiledialog.py,sha256=n7X-XwJPYD9fi7lQ1V3WemsHq-fNokwfLfqMIwY30tA,12799
|
|
309
|
-
datalab/gui/roieditor.py,sha256=
|
|
310
|
+
datalab/gui/roieditor.py,sha256=g2_8SyIJ5i8u8o_p-_h-vyML10mA0N0TteAScZMn-6c,22276
|
|
310
311
|
datalab/gui/roigrideditor.py,sha256=Ce4g2E65S0dROaYZSyOJekgeKDReNS8MCwt_WHLWH3k,7984
|
|
311
312
|
datalab/gui/settings.py,sha256=lf5NMn1StgrmlriAqcWhD0dobWSPbrzFx7SoNt81je0,22561
|
|
312
313
|
datalab/gui/tour.py,sha256=PzT9hIFohrLovQ7yCBEqPhGYYFLNIDkh053nTmj2y1U,32399
|
|
313
314
|
datalab/gui/panel/__init__.py,sha256=ZVgYukxTkP763BoNUWEIoHjrt_GnEiAsGexXTu4QiJQ,1452
|
|
314
|
-
datalab/gui/panel/base.py,sha256=
|
|
315
|
+
datalab/gui/panel/base.py,sha256=vzlHybaFIX6tHO7uY0EjTDrhhadBobznD_BHANLyYUk,137634
|
|
315
316
|
datalab/gui/panel/image.py,sha256=8SWLS24RdPKzO-tCoc-8PDFb2PQbjNcVb_heItRpZjI,5696
|
|
316
317
|
datalab/gui/panel/macro.py,sha256=gbqvaLa-IsqCV1g6WwTH57z89K7uratO0LPHqGpRKgs,20491
|
|
317
318
|
datalab/gui/panel/signal.py,sha256=LRsF-py96xvWa-XKJW9Qpay-4O3F_zLs2UFydrjCnYw,5762
|
|
318
319
|
datalab/gui/processor/__init__.py,sha256=6-Boho-VTI8I5s1UWaauT17gW8fp_UK2DBWqvMZ4qF8,3132
|
|
319
|
-
datalab/gui/processor/base.py,sha256=
|
|
320
|
+
datalab/gui/processor/base.py,sha256=m44_QSbrLCFcO2_KUxQDZFrFwbQIRbVhY5pJ2orIKqg,101314
|
|
320
321
|
datalab/gui/processor/catcher.py,sha256=g8_cEA7gOyej-vwjmUksgpcBbFlRZwHsGM9aYTyL6Ys,2667
|
|
321
322
|
datalab/gui/processor/image.py,sha256=PMdZ9KS3rJTHU7qZ6KB8hgKVykO3U2jex5Yzz2vOKIg,48062
|
|
322
|
-
datalab/gui/processor/signal.py,sha256=
|
|
323
|
+
datalab/gui/processor/signal.py,sha256=Dyj6fHSXOqY_tCNmeubz5lyqOtyYa4pSSnXkXdBUbXA,29055
|
|
323
324
|
datalab/h5/__init__.py,sha256=N55pl08bbGH-QCTqoA-8BCe5Hgj-N1QxvvCd2ZvGQ9Q,301
|
|
324
325
|
datalab/h5/common.py,sha256=zfXNZT4ZnTlLCe5Hz2vv44FXSKJqhpidUiRqY8CYCLI,10268
|
|
325
326
|
datalab/h5/generic.py,sha256=s51etvOl2acgkvqhhq_o_VxldmPCj3TsK6_N_2U4l8E,20737
|
|
@@ -357,6 +358,7 @@ datalab/tests/features/common/add_metadata_app_test.py,sha256=0OYyXZpIkidmqb4dbP
|
|
|
357
358
|
datalab/tests/features/common/add_metadata_unit_test.py,sha256=ypbwZfhEcW6WrEy6BhG3gdlv8AWRerTkFMMn-U3rMcQ,9269
|
|
358
359
|
datalab/tests/features/common/annotations_management_unit_test.py,sha256=Sjoywcz9sdzqlNw_aqLT__HQDhwew1oL1jPUC_QQDD4,5379
|
|
359
360
|
datalab/tests/features/common/auto_analysis_recompute_unit_test.py,sha256=0CSi6kDz130sNN_iqxeHb2S3Z4G9YPewP-8G6fYYuCk,10666
|
|
361
|
+
datalab/tests/features/common/coordutils_unit_test.py,sha256=tElai5nS-9eN8xgJfSphAxEOjx3lJOPLEEeMxu1BxyU,6706
|
|
360
362
|
datalab/tests/features/common/createobject_unit_test.py,sha256=2_LnW_RF0nhKDtmwBQn6tl7vM_1CFiJN7urDNFFUJFU,1631
|
|
361
363
|
datalab/tests/features/common/geometry_results_app_test.py,sha256=pB9Hj6IvNl8HUEuTAyeW5LHX0pVymxFnGUWhdEyJFz8,5192
|
|
362
364
|
datalab/tests/features/common/interactive_processing_test.py,sha256=lNWRw9oHGu5U5Rnk5BCKJVXJdBii2fWLHmG5sumVLWA,46488
|
|
@@ -374,7 +376,7 @@ datalab/tests/features/common/reorder_app_test.py,sha256=pIYbvBNjhWe-Eu6_EMJzczp
|
|
|
374
376
|
datalab/tests/features/common/result_deletion_unit_test.py,sha256=4D6NToe_kAQ2gOlQBROj-MgFimrl31n6gijRV00nnS8,3593
|
|
375
377
|
datalab/tests/features/common/result_merged_label_unit_test.py,sha256=VUf4vfrUbgtdOyU5x6lj3-xg4vklYHdU5q-3DCpRVTg,6387
|
|
376
378
|
datalab/tests/features/common/result_shape_settings_unit_test.py,sha256=NceT85JMqfVUScZ9p8-D_E6L9ct51V2Ev6v5zpajpPg,9406
|
|
377
|
-
datalab/tests/features/common/roi_plotitem_unit_test.py,sha256=
|
|
379
|
+
datalab/tests/features/common/roi_plotitem_unit_test.py,sha256=wQHycjeNL3V01ldQn4NQvtsqkAKHXd1G6yP1d2GRESU,2584
|
|
378
380
|
datalab/tests/features/common/roieditor_unit_test.py,sha256=1jnQTv_tPiFLM4EQutAENFBatZMv9HIo1TjEVaINwWc,4272
|
|
379
381
|
datalab/tests/features/common/save_to_dir_app_test.py,sha256=g-73KBzAehTW1iJ4cmI_rXqYlTV8vDXnx9dVcsvHkhs,6345
|
|
380
382
|
datalab/tests/features/common/save_to_dir_unit_test.py,sha256=a_IAnJ-f18rxTK8JVxfUHdReluUukt1VXuWKhrj3XNQ,17324
|
|
@@ -427,9 +429,10 @@ datalab/tests/features/image/roigrid_unit_test.py,sha256=0xQPIkT7Jp0RvU2JaaWeFNO
|
|
|
427
429
|
datalab/tests/features/image/side_by_side_app_test.py,sha256=x7C4873p6dGe9ck-O-uGA6BS0RwtZnpMM28SXP7KiKA,1540
|
|
428
430
|
datalab/tests/features/macro/__init__.py,sha256=_6Yl-eMBve0mGQA-aiFg4qvQ7GUCV5eGvIcoRf4mEPw,3
|
|
429
431
|
datalab/tests/features/macro/macro_app_test.py,sha256=BKT9usab_k8dLsfvanHfiv2I2vA4wiOqMDmzITDdY1g,804
|
|
430
|
-
datalab/tests/features/macro/macroeditor_unit_test.py,sha256=
|
|
432
|
+
datalab/tests/features/macro/macroeditor_unit_test.py,sha256=mR1mVxgq9iKyvSDIggkZdouRl-txfPdzDa3WZKRVANo,7868
|
|
431
433
|
datalab/tests/features/signal/__init__.py,sha256=_6Yl-eMBve0mGQA-aiFg4qvQ7GUCV5eGvIcoRf4mEPw,3
|
|
432
434
|
datalab/tests/features/signal/baseline_dialog_test.py,sha256=wYdWKEpXJ74DXbMeEjxOSCFIvh36QLXiDH0yP-Xjfg8,1804
|
|
435
|
+
datalab/tests/features/signal/custom_signal_bug_unit_test.py,sha256=8tyNX6pxp4ToTSV61OxgNBsUld5NBcBm6RWtQI6LTNg,3609
|
|
433
436
|
datalab/tests/features/signal/deltax_dialog_unit_test.py,sha256=9I4-gIAUlkFRyiDr_6s1Se-2Zp1rv_Ix6wcQ137pKKw,1166
|
|
434
437
|
datalab/tests/features/signal/fft1d_app_test.py,sha256=8560mrwMuq4wBF163VkrcdEjOSHGa7nT06oTPD3EQYA,730
|
|
435
438
|
datalab/tests/features/signal/filter_app_test.py,sha256=iDaA7mOnti2xVMV80k0m7i948M0q_CmaO1mE8_swIKo,1663
|
|
@@ -486,9 +489,9 @@ datalab/widgets/status.py,sha256=LopY06Mom3RqvxGCdqKJUobH3-7OxCNz5YGeAY_EQHE,803
|
|
|
486
489
|
datalab/widgets/textimport.py,sha256=NqJH8JsqEoIvjZeebW4GZkCD4ubxBuDJih6RzFki1K0,27997
|
|
487
490
|
datalab/widgets/warningerror.py,sha256=KiPagfry7-OJ7bHPw9r6RqhJm5e8SZfrjrC_DuNtVJw,8258
|
|
488
491
|
datalab/widgets/wizard.py,sha256=KN7NYadQuxO921WK9q0NfWAlw66l4c8JF4yeOhcRaAo,9904
|
|
489
|
-
datalab_platform-1.0.
|
|
490
|
-
datalab_platform-1.0.
|
|
491
|
-
datalab_platform-1.0.
|
|
492
|
-
datalab_platform-1.0.
|
|
493
|
-
datalab_platform-1.0.
|
|
494
|
-
datalab_platform-1.0.
|
|
492
|
+
datalab_platform-1.0.2.dist-info/licenses/LICENSE,sha256=iMgU90_yimtLdU_nI3rWUq2mDMCvdm_EOVliNKyNLXo,1565
|
|
493
|
+
datalab_platform-1.0.2.dist-info/METADATA,sha256=7g_KzBDcn6Kt_erpbALp5HV7hojRCvhcYjB3-DBXS2k,6945
|
|
494
|
+
datalab_platform-1.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
495
|
+
datalab_platform-1.0.2.dist-info/entry_points.txt,sha256=9qI5xVtl8G_ivVnsIYV-v2rPZ98HVO1WF1Of78ZxZhg,122
|
|
496
|
+
datalab_platform-1.0.2.dist-info/top_level.txt,sha256=sK3HGZNGMtLR-m29UNms9QgVzVqwSNCtmuR-_hmamdc,8
|
|
497
|
+
datalab_platform-1.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|