示例#1
0
 def disambiguate(self):
     gd = GraphDisambiguator()
     gd.find_instances(self)
     self.nodes = TopographicalSorter(
         self.nodes,
         dependencies=lambda n: tuple(
             e.related for e in n.related(backward=False))).sorted()
示例#2
0
    def process(self, normalize=True, prune=True, disambiguate=True):
        # TODO move models' normalize methods to regulator steps (SHARE-1023)
        if normalize:
            self.normalize()

        gd = GraphDisambiguator()

        # TODO move pruning to regulator step (SHARE-1024)
        if prune:
            gd.prune(self)

        if disambiguate:
            gd.find_instances(self)

        self.nodes = TopographicalSorter(self.nodes, dependencies=lambda n: tuple(e.related for e in n.related(backward=False))).sorted()
示例#3
0
    def process(self, normalize=True, prune=True, disambiguate=True):
        if normalize:
            self.normalize()

        gd = GraphDisambiguator()

        if prune:
            gd.prune(self)

        if disambiguate:
            gd.find_instances(self)

        self.nodes = TopographicalSorter(
            self.nodes,
            dependencies=lambda n: tuple(
                e.related for e in n.related(backward=False))).sorted()
示例#4
0
    def __init__(self, data, namespace=None):
        self.nodes = []
        self.relations = {}
        self._lookup = {}
        self.namespace = namespace

        hints, relations = {}, set()
        for blob in copy.deepcopy(data):
            id, type = blob.pop('@id'), blob.pop('@type').lower()

            self._lookup[id, type] = ChangeNode(self,
                                                id,
                                                type,
                                                blob,
                                                namespace=namespace)
            self.relations[self._lookup[id, type]] = set()
            self.nodes.append(self._lookup[id, type])

            for k, v in tuple(blob.items()):
                if isinstance(v,
                              dict) and k != 'extra' and not k.startswith('@'):
                    related = (v.pop('@id'), v.pop('@type').lower())
                    hints[(id, type), related] = k
                    relations.add(((id, type), related))
                    blob.pop(k)
                if isinstance(v, list):
                    for rel in v:
                        subject = (rel.pop('@id'), rel.pop('@type').lower())
                        relations.add((subject, (id, type)))
                    blob.pop(k)

        for subject, related in relations:
            try:
                edge = GraphEdge(self._lookup[subject],
                                 self._lookup[related],
                                 hint=hints.get((subject, related)))
            except KeyError as e:
                raise UnresolvableReference(*e.args)

            self.relations[self._lookup[subject]].add(edge)
            self.relations[self._lookup[related]].add(edge)

        self.nodes = TopographicalSorter(
            self.nodes,
            dependencies=lambda n: tuple(
                e.related for e in n.related(backward=False))).sorted()
示例#5
0
    def process(self, normalize=True, prune=True, disambiguate=True):
        if normalize:
            self.normalize()

        gd = GraphDisambiguator()

        if prune:
            gd.prune(self)

        if disambiguate:
            gd.find_instances(self)

        self.nodes = TopographicalSorter(self.nodes, dependencies=lambda n: tuple(e.related for e in n.related(backward=False))).sorted()
示例#6
0
    def __init__(self, data, namespace=None):
        self.nodes = []
        self.relations = {}
        self._lookup = {}
        self.namespace = namespace

        hints, relations = {}, set()
        for blob in copy.deepcopy(data):
            id, type = blob.pop('@id'), blob.pop('@type').lower()

            self._lookup[id, type] = ChangeNode(self, id, type, blob, namespace=namespace)
            self.relations[self._lookup[id, type]] = set()
            self.nodes.append(self._lookup[id, type])

            for k, v in tuple(blob.items()):
                if isinstance(v, dict) and k != 'extra' and not k.startswith('@'):
                    related = (v.pop('@id'), v.pop('@type').lower())
                    hints[(id, type), related] = k
                    relations.add(((id, type), related))
                    blob.pop(k)
                if isinstance(v, list):
                    for rel in v:
                        subject = (rel.pop('@id'), rel.pop('@type').lower())
                        relations.add((subject, (id, type)))
                    blob.pop(k)

        for subject, related in relations:
            try:
                edge = GraphEdge(self._lookup[subject], self._lookup[related], hint=hints.get((subject, related)))
            except KeyError as e:
                raise UnresolvableReference(*e.args)

            self.relations[self._lookup[subject]].add(edge)
            self.relations[self._lookup[related]].add(edge)

        self.nodes = TopographicalSorter(self.nodes, dependencies=lambda n: tuple(e.related for e in n.related(backward=False))).sorted()
