author Sylvain Thénault <>
Thu, 30 Mar 2017 13:53:01 +0200
changeset 2555 0ae7957cf9e3
parent 2526 d3dee90b9183
child 2578 056f484b6294
child 2579 3616158ae8e4
permissions -rw-r--r--
Provide a way to control the compound graph useful for e.g. the saem_ref cube that introduces some entity types (Activity) which would be shared by different compound graph while we want it to be skipped.

# copyright 2016-2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact --
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
# You should have received a copy of the GNU Lesser General Public License along
# with this program. If not, see <>.
"""cubicweb-seda application package

Data Exchange Standard for Archival
from functools import partial

from cubicweb_compound import skip_rtypes_set, CompositeGraph

# data structure allowing control of the compound graph:
# SEDAArchiveTransferGraph.keywords['skipetypes'].append('SomeEtype')
# SEDAArchiveTransferGraph.keywords['skiprtypes'].append('some_rtype')
SEDAArchiveTransferGraph = partial(CompositeGraph, skipetypes=[], skiprtypes=[])

def seda_profile_container_def(schema):
    """Define container for SEDAArchiveTransfer, as a list of (etype, parent_rdefs)."""
    graph = SEDAArchiveTransferGraph(schema)
    return [(child, set(relinfo))
            for child, relinfo in graph.parent_structure('SEDAArchiveTransfer').items()]

def iter_external_rdefs(eschema, skip_rtypes=skip_rtypes_set(['container'])):
    """Return an iterator on (rdef, role) of external relations from entity schema (i.e.
    non-composite relations).
    for rschema, targets, role in eschema.relation_definitions():
        if rschema in skip_rtypes:
        for target_etype in targets:
            rdef = eschema.rdef(rschema, role, target_etype)
            if rdef.composite:
            yield rdef, role

def iter_all_rdefs(schema, container_etype):
    """Return an iterator on (rdef, role) of all relations of the compound graph starting from the
    given entity type, both internal (composite) and external (non-composite).
    graph = SEDAArchiveTransferGraph(schema)
    stack = [container_etype]
    visited = set(stack)
    while stack:
        etype = stack.pop()
        for (rtype, role), targets in graph.child_relations(etype):
            rschema = schema.rschema(rtype)
            for target in targets:
                if role == 'subject':
                    rdef = rschema.rdefs[(etype, target)]
                    rdef = rschema.rdefs[(target, etype)]
                yield rdef, role

                if target not in visited:
        for rdef, role in iter_external_rdefs(schema[etype]):
            yield rdef, role