def test_private_events(self): event_log = [] def record(context): event_log.append((context.obj, context.action, context.val)) p = odml.Property(name="p", value="1") p.add_change_handler(record) p.value = "2" p.value = "1" log1 = event_log event_log = [] pp = proxy.PropertyProxy(p) pp.value = "2" pp.value = "1" self.assertEqual(log1, event_log) p.remove_change_handler(record) pp.add_change_handler(record) event_log = [] pp.value = "2" pp.value = "1" self.assertEqual(log1, event_log)
def test_section_events(self): s = odml.Section("sec1") p = odml.Property(name="p", value="1") s.append(p) event_log = [] def record(context): event_log.append((context.obj, context.action, context.val)) s.add_change_handler(record) p.value = "2" p.value = "1" log1 = event_log event_log = [] s.remove_change_handler(record) ps = proxy.NonexistantSection("psec") pp = proxy.PropertyProxy(p) ps.append(pp) ps.add_change_handler(record) p.value = "2" p.value = "1" self.assertEqual(log1, event_log)
def test_proxy_equality(self): p = odml.Property(name="p", value="1") pp = proxy.PropertyProxy(p) self.assertTrue(p == pp) s = odml.Section(name="sec1") ps = proxy.MappedSection(s) s.append(p) self.assertEqual(s, ps)
def test_section_proxy(self): s = odml.Section("sec1") p = odml.Property(name="p", value="1") s.append(p) ps = proxy.MappedSection(s) # forward attributes ps.name = "sec2" self.assertEqual(s.name, "sec2") p2 = odml.Property(name="p2", value="2") # append to proxy section, creates a proxy in ps # and the original object in s ps.append(p2) self.assertIn(p2, s) self.assertIn(p2, ps) self.assertIs(s.contains(p2), p2) self.assertIsInstance(ps.contains(p2), proxy.Proxy) # removing from proxy section, removes both ps.remove(p2) self.assertNotIn(p2, s) self.assertNotIn(p2, ps) # appending to section, creates a proxy in ps s.append(p2) self.assertIn(p2, s) self.assertIn(p2, ps) self.assertIs(s.contains(p2), p2) self.assertIsInstance(ps.contains(p2), proxy.Proxy) # removing removes from ps too s.remove(p2) self.assertNotIn(p2, s) self.assertNotIn(p2, ps) # appending creates in both, removing in ps removes in both s.append(p2) ps.remove(p2) self.assertNotIn(p2, s) self.assertNotIn(p2, ps) # append a proxy to ps, both original and proxy compare to # be 'in' ps pp = proxy.PropertyProxy(p) # you can use proxy_append to add an explicit proxy obj (without affecting # the original section) or you can append the object to the original section # so that the proxy object is created in the proxy section, too ps.proxy_append(pp) # this one is only in ps self.assertIn(pp, ps) self.assertIn(p, ps) # as p == pp, this also holds true # even if the name is changed ps.name = "p3" self.assertEqual(p.name, "p") # does not change the name of p self.assertEqual(ps.name, "p3") # but the one of ps self.assertIn(pp, ps) # both are in ps though self.assertIn(p, ps) # and we can remove it again ps.remove(p) self.assertNotIn(p, ps) self.assertNotIn(pp, ps) self.assertNotIn(p, s) s2 = odml.Section("sec3") # a mapped section added to another mapped section # will only appear there ps2 = proxy.MappedSection(s2) ps.proxy_append(ps2) self.assertIn(ps2, ps) self.assertIn(s2, ps) self.assertNotIn(s2, s) # and we can remove it again ps.remove(s2) self.assertNotIn(ps2, ps)
def create_property_mapping(sec, prop): """ map a property to its destination place using the mapping rules (see test/mapping.py) Note: all sections of the document need already to be mapped """ msec = sec._active_mapping mprop = proxy.PropertyProxy(prop) mprop._section = None prop._active_mapping = mprop mapping = prop.mapped_object if mapping is None: # easy case: just proxy the property msec.proxy_append(mprop) return mprop.name = mapping.name dst_type = mapping._section.type # rule 4c: target-type == section-type # copy attributes, keep property if dst_type == msec.type: msec.proxy_append(mprop) return mprop # rule 4d: one child has the type child = msec.find_related(type=dst_type, siblings=False, parents=False, findAll=True) if child is None: # rule 4e: a sibling has the type sibling = msec.find_related(type=dst_type, children=False, parents=False) if sibling is not None: rel = sibling.find_related(type=msec.type, findAll=True) if len(rel) > 1: # rule 4e2: create a subsection linked to the sibling # TODO set repository and other attributes? child = proxy.NonexistantSection(sibling.name, sibling.type) child.proxy_append(mprop) msec.proxy_append(child) # TODO the link will have trouble to be resolved, as the # nonexistant section does not allow to create any attributes in it # as it cannot be proxied child._link = sibling.get_path() return mprop # rule 4e1: exactly one relation for sibling child = sibling # once we found the target section, the code stays the same else: # rule 4f: no sibling, create a new section # TODO set repository and other attributes? child = proxy.NonexistantSection(mapping._section.name, dst_type) msec.proxy_append(child) elif len(child) > 1: raise MappingError("""Your data organisation does not make sense, there are %d children of type '%s'. Don't know how to handle.""" % (len(child), dst_type)) else: # exactly one child found child = child[0] # corner-case: we are remapping and/or the section already contains a property # with the same name # however this will also hold true, if multiple properties map to the same target # for now live with it being there multiple times (TODO) obj = child.contains(mprop) if obj is not None: pass #child.proxy_remove(obj) child.proxy_append(mprop) return mprop