示例#7
0
class ChangeGraph:
    def __init__(self, data, namespace=None):
        self.nodes = []
        self.relations = {}
        self._lookup = {}
        self.namespace = namespace

        hints, relations = {}, set()
        for blob in copy.deepcopy(data):
            id, type = blob.pop('@id'), blob.pop('@type').lower()

            self._lookup[id, type] = ChangeNode(self,
                                                id,
                                                type,
                                                blob,
                                                namespace=namespace)
            self.relations[self._lookup[id, type]] = set()
            self.nodes.append(self._lookup[id, type])

            for k, v in tuple(blob.items()):
                if isinstance(v,
                              dict) and k != 'extra' and not k.startswith('@'):
                    related = (v.pop('@id'), v.pop('@type').lower())
                    hints[(id, type), related] = k
                    relations.add(((id, type), related))
                    blob.pop(k)
                if isinstance(v, list):
                    for rel in v:
                        subject = (rel.pop('@id'), rel.pop('@type').lower())
                        relations.add((subject, (id, type)))
                    blob.pop(k)

        for subject, related in relations:
            try:
                edge = GraphEdge(self._lookup[subject],
                                 self._lookup[related],
                                 hint=hints.get((subject, related)))
            except KeyError as e:
                raise UnresolvableReference(*e.args)

            self.relations[self._lookup[subject]].add(edge)
            self.relations[self._lookup[related]].add(edge)

        self.nodes = TopographicalSorter(
            self.nodes,
            dependencies=lambda n: tuple(
                e.related for e in n.related(backward=False))).sorted()

    def prune(self):
        gd = GraphDisambiguator()
        gd.prune(self)
        self.nodes = TopographicalSorter(
            self.nodes,
            dependencies=lambda n: tuple(
                e.related for e in n.related(backward=False))).sorted()

    def disambiguate(self):
        gd = GraphDisambiguator()
        gd.find_instances(self)
        self.nodes = TopographicalSorter(
            self.nodes,
            dependencies=lambda n: tuple(
                e.related for e in n.related(backward=False))).sorted()

    def normalize(self):
        # Freeze nodes to avoid oddities with inserting and removing nodes
        for node in tuple(self.nodes):
            # If a node has been removed dont normalize it
            # Fast check may be wrong if type has changed double check with a slower method
            if not (node.id,
                    node.type) in self._lookup and node not in self.nodes:
                logger.debug('Skipping removed node %s', node)
                continue
            # This feels overly hacky
            if hasattr(node.model, 'normalize'):
                node.model.normalize(node, self)

    def process(self, normalize=True, prune=True, disambiguate=True):
        if normalize:
            self.normalize()

        gd = GraphDisambiguator()

        if prune:
            gd.prune(self)

        if disambiguate:
            gd.find_instances(self)

        self.nodes = TopographicalSorter(
            self.nodes,
            dependencies=lambda n: tuple(
                e.related for e in n.related(backward=False))).sorted()

    def get(self, id, type):
        return self._lookup[(id, type)]

    def create(self, id, type, attrs):
        return self.add(
            ChangeNode(self,
                       id or '_:{}'.format(uuid.uuid4()),
                       type,
                       attrs,
                       namespace=self.namespace))

    def add(self, node):
        node.graph = self
        self.nodes.append(node)
        self.relations[node] = set()
        self._lookup[node.id, node.type] = node
        return node

    def relate(self, subject, related, hint=None):
        edge = GraphEdge(subject, related, hint)
        self.relations[subject].add(edge)
        self.relations[related].add(edge)
        return edge

    def replace(self, source, replacement):
        for edge in tuple(source.related()):
            # NOTE: Order of add & removes matters here due to
            # the hash function of an edge and how sets work
            self.relations[source].remove(edge)
            if edge.subject == source:
                self.relations[edge.related].remove(edge)
                edge.subject = replacement
                self.relations[edge.related].add(edge)
            else:
                self.relations[edge.subject].remove(edge)
                edge.related = replacement
                self.relations[edge.subject].add(edge)
            self.relations[replacement].add(edge)

        return self.remove(source)

    def remove(self, node, cascade=True):
        for edge in tuple(self.relations[node]):
            if edge.subject is node:
                self.relations[edge.related].remove(edge)
            elif cascade:
                self.remove(edge.subject, cascade=True)
            else:
                self.relations[edge.subject].remove(edge)

        self.nodes.remove(node)
        del self.relations[node]
        try:
            del self._lookup[node.id, node.type]
        except KeyError:
            key = next(k for k in self._lookup.keys() if k[0] == node.id)
            logger.warning(
                'Could not find lookup entry for %s. Falling back to %s', node,
                key)
            del self._lookup[key]

    def serialize(self):
        return [
            n.serialize()
            for n in sorted(self.nodes, key=lambda x: x.type + str(x.id))
        ]
