def create_dangling(name: str, vault_name: str,
                    all_communities: [str]) -> Node:
    n = Node(CAT_DANGLING,
             name=escape_cypher(name),
             community=all_communities.index(CAT_DANGLING),
             obsidian_url=escape_cypher(obsidian_url(name, vault_name)))
    n[PROP_VAULT] = vault_name
    return n
def add_rels_between_nodes(rels, src_node, trgt_node,
                           subgraph: [Relationship]):
    # Adds all relations between src node and trgt node as described in rels to subgraph
    for rel in rels:
        properties = {}
        for property, value in rel.properties.items():
            properties[property] = escape_cypher(str(value))
        subgraph.append(
            Relationship(src_node, escape_cypher(rel.type), trgt_node,
                         **properties))
Beispiel #3
0
def add_rels_between_nodes(rels, src_node, trgt_node, subgraph):
    # Adds all relations between src node and trgt node as described in rels to subgraph
    for rel in rels:
        properties = {}
        for property, value in rel.properties.items():
            properties[property] = escape_cypher(str(value))
        rel = Relationship(src_node, escape_cypher(rel.type), trgt_node,
                           **properties)
        if subgraph is None:
            subgraph = rel
        else:
            subgraph = subgraph | rel
    return subgraph
 def _on_deleted(event):
     name = note_name(event.src_path)
     node = self.nodes.match(name=name).first()
     in_rels = self.relationships.match([None, node])
     if len(in_rels) > 0:
         # If there are still active incoming links, keep the node as a reference
         node.clear()
         node.clear_labels()
         node.add_label(CAT_DANGLING)
         node.name = escape_cypher(name)
         node.obsidian_url = escape_cypher(obsidian_url(name, self.vault_name))
         self._clear_outgoing(node)
     else:
         self.graph.delete(node)
    def _process_node_on_graph(self, note: Note):
        in_graph = self.nodes.match(name=note.name)
        if len(in_graph) == 0:
            # Create new node
            node = node_from_note(note)
            self.graph.create(node)
            return
        # Update
        node = in_graph.first()
        # Update labels
        node.clear_labels()
        note_tags = map(escape_cypher, note.tags)
        node.update_labels(note_tags)
        for tag in note_tags:
            if tag not in self.tags:
                properties = ['name', 'aliases']
                # TODO: Is this too slow?
                if True:
                    properties.append("content")
                create_index(self.graph, tag, properties)
                self.tags.add(tag)
        # Update properties
        node.clear()
        escaped_properties = {}
        for key, value in note.properties.items():
            escaped_properties[key] = escape_cypher(str(value))
        node.update(escaped_properties)
        self.graph.push(node)

        # Delete active relations
        self._clear_outgoing(node)

        # Insert up-to-date relations
        subgraph = None
        for trgt, rels in note.out_rels.items():
            trgt_node = self.nodes.match(name=trgt)
            if len(trgt_node) == 0:
                trgt_node = Node(CAT_DANGLING, name=escape_cypher(trgt),
                                 obsidian_url=escape_cypher(obsidian_url(trgt, self.vault_name)))
                if subgraph is None:
                    subgraph = trgt_node
                else:
                    subgraph = subgraph | trgt_node
            else:
                trgt_node = trgt_node.first()
            # Possibly refactor this with
            subgraph = add_rels_between_nodes(rels, node, trgt_node, subgraph)
        if subgraph is not None:
            self.graph.create(subgraph)
Beispiel #6
0
def node_from_note(note: Note) -> Node:
    tags = [CAT_NO_TAGS]
    if note.tags:
        tags = list(map(escape_cypher, note.tags))
    properties = {}
    for property, value in note.properties.items():
        properties[property] = escape_cypher(str(value))
    return Node(*tags, **properties)
 def _on_deleted(event):
     if smdc.DEBUG:
         print("On deleted", event.src_path, flush=True)
     name = note_name(event.src_path)
     node = self.nodes.match(name=name).first()
     node_id = node.identity
     in_rels = self.relationships.match([None, node])
     if len(in_rels) > 0:
         # If there are still active incoming links, keep the node as a reference
         node.clear()
         node.clear_labels()
         node.add_label(CAT_DANGLING)
         node.name = escape_cypher(name)
         node.obsidian_url = escape_cypher(
             obsidian_url(name, self.vault_name))
         self._clear_outgoing(node)
     else:
         self.graph.delete(node)
     print(f"onSMDDeletedEvent/{node_id}", flush=True)
