1616 QStyleOptionViewItem , QDialog , QMenu , QToolTip , QListView
1717from AnyQt .QtTest import QTest , QSignalSpy
1818
19+ from orangewidget .settings import Context
1920from orangewidget .tests .utils import simulate
2021
2122from Orange .data import (
@@ -325,7 +326,7 @@ def test_restore(self):
325326 w = self .widget
326327
327328 def restore (state ):
328- w ._domain_change_store = state
329+ w ._domain_change_hints = state
329330 w ._restore ()
330331
331332 model = w .variables_model
@@ -338,6 +339,177 @@ def restore(state):
338339 tr = model .data (model .index (4 ), TransformRole )
339340 self .assertEqual (tr , [AsString (), Rename ("Z" )])
340341
342+ def test_hint_keeping (self ):
343+ editor : ContinuousVariableEditor = self .widget .findChild (ContinuousVariableEditor )
344+ name_edit = editor .name_edit
345+ model = self .widget .domain_view .model ()
346+
347+ def rename (fr , to ):
348+ for idx in range (fr , to ):
349+ self .widget .domain_view .setCurrentIndex (model .index (idx ))
350+ cur_text = name_edit .text ()
351+ if cur_text [0 ] != "x" :
352+ name_edit .setText ("x" + cur_text )
353+ editor .on_name_changed ()
354+
355+ def data (fr , to ):
356+ return Table .from_numpy (Domain (vars [fr :to ]),
357+ np .zeros ((1 , to - fr )))
358+
359+
360+ vars = [ContinuousVariable (f"v{ i } " ) for i in range (1020 )]
361+ self .send_signal (data (0 , 5 ))
362+ rename (2 , 4 )
363+
364+ self .send_signal (None )
365+ self .assertIsNone (self .get_output ())
366+
367+ self .send_signal (data (3 , 7 ))
368+ outp = self .get_output ()
369+ self .assertEqual ([var .name for var in outp .domain .attributes ],
370+ ["xv3" , "v4" , "v5" , "v6" ])
371+
372+ self .send_signal (data (0 , 5 ))
373+ outp = self .get_output ()
374+ self .assertEqual ([var .name for var in outp .domain .attributes ],
375+ ["v0" , "v1" , "xv2" , "xv3" , "v4" ])
376+
377+ self .send_signal (data (3 , 7 ))
378+ outp = self .get_output ()
379+ self .assertEqual ([var .name for var in outp .domain .attributes ],
380+ ["xv3" , "v4" , "v5" , "v6" ])
381+
382+ # This is too large: widget should retain just hints related to
383+ # the current data
384+ self .send_signal (data (3 , 1020 ))
385+ outp = self .get_output ()
386+ self .assertEqual ([var .name for var in outp .domain .attributes [:4 ]],
387+ ["xv3" , "v4" , "v5" , "v6" ])
388+ rename (5 , 1017 )
389+ self .widget .commit ()
390+ outp = self .get_output ()
391+ self .assertEqual ([var .name for var in outp .domain .attributes [- 3 :]],
392+ ["xv1017" , "xv1018" , "xv1019" ])
393+
394+ self .send_signal (None )
395+ self .assertIsNone (self .get_output ())
396+
397+ # Tests that hints for the current data are kept
398+ # - including the earliest (v3) and latest (v1019)
399+ self .send_signal (data (3 , 1020 ))
400+ outp = self .get_output ()
401+ self .assertEqual ([var .name for var in outp .domain .attributes [:4 ]],
402+ ["xv3" , "v4" , "v5" , "v6" ])
403+ self .assertEqual ([var .name for var in outp .domain .attributes [- 3 :]],
404+ ["xv1017" , "xv1018" , "xv1019" ])
405+
406+ # Tests that older hints are dropped: v2 should be lost
407+ self .send_signal (data (0 , 5 ))
408+ outp = self .get_output ()
409+ self .assertEqual ([var .name for var in outp .domain .attributes ],
410+ ["v0" , "v1" , "v2" , "xv3" , "v4" ])
411+
412+ def test_migrate_settings_hints_2_to_3 (self ):
413+ settings = {
414+ '__version__' : 2 ,
415+ 'context_settings' :
416+ [Context (values = {
417+ '_domain_change_store' : (
418+ {('Categorical' , ('a' , ('mir1' , 'mir4' , 'mir2' ), (), False )):
419+ [('Rename' , ('disease mir' ,))],
420+ ('Categorical' , ('b' , ('mir4' , 'mir1' , 'mir2' ), (), False )):
421+ [('Rename' , ('disease mirs' ,))]
422+ },
423+ - 2 ),
424+ '_merge_dialog_settings' : ({}, - 4 ),
425+ '_selected_item' : (('1' , 0 ), - 2 ),
426+ 'output_table_name' : ('boo' , - 2 ),
427+ '__version__' : 2 }),
428+ Context (values = {
429+ '_domain_change_store' : (
430+ {('Categorical' , ('b' , ('mir4' , 'mir1' , 'mir2' ), (), False )):
431+ [('Rename' , ('disease bmir' ,))],
432+ ('Categorical' , ('c' , ('mir4' , 'mir1' , 'mir2' ), (), False )):
433+ [('Rename' , ('disease mirs' ,))]
434+ },
435+ - 2 ),
436+ '_merge_dialog_settings' : ({}, - 4 ),
437+ '_selected_item' : (('1' , 0 ), - 2 ),
438+ 'output_table_name' : ('far' , - 2 ),
439+ '__version__' : 2 }),
440+ ]}
441+ migrated_hints = {
442+ ('Categorical' , ('b' , ('mir4' , 'mir1' , 'mir2' ), (), False )):
443+ [('Rename' , ('disease bmir' ,))],
444+ ('Categorical' , ('c' , ('mir4' , 'mir1' , 'mir2' ), (), False )):
445+ [('Rename' , ('disease mirs' ,))],
446+ ('Categorical' , ('a' , ('mir1' , 'mir4' , 'mir2' ), (), False )):
447+ [('Rename' , ('disease mir' ,))],
448+ }
449+ widget = self .create_widget (OWEditDomain , stored_settings = settings )
450+ self .assertEqual (widget ._domain_change_hints , migrated_hints )
451+ # order matters
452+ self .assertEqual (list (widget ._domain_change_hints ), list (migrated_hints ))
453+ self .assertEqual (widget .output_table_name , "far" )
454+
455+ def test_migrate_settings_2_to_3_realworld (self ):
456+ settings = {
457+ 'controlAreaVisible' : True ,
458+ '__version__' : 2 ,
459+ 'context_settings' : [Context (
460+ values = {
461+ '_domain_change_store' :
462+ ({('Real' , ('sepal length' , (1 , 'f' ), (), False )):
463+ [('AsString' , ())],
464+ ('Real' , ('sepal width' , (1 , 'f' ), (), False )):
465+ [('AsTime' , ()), ('StrpTime' , ('Detect automatically' , None , 1 , 1 ))],
466+ ('Real' , ('petal width' , (1 , 'f' ), (), False )):
467+ [('Annotate' , ((('a' , 'b' ),),))]}, - 2 ),
468+ '_merge_dialog_settings' : ({}, - 4 ),
469+ '_selected_item' : (('petal width' , 2 ), - 2 ),
470+ 'output_table_name' : ('' , - 2 ),
471+ '__version__' : 2 },
472+ attributes = {'sepal length' : 2 , 'sepal width' : 2 ,
473+ 'petal length' : 2 , 'petal width' : 2 , 'iris' : 1 },
474+ metas = {}
475+ )]
476+ }
477+ widget = self .create_widget (OWEditDomain , stored_settings = settings )
478+ self .assertEqual (
479+ widget ._domain_change_hints ,
480+ {('Real' , ('sepal length' , (1 , 'f' ), (), False )):
481+ [('AsString' , ())],
482+ ('Real' , ('sepal width' , (1 , 'f' ), (), False )):
483+ [('AsTime' , ()),
484+ ('StrpTime' , ('Detect automatically' , None , 1 , 1 ))],
485+ ('Real' , ('petal width' , (1 , 'f' ), (), False )):
486+ [('Annotate' , ((('a' , 'b' ),),))]}
487+ )
488+
489+ def test_migrate_settings_name_2_to_3 (self ):
490+ settings = {
491+ '__version__' : 2 ,
492+ 'context_settings' :
493+ [Context (values = {
494+ '_domain_change_store' : ({}, - 2 ),
495+ 'output_table_name' : ('boo' , - 2 ),
496+ '__version__' : 2 }),
497+ Context (values = {
498+ '_domain_change_store' : ({}, - 2 ),
499+ 'output_table_name' : ('far' , - 2 ),
500+ '__version__' : 2 }),
501+ Context (values = {
502+ '_domain_change_store' : ({}, - 2 ),
503+ 'output_table_name' : ('' , - 2 ),
504+ '__version__' : 2 }),
505+ Context (values = {
506+ '_domain_change_store' : ({}, - 2 ),
507+ '__version__' : 2 })
508+ ]
509+ }
510+ widget = self .create_widget (OWEditDomain , stored_settings = settings )
511+ self .assertEqual (widget .output_table_name , "far" )
512+
341513
342514class TestEditors (GuiTest ):
343515 def test_variable_editor (self ):
0 commit comments