示例#8
0
class ChangeGraph:

    def __init__(self, data, namespace=None):
        self.nodes = []
        self.relations = {}
        self._lookup = {}
        self.namespace = namespace

        hints, relations = {}, set()
        for blob in copy.deepcopy(data):
            id, type = blob.pop('@id'), blob.pop('@type').lower()

            self._lookup[id, type] = ChangeNode(self, id, type, blob, namespace=namespace)
            self.relations[self._lookup[id, type]] = set()
            self.nodes.append(self._lookup[id, type])

            for k, v in tuple(blob.items()):
                if isinstance(v, dict) and k != 'extra' and not k.startswith('@'):
                    related = (v.pop('@id'), v.pop('@type').lower())
                    hints[(id, type), related] = k
                    relations.add(((id, type), related))
                    blob.pop(k)
                if isinstance(v, list):
                    for rel in v:
                        subject = (rel.pop('@id'), rel.pop('@type').lower())
                        relations.add((subject, (id, type)))
                    blob.pop(k)

        for subject, related in relations:
            try:
                edge = GraphEdge(self._lookup[subject], self._lookup[related], hint=hints.get((subject, related)))
            except KeyError as e:
                raise UnresolvableReference(*e.args)

            self.relations[self._lookup[subject]].add(edge)
            self.relations[self._lookup[related]].add(edge)

        self.nodes = TopographicalSorter(self.nodes, dependencies=lambda n: tuple(e.related for e in n.related(backward=False))).sorted()

    def prune(self):
        gd = GraphDisambiguator()
        gd.prune(self)
        self.nodes = TopographicalSorter(self.nodes, dependencies=lambda n: tuple(e.related for e in n.related(backward=False))).sorted()

    def disambiguate(self):
        gd = GraphDisambiguator()
        gd.find_instances(self)
        self.nodes = TopographicalSorter(self.nodes, dependencies=lambda n: tuple(e.related for e in n.related(backward=False))).sorted()

    def normalize(self):
        # Freeze nodes to avoid oddities with inserting and removing nodes
        for node in tuple(self.nodes):
            # If a node has been removed dont normalize it
            # Fast check may be wrong if type has changed double check with a slower method
            if not (node.id, node.type) in self._lookup and node not in self.nodes:
                logger.debug('Skipping removed node %s', node)
                continue
            # This feels overly hacky
            if hasattr(node.model, 'normalize'):
                node.model.normalize(node, self)

    def process(self, normalize=True, prune=True, disambiguate=True):
        if normalize:
            self.normalize()

        gd = GraphDisambiguator()

        if prune:
            gd.prune(self)

        if disambiguate:
            gd.find_instances(self)

        self.nodes = TopographicalSorter(self.nodes, dependencies=lambda n: tuple(e.related for e in n.related(backward=False))).sorted()

    def get(self, id, type):
        return self._lookup[(id, type)]

    def create(self, id, type, attrs):
        return self.add(ChangeNode(self, id or '_:{}'.format(uuid.uuid4()), type, attrs, namespace=self.namespace))

    def add(self, node):
        node.graph = self
        self.nodes.append(node)
        self.relations[node] = set()
        self._lookup[node.id, node.type] = node
        return node

    def relate(self, subject, related, hint=None):
        edge = GraphEdge(subject, related, hint)
        self.relations[subject].add(edge)
        self.relations[related].add(edge)
        return edge

    def replace(self, source, replacement):
        for edge in tuple(source.related()):
            # NOTE: Order of add & removes matters here due to
            # the hash function of an edge and how sets work
            self.relations[source].remove(edge)
            if edge.subject == source:
                self.relations[edge.related].remove(edge)
                edge.subject = replacement
                self.relations[edge.related].add(edge)
            else:
                self.relations[edge.subject].remove(edge)
                edge.related = replacement
                self.relations[edge.subject].add(edge)
            self.relations[replacement].add(edge)

        return self.remove(source)

    def remove(self, node, cascade=True):
        for edge in tuple(self.relations[node]):
            if edge.subject is node:
                self.relations[edge.related].remove(edge)
            elif cascade:
                self.remove(edge.subject, cascade=True)
            else:
                self.relations[edge.subject].remove(edge)

        self.nodes.remove(node)
        del self.relations[node]
        try:
            del self._lookup[node.id, node.type]
        except KeyError:
            key = next(k for k in self._lookup.keys() if k[0] == node.id)
            logger.warning('Could not find lookup entry for %s. Falling back to %s', node, key)
            del self._lookup[key]

    def serialize(self):
        return [
            n.serialize()
            for n in sorted(self.nodes, key=lambda x: x.type + str(x.id))
        ]
示例#9
0
 def disambiguate(self):
     gd = GraphDisambiguator()
     gd.find_instances(self)
     self.nodes = TopographicalSorter(self.nodes, dependencies=lambda n: tuple(e.related for e in n.related(backward=False))).sorted()