def test_needs_container_parent(self): needs_cp = set(eschema.type for eschema in self.schema.entities() if utils.needs_container_parent(eschema)) self.assertEqual([ 'CWAttribute', 'CWRelation', 'CWSourceSchemaConfig', 'Card', 'Folder', 'RQLExpression' ], sorted(needs_cp))
def parent(self): if needs_container_parent(self.entity.e_schema): parent = self.entity.container_parent return parent[0] if parent else None try: rdef = first_parent_rdef(self.entity.e_schema) rtype, role = rdef.rtype.type, neg_role(rdef.composite) except StopIteration: self.debug('ContainerProtocol.parent stopped on %s', self.entity) return None parent = self.entity.related(rtype=rtype, role=role, entities=True) if parent: return parent[0]
def _container_parent_rdefs(self): """Compute a mapping from rtype to subject/object for use by the container hook. The hook will notice when the from/to etypes are in this mapping and compute the effective container_parent relation. """ cprdefs = defaultdict(set) inner_rdefs = self.inner_rdefs for etype in self.etypes: eschema = self.schema[etype] if not utils.needs_container_parent(eschema): continue # let's compute the parent rdefs of this container for parent_rdef in utils.parent_rdefs(eschema): if parent_rdef not in inner_rdefs: continue cprdefs[parent_rdef.rtype.type].add( (parent_rdef.subject.type, parent_rdef.object.type)) return dict(cprdefs)
def define_container(self, schema): """ Produce the necessary schema relations of a container: * (<container_rtype>, etype, cetype) for each container etype * (container_etype, etype, 'CWEType') for each container etype * an optional (if needed) (container_parent, etype, parent etype) """ assert utils.fsschema(schema), \ 'this method is expected to be called only on filesystem schema (in schema.py)' assert not getattr(schema, '_%s_define_container' % self.cetype, False), \ 'this method is expected to be called only once on a schema (in schema.py)' setattr(schema, '_%s_define_container' % self.cetype, True) self.bind(schema) if self.crtype not in schema: # ease pluggability of container in existing applications schema.add_relation_type(RelationType(self.crtype, inlined=True)) cw_schema.META_RTYPES.add(self.crtype) else: logger.warning( '%r is already defined in the schema - you probably want ' 'to let it to the container cube', self.crtype) crschema = schema[self.crtype] cetype_rschema = schema['container_etype'] for etype in self.etypes: # populate <container_rtype> if (etype, self.cetype) not in crschema.rdefs: # checking this will help adding containers to existing applications # and reusing the container rtype schema.add_relation_def( RelationDefinition(etype, self.crtype, self.cetype, cardinality='?*')) else: logger.warning( '%r - %r - %r rdef is already defined in the schema ' '- you probably want to let it to the container cube', etype, self.crtype, self.cetype) # populate container_etype if (etype, 'CWEType') not in cetype_rschema.rdefs: schema.add_relation_def( RelationDefinition(etype, 'container_etype', 'CWEType', cardinality='?*')) # populate container_parent eschema = schema[etype] if utils.needs_container_parent(eschema): cparent_rschema = schema['container_parent'] # we take a list because iterating over the schema while # we're mutating parts of it won't work peschemas = list(utils.parent_eschemas(eschema)) for peschema in peschemas: petype = peschema.type if (etype, petype) in cparent_rschema.rdefs: continue schema.add_relation_def( RelationDefinition(etype, 'container_parent', petype, cardinality='?*'))
def test_needs_container_parent(self): schema = self.vreg.schema for etype in ('Diamond', 'Left', 'Right', 'Mess'): self.assertFalse(utils.needs_container_parent(schema[etype])) self.assertTrue(utils.needs_container_parent(schema['Bottom']))