66
77Automatic curve styles depend on the position of the curves on the plot, are not
88stored in signal metadata, and are not shifted by dialogs showing signals. Curve
9- styles chosen by the user are kept.
9+ styles chosen by the user are kept. Automatic styles stored by DataLab 1.3 or
10+ earlier are removed when loading files saved by these versions.
1011"""
1112
1213# guitest: show
1516
1617import os .path as osp
1718
19+ import h5py
1820import numpy as np
21+ import pytest
1922from plotpy .items import CurveItem
2023from qtpy import QtGui as QG
2124from sigima .objects import SignalObj , create_signal
2629 CurveStyles ,
2730 create_adapter_from_object ,
2831)
32+ from datalab .gui .main import DLMainWindow
2933from datalab .gui .panel .signal import SignalPanel
34+ from datalab .h5 .native import DATALAB_VERSION_NAME , is_legacy_style_version
3035from datalab .objectmodel import get_uuid
3136from datalab .tests import datalab_test_app_context , helpers
3237
38+ #: Style of the automatic style cycle of DataLab 1.3 or earlier
39+ LEGACY_STYLE = (CurveStyles .LEGACY_COLORS [2 ], "DashDotDotLine" )
40+
3341
3442def _create_signals (count : int ) -> list [SignalObj ]:
3543 """Create test signals"""
@@ -47,13 +55,60 @@ def _style(item: CurveItem) -> tuple[str, str]:
4755 return QG .QColor (item .param .line .color ).name (), item .param .line .style
4856
4957
50- def _set_user_style (panel : SignalPanel , item : CurveItem , color : str ) -> None :
51- """Set a curve color as the user does with the curve parameters dialog"""
58+ def _stored_style (obj : SignalObj ) -> tuple [str | None , str | None ]:
59+ """Return the color and the line style stored in signal metadata"""
60+ return obj .metadata .get ("color" ), obj .metadata .get ("style" )
61+
62+
63+ def _set_user_style (
64+ panel : SignalPanel , item : CurveItem , color : str , linestyle : str | None = None
65+ ) -> None :
66+ """Set a curve style as the user does with the curve parameters dialog"""
5267 item .param .line .color = color
68+ if linestyle is not None :
69+ item .param .line .style = linestyle
5370 item .param .update_item (item )
5471 panel .plot_item_parameters_changed (item )
5572
5673
74+ def _set_saved_version (filename : str , version : str ) -> None :
75+ """Set the DataLab version that saved a native HDF5 file"""
76+ with h5py .File (filename , "r+" ) as h5file :
77+ del h5file [DATALAB_VERSION_NAME ]
78+ h5file [DATALAB_VERSION_NAME ] = version
79+
80+
81+ def _reload_workspace (win : DLMainWindow , filename : str ) -> list [SignalObj ]:
82+ """Reload a workspace and show all its signals"""
83+ panel = win .signalpanel
84+ panel .remove_all_objects ()
85+ win .load_h5_workspace ([filename ], reset_all = True )
86+ loaded = panel .objmodel .get_all_objects ()
87+ panel .objview .select_objects (loaded )
88+ return loaded
89+
90+
91+ @pytest .mark .parametrize (
92+ "version, expected" ,
93+ [
94+ ("1.3.0" , True ),
95+ ("1.3.10" , True ),
96+ ("0.20.1" , True ),
97+ ("1.4.0" , False ),
98+ ("1.4.0rc1" , False ), # Pre-releases of 1.4 do not store automatic styles
99+ ("1.4.0.dev0" , False ),
100+ ("1.10.0" , False ),
101+ ("2.0.0" , False ),
102+ ("invalid" , False ),
103+ ("" , False ),
104+ (None , False ),
105+ ],
106+ )
107+ def test_legacy_style_version (version : str | None , expected : bool ) -> None :
108+ """Versions which stored automatic curve styles are DataLab 1.3 or earlier"""
109+ assert is_legacy_style_version (version ) is expected
110+
111+
57112def test_styles_follow_curve_positions () -> None :
58113 """Visible curves are given the automatic styles of their positions"""
59114 with datalab_test_app_context (console = False , exec_loop = False ) as win :
@@ -123,23 +178,80 @@ def test_user_styles_are_kept() -> None:
123178 assert _style (_item (panel , loaded [2 ])) == CurveStyles .style_at (2 )
124179
125180
126- def test_legacy_styles_are_automatic () -> None :
127- """Styles stored by earlier versions from their style cycle are automatic"""
181+ def test_user_style_from_legacy_cycle_is_kept () -> None :
182+ """A style chosen by the user is kept over several workspace round trips, even
183+ if it matches a style of the automatic style cycle of DataLab 1.3 or earlier"""
128184 with helpers .WorkdirRestoringTempDir () as tmpdir :
129185 with datalab_test_app_context (console = False , exec_loop = False ) as win :
130186 panel = win .signalpanel
131187 signals = _create_signals (2 )
132- for obj in signals :
133- obj .metadata ["color" ] = CurveStyles .LEGACY_COLORS [2 ]
134- obj .metadata ["style" ] = "DashDotDotLine"
135188 panel .add_objects (signals , set_current = False )
136189 panel .objview .select_objects (signals )
137- for index , obj in enumerate (signals ):
138- assert _style (_item (panel , obj )) == CurveStyles .style_at (index )
139- win .save_h5_workspace (osp .join (tmpdir , "legacy_styles.h5" ))
140- for obj in signals :
141- for key in LINE_STYLE_KEYS :
142- assert key not in obj .metadata
190+ _set_user_style (panel , _item (panel , signals [1 ]), "#1f77b4" , "SolidLine" )
191+ assert CurveStyles .is_legacy_automatic ("#1f77b4" , "SolidLine" )
192+ fname = osp .join (tmpdir , "user_styles.h5" )
193+ for _cycle in range (2 ):
194+ win .save_h5_workspace (fname )
195+ loaded = _reload_workspace (win , fname )
196+ assert _stored_style (loaded [1 ]) == ("#1f77b4" , "SolidLine" )
197+ assert _style (_item (panel , loaded [1 ])) == ("#1f77b4" , "SolidLine" )
198+ assert _stored_style (loaded [0 ]) == (None , None )
199+ assert _style (_item (panel , loaded [0 ])) == CurveStyles .style_at (0 )
200+
201+
202+ def test_legacy_styles_converted_on_load () -> None :
203+ """Automatic styles stored by DataLab 1.3 or earlier are removed on load"""
204+ with helpers .WorkdirRestoringTempDir () as tmpdir :
205+ with datalab_test_app_context (console = False , exec_loop = False ) as win :
206+ panel = win .signalpanel
207+ signals = _create_signals (3 )
208+ signals [0 ].metadata ["color" ], signals [0 ].metadata ["style" ] = LEGACY_STYLE
209+ signals [1 ].metadata ["color" ], signals [1 ].metadata ["style" ] = LEGACY_STYLE
210+ # A legacy color with a line style which is not a legacy automatic one:
211+ signals [2 ].metadata ["color" ] = LEGACY_STYLE [0 ]
212+ signals [2 ].metadata ["style" ] = "DotLine"
213+ panel .add_objects (signals , set_current = False )
214+ panel .objview .select_objects (signals )
215+ fname = osp .join (tmpdir , "legacy_styles.h5" )
216+ win .save_h5_workspace (fname )
217+
218+ # Saved by the current version: stored styles are kept
219+ loaded = _reload_workspace (win , fname )
220+ assert _stored_style (loaded [0 ]) == LEGACY_STYLE
221+ assert _style (_item (panel , loaded [0 ])) == LEGACY_STYLE
222+
223+ # Saved by DataLab 1.3: legacy automatic styles are removed
224+ _set_saved_version (fname , "1.3.0" )
225+ loaded = _reload_workspace (win , fname )
226+ for index in (0 , 1 ):
227+ assert _stored_style (loaded [index ]) == (None , None )
228+ assert _style (_item (panel , loaded [index ])) == CurveStyles .style_at (
229+ index
230+ )
231+ assert _stored_style (loaded [2 ]) == (LEGACY_STYLE [0 ], "DotLine" )
232+ assert _style (_item (panel , loaded [2 ])) == (LEGACY_STYLE [0 ], "DotLine" )
233+
234+
235+ def test_legacy_styles_converted_on_dlhist_import () -> None :
236+ """Automatic styles stored by DataLab 1.3 or earlier are removed when importing
237+ a history file in a workspace in use"""
238+ with helpers .WorkdirRestoringTempDir () as tmpdir :
239+ with datalab_test_app_context (console = False , exec_loop = False ) as win :
240+ panel = win .signalpanel
241+ signals = _create_signals (1 )
242+ signals [0 ].metadata ["color" ], signals [0 ].metadata ["style" ] = LEGACY_STYLE
243+ panel .add_objects (signals , set_current = False )
244+ fname = osp .join (tmpdir , "legacy_styles.dlhist" )
245+ assert win .historypanel .save_to_dlhist_file (fname )
246+ _set_saved_version (fname , "1.3.0" )
247+ existing = panel .objmodel .get_all_objects ()
248+ assert win .historypanel .open_dlhist_file (fname )
249+ imported = [
250+ obj for obj in panel .objmodel .get_all_objects () if obj not in existing
251+ ]
252+ assert len (imported ) == 1
253+ assert _stored_style (imported [0 ]) == (None , None )
254+ assert _stored_style (existing [0 ]) == LEGACY_STYLE
143255
144256
145257def test_reset_curve_styles () -> None :
@@ -168,5 +280,7 @@ def test_reset_curve_styles() -> None:
168280 test_styles_follow_curve_positions ()
169281 test_style_cycle_not_used_by_panel_and_dialogs ()
170282 test_user_styles_are_kept ()
171- test_legacy_styles_are_automatic ()
283+ test_user_style_from_legacy_cycle_is_kept ()
284+ test_legacy_styles_converted_on_load ()
285+ test_legacy_styles_converted_on_dlhist_import ()
172286 test_reset_curve_styles ()
0 commit comments