def get_community(note: Note, communities: [str], community_type: str):
    if community_type == "tags":
        if note.tags:
            community = escape_cypher(note.tags[0])
        else:
            community = CAT_NO_TAGS
    elif community_type == "folders":
        community = str(Path(note.properties[PROP_PATH]).parent)
        if community not in communities:
            communities.append(community)
    return communities.index(community)
def node_from_note(note: Note, all_tags: [str], all_communities: [str],
                   community_type: str) -> Node:
    tags = [CAT_NO_TAGS]
    if note.tags:
        tags = list(map(escape_cypher, note.tags))
        for tag in tags:
            if tag not in all_tags:
                all_tags.append(tag)
    properties = {}
    for property, value in note.properties.items():
        properties[property] = escape_cypher(str(value))
    properties[PROP_COMMUNITY] = get_community(note, all_communities,
                                               community_type)
    return Node(*tags, **properties)
    def _process_node_on_graph(self, note: Note):
        if smdc.DEBUG:
            print(note, flush=True)
        in_graph = self.nodes.match(**{
            'name': note.name,
            PROP_VAULT: self.vault_name
        })
        if len(in_graph) == 0:
            # Create new node
            node = node_from_note(note, self.tags, self.communities,
                                  self.args.community)
            if smdc.DEBUG:
                print("creating")
                print(node, flush=True)
            self.graph.create(node)
            return
        # Update
        node = in_graph.first()
        if smdc.DEBUG:
            print("updating")
            print(node, flush=True)
        # Update labels
        node.clear_labels()
        note_tags = [CAT_NO_TAGS]
        if note.tags:
            note_tags = list(map(escape_cypher, note.tags))
        node.update_labels(note_tags)
        for tag in note_tags:
            if tag not in self.tags:
                create_index(self.graph, tag)
                self.tags.append(tag)
        # Update properties
        node.clear()
        escaped_properties = {}
        for key, value in note.properties.items():
            escaped_properties[key] = escape_cypher(str(value))
        escaped_properties[PROP_COMMUNITY] = get_community(
            note, self.communities, self.args.community)
        node.update(escaped_properties)
        self.graph.push(node)

        # # Delete active relations
        # self._clear_outgoing(node)

        # Insert up-to-date relations
        rels_to_create = []
        nodes_to_create = []
        not_matched_active_rels = list(
            map(lambda r: r.identity, self.relationships.match([node, None])))
        for trgt, rels in note.out_rels.items():
            trgt_node = self.nodes.match(**{
                'name': trgt,
                PROP_VAULT: self.vault_name
            })
            if len(trgt_node) == 0:
                trgt_node = create_dangling(trgt, self.vault_name, self.tags)
                nodes_to_create.append(trgt_node)
            else:
                trgt_node = trgt_node.first()
            # Possibly refactor this with
            for i, rel in enumerate(rels):
                properties = {}
                for property, value in rel.properties.items():
                    properties[property] = escape_cypher(str(value))
                rel_type = escape_cypher(rel.type)
                found_rel = False
                active_rels = list(
                    filter(lambda r: r.identity in not_matched_active_rels,
                           self.relationships.match([node, None])))
                # Update instead of removing makes sure the relationship has a persistent id
                for active_rel in active_rels:
                    walks = list(walk(active_rel))
                    if type(active_rel
                            ).__name__ == rel_type and walks[2] == trgt_node:
                        # Maybe this can leave dangling properties? But that'' an edge case. Not sure how to clear properties.
                        active_rel.clear()
                        active_rel.update(properties)
                        self.graph.push(active_rel)
                        found_rel = True
                        not_matched_active_rels.remove(active_rel.identity)
                        break
                if not found_rel:
                    rels_to_create.append(
                        Relationship(node, rel_type, trgt_node, **properties))

        if rels_to_create or nodes_to_create:
            self.graph.create(
                Subgraph(nodes=nodes_to_create, relationships=rels_to_create))
        if len(not_matched_active_rels) > 0:
            rels = list(
                filter(lambda r: r.identity in not_matched_active_rels,
                       self.relationships.match([node, None])))
            if len(rels) > 0:
                self.graph.separate(Subgraph(relationships=rels))
            print("onSMDRelDeletedEvent/" +
                  "/".join(map(str, not_matched_active_rels)))