Skip to content

Commit 359f0b3

Browse files
authored
Merge pull request #1577 from thocevar/context
[FIX] Context settings
2 parents 3b1196a + 6cc9921 commit 359f0b3

File tree

3 files changed

+58
-6
lines changed

3 files changed

+58
-6
lines changed

Orange/widgets/settings.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,10 +659,11 @@ def find_or_create_context(self, widget, *args):
659659
of the context list."""
660660

661661
# First search the contexts that were already used in this widget instance
662-
best_context, best_score = self.find_context(widget.context_settings, args)
662+
best_context, best_score = self.find_context(widget.context_settings, args, move_up=True)
663663
# If the exact data was used, reuse the context
664664
if best_score == self.PERFECT_MATCH:
665665
return best_context, False
666+
666667
# Otherwise check if a better match is available in global_contexts
667668
best_context, best_score = self.find_context(self.global_contexts, args,
668669
best_score, best_context)
@@ -675,7 +676,7 @@ def find_or_create_context(self, widget, *args):
675676
self.add_context(widget.context_settings, context)
676677
return context, best_context is None
677678

678-
def find_context(self, known_contexts, args, best_score=0, best_context=None):
679+
def find_context(self, known_contexts, args, best_score=0, best_context=None, move_up=False):
679680
"""Search the given list of contexts and return the context
680681
which best matches the given args.
681682
@@ -685,7 +686,8 @@ def find_context(self, known_contexts, args, best_score=0, best_context=None):
685686
for i, context in enumerate(known_contexts):
686687
score = self.match(context, *args)
687688
if score == self.PERFECT_MATCH:
688-
self.move_context_up(known_contexts, i)
689+
if move_up:
690+
self.move_context_up(known_contexts, i)
689691
return context, score
690692
if score > best_score: # NO_MATCH is not OK!
691693
best_context, best_score = context, score
@@ -1035,6 +1037,8 @@ def is_valid_item(self, setting, item, attrs, metas):
10351037
Subclasses can override this method to checks data in alternative
10361038
representations.
10371039
"""
1040+
if not isinstance(item, tuple):
1041+
return True
10381042
return self._var_exists(setting, item, attrs, metas)
10391043

10401044

Orange/widgets/tests/test_context_handler.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
from copy import copy
12
from unittest import TestCase
23
from unittest.mock import Mock
3-
from Orange.widgets.settings import ContextHandler, Setting, ContextSetting
4+
from Orange.widgets.settings import ContextHandler, Setting, ContextSetting, Context
45

56
__author__ = 'anze'
67

@@ -11,7 +12,7 @@ class SimpleWidget:
1112
context_setting = ContextSetting(42)
1213

1314

14-
class ContextHandlerTestCase(TestCase):
15+
class TestContextHandler(TestCase):
1516
def test_initialize(self):
1617
handler = ContextHandler()
1718
handler.provider = Mock()
@@ -40,3 +41,30 @@ def test_fast_save(self):
4041
self.assertEqual(context.values['context_setting'], 55)
4142
self.assertEqual(handler.known_settings['context_setting'].default,
4243
SimpleWidget.context_setting.default)
44+
45+
def test_find_or_create_context(self):
46+
widget = SimpleWidget()
47+
handler = ContextHandler()
48+
handler.match = lambda context, i: (context.i == i) * 2
49+
handler.clone_context = lambda context, i: copy(context)
50+
51+
c1, c2, c3, c4, c5, c6, c7, c8, c9 = (Context(i=i)
52+
for i in range(1, 10))
53+
54+
# finding a perfect match in global_contexts should copy it to
55+
# the front of context_settings (and leave globals as-is)
56+
widget.context_settings = [c2, c5]
57+
handler.global_contexts = [c3, c7]
58+
context, new = handler.find_or_create_context(widget, 7)
59+
self.assertEqual(context.i, 7)
60+
self.assertEqual([c.i for c in widget.context_settings], [7, 2, 5])
61+
self.assertEqual([c.i for c in handler.global_contexts], [3, 7])
62+
63+
# finding a perfect match in context_settings should move it to
64+
# the front of the list
65+
widget.context_settings = [c2, c5]
66+
handler.global_contexts = [c3, c7]
67+
context, new = handler.find_or_create_context(widget, 5)
68+
self.assertEqual(context.i, 5)
69+
self.assertEqual([c.i for c in widget.context_settings], [5, 2])
70+
self.assertEqual([c.i for c in handler.global_contexts], [3, 7])

Orange/widgets/tests/test_domain_context_handler.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
Discrete = vartype(DiscreteVariable())
1010

1111

12-
class DomainContextHandlerTestCase(TestCase):
12+
class TestDomainContextHandler(TestCase):
1313
def setUp(self):
1414
self.domain = Domain(
1515
attributes=[ContinuousVariable('c1'),
@@ -235,6 +235,26 @@ def test_open_context_with_no_match(self):
235235
('c2', Continuous), ('d4', Discrete)))
236236
self.assertEqual(context.values['text'], ('u', -2))
237237

238+
def test_filter_value(self):
239+
setting = ContextSetting([])
240+
setting.name = "value"
241+
242+
def test_filter(before_value, after_value):
243+
data = dict(value=before_value)
244+
self.handler.filter_value(setting, data, *self.args)
245+
self.assertIn("value", data)
246+
self.assertEqual(data["value"], after_value)
247+
248+
# filter list values
249+
test_filter([], [])
250+
# When list contains attributes asa tuple of (name, type),
251+
# Attributes not present in domain should be filtered out
252+
test_filter([("d1", Discrete), ("d1", Continuous),
253+
("c1", Continuous), ("c1", Discrete)],
254+
[("d1", Discrete), ("c1", Continuous)])
255+
# All other values in list should remain
256+
test_filter([0, [1, 2, 3], "abcd", 5.4], [0, [1, 2, 3], "abcd", 5.4])
257+
238258
def create_context(self, domain, values):
239259
if not domain:
240260
domain = Domain([])

0 commit comments

Comments
 (0)