from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \ OptionDescription from pickle import dumps, loads def _get_slots(opt): slots = set() for subclass in opt.__class__.__mro__: if subclass is not object: slots.update(subclass.__slots__) return slots def _no_state(opt): for attr in _get_slots(opt): if 'state' in attr: try: getattr(opt, attr) except: pass else: raise Exception('opt should have already attribute {0}'.format(attr)) def _diff_opt(opt1, opt2): attr1 = set(_get_slots(opt1)) attr2 = set(_get_slots(opt2)) diff1 = attr1 - attr2 diff2 = attr2 - attr1 if diff1 != set(): raise Exception('more attribute in opt1 {0}'.format(list(diff1))) if diff2 != set(): raise Exception('more attribute in opt2 {0}'.format(list(diff2))) for attr in attr1: if attr in ['_cache_paths']: continue err1 = False err2 = False val1 = None val2 = None try: val1 = getattr(opt1, attr) except: err1 = True try: val2 = getattr(opt2, attr) except: err2 = True assert err1 == err2 if val1 is None: assert val1 == val2 elif attr == '_children': assert val1[0] == val2[0] for index, _opt in enumerate(val1[1]): assert _opt._name == val2[1][index]._name elif attr == '_requires': assert val1[0][0][0]._name == val2[0][0][0]._name assert val1[0][0][1:] == val2[0][0][1:] elif attr == '_opt': assert val1._name == val2._name elif attr == '_consistencies': # dict is only a cache if isinstance(val1, list): for index, consistency in enumerate(val1): assert consistency[0] == val2[index][0] assert consistency[1]._name == val2[index][1]._name else: assert val1 == val2 def test_diff_opt(): b = BoolOption('b', '') u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}]) #u.impl_add_consistency('not_equal', b) s = SymLinkOption('s', u) o = OptionDescription('o', '', [b, u, s]) o1 = OptionDescription('o1', '', [o]) a = dumps(o1) q = loads(a) _diff_opt(o1, q) _diff_opt(o1.o, q.o) _diff_opt(o1.o.b, q.o.b) _diff_opt(o1.o.u, q.o.u) _diff_opt(o1.o.s, q.o.s) def test_diff_opt_cache(): b = BoolOption('b', '') u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}]) u.impl_add_consistency('not_equal', b) s = SymLinkOption('s', u) o = OptionDescription('o', '', [b, u, s]) o1 = OptionDescription('o1', '', [o]) o1.impl_build_cache() a = dumps(o1) q = loads(a) _diff_opt(o1, q) _diff_opt(o1.o, q.o) _diff_opt(o1.o.b, q.o.b) _diff_opt(o1.o.u, q.o.u) _diff_opt(o1.o.s, q.o.s) def test_no_state_attr(): # all _state_xxx attributes should be deleted b = BoolOption('b', '') u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}]) s = SymLinkOption('s', u) o = OptionDescription('o', '', [b, u, s]) o1 = OptionDescription('o1', '', [o]) a = dumps(o1) q = loads(a) _no_state(q) _no_state(q.o) _no_state(q.o.b) _no_state(q.o.u) _no_state(q.o.s)