Exemplo n.º 1
0
def construct_traversals(root, node, visited, path):
    recurse = lambda neighbor: (
        neighbor
        # no backtracking
        and neighbor not in visited
        and neighbor != node
        # no traveling THROUGH terminal nodes
        and (path[-1] not in terminal_nodes
             if path else neighbor.label not in terminal_nodes)
        and (not path[-1].startswith('_related')
             if path else not neighbor.label.startswith('_related')))

    for edge in Edge._get_edges_with_src(node.__name__):
        neighbor = [n for n in Node.get_subclasses()
                    if n.__name__ == edge.__dst_class__][0]
        if recurse(neighbor):
            construct_traversals(
                root, neighbor, visited+[node], path+[edge.__src_dst_assoc__])

    for edge in Edge._get_edges_with_dst(node.__name__):
        neighbor = [n for n in Node.get_subclasses()
                    if n.__name__ == edge.__src_class__][0]
        if recurse(neighbor):
            construct_traversals(
                root, neighbor, visited+[node], path+[edge.__dst_src_assoc__])

    traversals[root][node.label] = traversals[root].get(node.label) or set()
    traversals[root][node.label].add('.'.join(path))
Exemplo n.º 2
0
def construct_traversals(root, node, visited, path):
    recurse = lambda neighbor: (
        neighbor
        # no backtracking
        and neighbor not in visited and neighbor != node
        # no traveling THROUGH terminal nodes
        and (path[-1] not in terminal_nodes
             if path else neighbor.label not in terminal_nodes) and
        (not path[-1].startswith('_related')
         if path else not neighbor.label.startswith('_related')))

    for edge in Edge._get_edges_with_src(node.__name__):
        neighbor = [
            n for n in Node.get_subclasses()
            if n.__name__ == edge.__dst_class__
        ][0]
        if recurse(neighbor):
            construct_traversals(root, neighbor, visited + [node],
                                 path + [edge.__src_dst_assoc__])

    for edge in Edge._get_edges_with_dst(node.__name__):
        neighbor = [
            n for n in Node.get_subclasses()
            if n.__name__ == edge.__src_class__
        ][0]
        if recurse(neighbor):
            construct_traversals(root, neighbor, visited + [node],
                                 path + [edge.__dst_src_assoc__])

    traversals[root][node.label] = traversals[root].get(node.label) or set()
    traversals[root][node.label].add('.'.join(path))
Exemplo n.º 3
0
def inject_pg_backrefs():
    """Add a dict of links to this class.  Backrefs look like:

    .. code-block::
        { <link name>: {'name': <backref name>, 'src_type': <source type> } }

    """

    for src_label, subschema in dictionary.schema.iteritems():
        for name, link in get_links(subschema).iteritems():
            dst_cls = Node.get_subclass(link['target_type'])
            dst_cls._pg_backrefs[link['backref']] = {
                'name': link['name'],
                'src_type': Node.get_subclass(src_label)
            }
Exemplo n.º 4
0
def inject_pg_backrefs():
    """Add a dict of links to this class.  Backrefs look like:

    .. code-block::
        { <link name>: {'name': <backref name>, 'src_type': <source type> } }

    """

    for src_label, subschema in dictionary.schema.iteritems():
        for name, link in get_links(subschema).iteritems():
            dst_cls = Node.get_subclass(link['target_type'])
            dst_cls._pg_backrefs[link['backref']] = {
                'name': link['name'],
                'src_type': Node.get_subclass(src_label)
            }
Exemplo n.º 5
0
def grant_graph_permissions(engine, roles, grant_users):
    for grant_user in grant_users:
        for cls in Node.get_subclasses() + Edge.get_subclasses():
            stmt = "GRANT {roles} ON TABLE {table} TO {user};".format(
                roles=roles, table=cls.__tablename__, user=grant_user)
            print stmt.strip()
            engine.execute(text("BEGIN;" + stmt + "COMMIT;"))
 def drop_all_tables(cls):
     for scls in Node.__subclasses__():
         try:
             cls.engine.execute("DROP TABLE {} CASCADE"
                                .format(scls.__tablename__))
         except Exception as e:
             cls.logger.warning(e)
Exemplo n.º 7
0
def truncate(engine):
    """
    Remove data from existing tables
    """
    conn = engine.connect()
    for table in Node.get_subclass_table_names():
        if table != Node.__tablename__:
            conn.execute('delete from {}'.format(table))
    for table in Edge.get_subclass_table_names():
        if table != Edge.__tablename__:
            conn.execute('delete from {}'.format(table))

    # Extend this list as needed
    ng_models_metadata = [
        models.versioned_nodes.Base.metadata,
        models.submission.Base.metadata,
        models.redaction.Base.metadata,
        models.qcreport.Base.metadata,
        models.misc.Base.metadata,
    ]

    for meta in ng_models_metadata:
        for table in meta.tables:
            conn.execute("DELETE FROM  {}".format(table))
    conn.close()
 def drop_all_tables(cls):
     for scls in Node.__subclasses__():
         try:
             cls.engine.execute("DROP TABLE {} CASCADE".format(
                 scls.__tablename__))
         except Exception as e:
             cls.logger.warning(e)
Exemplo n.º 9
0
def create_indexes(host, user, password, database):
    print("Creating indexes")
    engine = create_engine("postgres://{user}:{pwd}@{host}/{db}".format(
        user=user, host=host, pwd=password, db=database))
    index = lambda t, c: ["CREATE INDEX ON {} ({})".format(t, x) for x in c]
    for scls in Node.get_subclasses():
        tablename = scls.__tablename__
        list(map(engine.execute, index(tablename, ["node_id"])))
        list(
            map(
                engine.execute,
                [
                    "CREATE INDEX ON {} USING gin (_sysan)".format(tablename),
                    "CREATE INDEX ON {} USING gin (_props)".format(tablename),
                    "CREATE INDEX ON {} USING gin (_sysan, _props)".format(
                        tablename),
                ],
            ))
    for scls in Edge.get_subclasses():
        list(
            map(
                engine.execute,
                index(scls.__tablename__,
                      ["src_id", "dst_id", "dst_id, src_id"]),
            ))
Exemplo n.º 10
0
def set_row_type(row):
    """Get the class for a row dict, setting 'type'. Coerce '' -> None."""
    row["type"] = row.get("type", None)
    if not row["type"]:
        row.pop("type")
        return None
    return Node.get_subclass(row["type"])
Exemplo n.º 11
0
def load_edges():
    """Add a dictionry of links from this class

    { <link name>: {'backref': <backref name>, 'type': <source type> } }

    """

    for src_label, subschema in dictionary.schema.iteritems():

        src_cls = Node.get_subclass(src_label)
        if not src_cls:
            raise RuntimeError('No source class labeled {}'.format(src_label))

        for name, link in get_links(subschema).iteritems():
            edge_label = link['label']
            edge_name = parse_edge(
                src_label, name, edge_label, subschema, link)
            src_cls._pg_links[link['name']] = {
                'edge_out': edge_name,
                'dst_type': Node.get_subclass(link['target_type'])
            }

    for src_cls in Node.get_subclasses():
        cache_case = (
            src_cls._dictionary['category'] in RELATED_CASES_CATEGORIES
            or src_cls.label in ['annotation']
        )

        if not cache_case:
            continue

        link = {
            'name': RELATED_CASES_LINK_NAME,
            'multiplicity': 'many_to_one',
            'required': False,
            'target_type': 'case',
            'label': 'relates_to',
            'backref': '_related_{}'.format(src_cls.label),
        }

        edge_name = parse_edge(
            src_cls.label,
            link['name'],
            'relates_to',
            {'id': src_cls.label},
            link,
        )
Exemplo n.º 12
0
def down_transaction(connection):
    logger.info('Migrating async-transactions: down')

    for cls in Node.get_subclasses():
        for index in get_secondary_key_indexes(cls):
            logger.info('Dropping %s', index.name)
            index.drop(connection)
    TX_LOG_PROJECT_ID_IDX.drop(connection)
Exemplo n.º 13
0
def up_transaction(connection):
    logger.info('Migrating async-transactions: up')

    for cls in Node.get_subclasses():
        for index in get_secondary_key_indexes(cls):
            logger.info('Creating %s', index.name)
            index.create(connection)
    TX_LOG_PROJECT_ID_IDX.create(connection)
Exemplo n.º 14
0
 def _clear_tables(self):
     conn = g.engine.connect()
     conn.execute('commit')
     for table in Node.get_subclass_table_names():
         if table != Node.__tablename__:
             conn.execute('delete from {}'.format(table))
     conn.execute('delete from {}'.format('_voided_nodes'))
     conn.close()
Exemplo n.º 15
0
def load_edges():
    """Add a dictionry of links from this class

    { <link name>: {'backref': <backref name>, 'type': <source type> } }

    """

    for src_label, subschema in dictionary.schema.iteritems():

        src_cls = Node.get_subclass(src_label)
        if not src_cls:
            raise RuntimeError('No source class labeled {}'.format(src_label))

        for name, link in get_links(subschema).iteritems():
            edge_label = link['label']
            edge_name = parse_edge(src_label, name, edge_label, subschema,
                                   link)
            src_cls._pg_links[link['name']] = {
                'edge_out': edge_name,
                'dst_type': Node.get_subclass(link['target_type'])
            }

    for src_cls in Node.get_subclasses():
        cache_case = (src_cls._dictionary['category']
                      in RELATED_CASES_CATEGORIES
                      or src_cls.label in ['annotation'])

        if not cache_case:
            continue

        link = {
            'name': RELATED_CASES_LINK_NAME,
            'multiplicity': 'many_to_one',
            'required': False,
            'target_type': 'case',
            'label': 'relates_to',
            'backref': '_related_{}'.format(src_cls.label),
        }

        edge_name = parse_edge(
            src_cls.label,
            link['name'],
            'relates_to',
            {'id': src_cls.label},
            link,
        )
Exemplo n.º 16
0
def execute_for_all_graph_tables(engine, sql, *args, **kwargs):
    """Execute a SQL statment that has a python format variable {table}
    to be replaced with the tablename for all Node and Edge tables

    """
    for cls in Node.__subclasses__() + Edge.__subclasses__():
        _kwargs = dict(kwargs, **{'table': cls.__tablename__})
        statement = sql.format(**_kwargs)
        execute(engine, statement)
Exemplo n.º 17
0
def execute_for_all_graph_tables(driver, sql, *args, **kwargs):
    """Execute a SQL statment that has a python format variable {table}
    to be replaced with the tablename for all Node and Edge tables

    """
    for cls in Node.__subclasses__() + Edge.__subclasses__():
        _kwargs = dict(kwargs, **{"table": cls.__tablename__})
        statement = sql.format(**_kwargs)
        execute(driver, statement)
Exemplo n.º 18
0
def test_node_subclasses(client, submitter, pg_driver_clean, cgci_blgsp):
    post_example_entities_together(client, pg_driver_clean, submitter)
    for cls in Node.get_subclasses():
        print cls
        data = json.dumps(
            {'query': """query Test {{ {} {{ id }}}}""".format(cls.label)})
        r = client.post(path, headers=submitter, data=data)
        print r.data
        assert cls.label in r.json['data'], r.data
Exemplo n.º 19
0
    def export_to_csv(self, data_dir, silent=False):
        node_ids = dict()
        if not silent:
            i = 0
            node_count = self.psqlgraphDriver.nodes().not_sysan({
                'to_delete':
                True
            }).count()
            print("Exporting {n} nodes:".format(n=node_count))
            if node_count != 0:
                pbar = self.start_pbar(node_count)

        edge_file = open(os.path.join(data_dir, 'rels.csv'), 'w')
        print('start\tend\ttype\t', file=edge_file)
        self.create_node_files(data_dir)
        batch_size = 1000
        id_count = 0
        for node_type in Node.get_subclasses():
            nodes = self.psqlgraphDriver.nodes(node_type).not_sysan({
                'to_delete':
                True
            }).yield_per(batch_size)
            for node in nodes:
                self.convert_node(node)
                self.node_to_csv(str(id_count), node)
                node_ids[node.node_id] = id_count
                id_count += 1

                if not silent and node_count != 0:
                    i = self.update_pbar(pbar, i)

            if not silent and node_count != 0:
                self.update_pbar(pbar, node_count)

        self.close_files()
        if not silent:
            i = 0
            edge_count = self.psqlgraphDriver.get_edge_count()
            print("Exporting {n} edges:".format(n=edge_count))
            if edge_count != 0:
                pbar = self.start_pbar(node_count)

        for edge_type in Edge.get_subclasses():
            edges = self.psqlgraphDriver.edges(edge_type).yield_per(batch_size)
            for edge in edges:
                src = node_ids.get(edge.src_id, '')
                dst = node_ids.get(edge.dst_id, '')
                if src != '' and dst != '':
                    edge_file.write(
                        str(src) + '\t' + str(dst) + '\t' + edge.label + '\n')
                if not silent and edge_count != 0:
                    i = self.update_pbar(pbar, i)

        edge_file.close()
        if not silent and edge_count != 0:
            self.update_pbar(pbar, edge_count)
Exemplo n.º 20
0
def construct_traversals_from_node(root_node):

    node_subclasses = Node.get_subclasses()
    traversals = {node.label: set() for node in node_subclasses}

    def recursively_contstruct_traversals(node, visited, path):

        traversals[node.label].add('.'.join(path))

        def should_recurse_on(neighbor):
            """Check whether to recurse on a path."""
            return (
                neighbor
                # no backtracking:
                and neighbor not in visited
                # No 0 length edges:
                and neighbor != node
                # Don't walk back up the tree:
                and is_valid_direction(root_node.label, node, visited, path)
                # no traveling THROUGH terminal nodes:
                and (
                    (path and path[-1] not in terminal_nodes)
                    if path else neighbor.label not in terminal_nodes
                )
            )

        for edge in Edge._get_edges_with_src(node.__name__):
            neighbor_singleton = [
                n for n in node_subclasses
                if n.__name__ == edge.__dst_class__
            ]
            neighbor = neighbor_singleton[0]
            if should_recurse_on(neighbor):
                recursively_contstruct_traversals(
                    neighbor, visited + [node], path + [edge.__src_dst_assoc__]
                )

        for edge in Edge._get_edges_with_dst(node.__name__):
            neighbor_singleton = [
                n for n in node_subclasses
                if n.__name__ == edge.__src_class__
            ]
            neighbor = neighbor_singleton[0]
            if should_recurse_on(neighbor):
                recursively_contstruct_traversals(
                    neighbor, visited + [node], path + [edge.__dst_src_assoc__]
                )

    # Build up the traversals dictionary recursively.
    recursively_contstruct_traversals(root_node, [root_node], [])
    # Remove empty entries.
    traversals = {
        label: paths for label, paths in traversals.iteritems() if bool(paths)
    }
    return traversals
    def tearDownClass(cls):
        """Recreate the database for tests that follow.

        """
        cls.create_all_tables()

        # Re-grant permissions to test user
        for scls in Node.__subclasses__() + Edge.__subclasses__():
            statment = ("GRANT ALL PRIVILEGES ON TABLE {} TO test".format(
                scls.__tablename__))
            cls.engine.execute('BEGIN; %s; COMMIT;' % statment)
Exemplo n.º 22
0
    def tearDownClass(cls):
        """Recreate the database for tests that follow.

        """
        cls.create_all_tables()

        # Re-grant permissions to test user
        for scls in Node.__subclasses__() + Edge.__subclasses__():
            statment = ("GRANT ALL PRIVILEGES ON TABLE {} TO test"
                        .format(scls.__tablename__))
            cls.engine.execute('BEGIN; %s; COMMIT;' % statment)
Exemplo n.º 23
0
 def import_keywords(self):
     nodes = []
     for keyword in self.metadata['keywords'].split(","):
         keyword=keyword.strip()
         node = self.driver.nodes().labels('keyword').props({'value':keyword}).first()
         if not node:
             doc = self.signpost.create()
             node = Node(label='keyword',node_id = doc.did,properties = {'value':keyword})
             self.driver.node_merge(node=node)
             print 'create new keyword %s' % keyword
         nodes.append(node)
     return nodes
Exemplo n.º 24
0
def make_graph_traversal_dict(app, preload=False):
    """Initialize the graph traversal dict.

    If USE_LAZY_TRAVERSE is False, Peregrine server will preload the full dict at start,
    or it will be initialized as an empty dict.

    You may call this method with `preload=True` to manually preload the full dict.
    """
    app.graph_traversals = getattr(app, "graph_traversals", {})
    if preload or not app.config.get("USE_LAZY_TRAVERSE", True):
        for node in Node.get_subclasses():
            _get_paths_from(node, app)
Exemplo n.º 25
0
def construct_traversals_from_node(root_node, app):
    traversals = {node.label: set() for node in Node.get_subclasses()}
    to_visit = [(root_node, [], [])]
    path = []
    while to_visit:
        node, path, visited = to_visit.pop()
        if path:
            path_string = '.'.join(path)
            if path_string in traversals[node.label]:
                continue
            traversals[node.label].add(path_string)
            # stop at terminal nodes
            if path[-1] in terminal_nodes:
                continue
        # Don't walk back up the tree
        if not is_valid_direction(node, visited or [root_node]):
            continue
        name_to_subclass = getattr(app, 'name_to_subclass', None)
        if name_to_subclass is None:
            name_to_subclass = app.name_to_subclass = {
                n.__name__: n
                for n in Node.get_subclasses()
            }
        neighbors_dst = {(name_to_subclass[edge.__dst_class__],
                          edge.__src_dst_assoc__)
                         for edge in Edge._get_edges_with_src(node.__name__)
                         if name_to_subclass[edge.__dst_class__]}
        neighbors_src = {(name_to_subclass[edge.__src_class__],
                          edge.__dst_src_assoc__)
                         for edge in Edge._get_edges_with_dst(node.__name__)
                         if name_to_subclass[edge.__src_class__]}
        to_visit.extend([
            (neighbor, path + [edge], visited + [node])
            for neighbor, edge in neighbors_dst.union(neighbors_src)
            if neighbor not in visited
        ])
    return {
        label: list(paths)
        for label, paths in traversals.iteritems() if paths
    }
Exemplo n.º 26
0
 def _clear_tables(cls):
     conn = cls.g.engine.connect()
     conn.execute('commit')
     for table in Node().get_subclass_table_names():
         if table != Node.__tablename__:
             conn.execute('delete from {}'.format(table))
     for table in Edge.get_subclass_table_names():
         if table != Edge.__tablename__:
             conn.execute('delete from {}'.format(table))
     conn.execute('delete from versioned_nodes')
     conn.execute('delete from _voided_nodes')
     conn.execute('delete from _voided_edges')
     conn.close()
Exemplo n.º 27
0
 def _queries():
     return [
         Query.schema(
             args=ns.NodeSubclassQuery.get_node_query_args(cls),
             name=NodeCountQuery._query_name(cls),
             type=graphene.Int,
         ) for cls in Node.get_subclasses()
     ] + [
         Query.schema(
             args=transaction.TransactionLogQuery._args(),
             name="_{}_count".format(transaction.TransactionLogQuery.name),
             type=graphene.Int,
         )
     ]
Exemplo n.º 28
0
    def get_node_count_result(self, field):
        label = "_".join(self.top.name.split("_")[1:-1])
        cls = Node.get_subclass(label)

        if not cls:
            self.errors.append("Unable to execute {} count".format(label))
            return None

        node_query = ns.NodeSubclassQuery(self.g, None, self.fragments)

        q = self.get_authorized_query(cls)
        for arg in self.top.arguments:
            q = node_query.add_arg_filter(q, arg)
        self.result = {self.top.key: clean_count(q)}
Exemplo n.º 29
0
def inject_pg_edges():
    """Add a dict of ALL the links, to and from, each class

    .. code-block::
        { <link name>: {'backref': <backref name>, 'type': <target type> } }

    """

    def find_backref(link, src_cls):
        """Given the JSON link definition and a source class :param:`src_cls`,
        return the name of the backref

        """

        for prop, backref in link['dst_type']._pg_backrefs.iteritems():
            if backref['src_type'] == cls:
                return prop

    def cls_inject_forward_edges(cls):
        """We should have already added the links that go OUT from this class,
        so let's add them to `_pg_edges`

        :returns: None, cls is mutated

        """

        for name, link in cls._pg_links.iteritems():
            cls._pg_edges[name] = {
                'backref': find_backref(link, cls),
                'type': link['dst_type'],
            }

    def cls_inject_backward_edges(cls):
        """We should have already added the links that go INTO this class,
        so let's add them to `_pg_edges`

        :returns: None, cls is mutated

        """

        for name, backref in cls._pg_backrefs.iteritems():
            cls._pg_edges[name] = {
                'backref': backref['name'],
                'type': backref['src_type'],
            }

    for cls in Node.get_subclasses():
        cls_inject_forward_edges(cls)
        cls_inject_backward_edges(cls)
Exemplo n.º 30
0
    def export_to_csv(self, data_dir, silent=False):
        node_ids = dict()
        if not silent:
            i = 0
            node_count = self.psqlgraphDriver.nodes().not_sysan({'to_delete': True}).count()
            print("Exporting {n} nodes:".format(n=node_count))
            if node_count != 0:
                pbar = self.start_pbar(node_count)

        edge_file = open(os.path.join(data_dir, 'rels.csv'), 'w')
        print('start\tend\ttype\t', file=edge_file)
        self.create_node_files(data_dir)
        batch_size = 1000
        id_count = 0
        for node_type in Node.get_subclasses():
            nodes = self.psqlgraphDriver.nodes(node_type).not_sysan({'to_delete': True}).yield_per(batch_size)
            for node in nodes:
                self.convert_node(node)
                self.node_to_csv(str(id_count), node)
                node_ids[node.node_id] = id_count
                id_count += 1

                if not silent and node_count != 0:
                    i = self.update_pbar(pbar, i)

            if not silent and node_count != 0:
                self.update_pbar(pbar, node_count)

        self.close_files()
        if not silent:
            i = 0
            edge_count = self.psqlgraphDriver.get_edge_count()
            print("Exporting {n} edges:".format(n=edge_count))
            if edge_count != 0:
                pbar = self.start_pbar(node_count)

        for edge_type in Edge.get_subclasses():
            edges = self.psqlgraphDriver.edges(edge_type).yield_per(batch_size)
            for edge in edges:
                src = node_ids.get(edge.src_id, '')
                dst = node_ids.get(edge.dst_id, '')
                if src != '' and dst != '':
                    edge_file.write(str(src)+'\t'+str(dst)+'\t'+edge.label+'\n')
                if not silent and edge_count != 0:
                    i = self.update_pbar(pbar, i)

        edge_file.close()
        if not silent and edge_count != 0:
            self.update_pbar(pbar, edge_count)
Exemplo n.º 31
0
def get_edge_dst(edge, allow_query=False):
    """Return the edge's destination or None.

    """

    if edge.dst:
        dst = edge.dst
    elif edge.dst_id is not None and allow_query:
        dst_class = Node.get_subclass_named(edge.__dst_class__)
        dst = (edge.get_session().query(dst_class).filter(
            dst_class.node_id == edge.dst_id).first())
    else:
        dst = None

    return dst
Exemplo n.º 32
0
def inject_pg_edges():
    """Add a dict of ALL the links, to and from, each class

    .. code-block::
        { <link name>: {'backref': <backref name>, 'type': <target type> } }

    """
    def find_backref(link, src_cls):
        """Given the JSON link definition and a source class :param:`src_cls`,
        return the name of the backref

        """

        for prop, backref in link['dst_type']._pg_backrefs.iteritems():
            if backref['src_type'] == cls:
                return prop

    def cls_inject_forward_edges(cls):
        """We should have already added the links that go OUT from this class,
        so let's add them to `_pg_edges`

        :returns: None, cls is mutated

        """

        for name, link in cls._pg_links.iteritems():
            cls._pg_edges[name] = {
                'backref': find_backref(link, cls),
                'type': link['dst_type'],
            }

    def cls_inject_backward_edges(cls):
        """We should have already added the links that go INTO this class,
        so let's add them to `_pg_edges`

        :returns: None, cls is mutated

        """

        for name, backref in cls._pg_backrefs.iteritems():
            cls._pg_edges[name] = {
                'backref': backref['name'],
                'type': backref['src_type'],
            }

    for cls in Node.get_subclasses():
        cls_inject_forward_edges(cls)
        cls_inject_backward_edges(cls)
Exemplo n.º 33
0
def lookup_node(psql_driver, label, node_id=None, secondary_keys=None):
    """Return a query for nodes by id and secondary keys"""

    cls = Node.get_subclass(label)
    query = psql_driver.nodes(cls)

    if node_id is None and not secondary_keys:
        return query.filter(sqlalchemy.sql.false())

    if node_id is not None:
        query = query.ids(node_id)

    if all(all(keys) for keys in secondary_keys):
        query = query.filter(cls._secondary_keys == secondary_keys)

    return query
Exemplo n.º 34
0
def get_edge_src(edge):
    """Return the edge's source or None.

    Attempts to lookup the node by id if the association proxy is not
    set.

    """

    if edge.src:
        src = edge.src
    elif edge.src_id is not None:
        src_class = Node.get_subclass_named(edge.__src_class__)
        src = (edge.get_session().query(src_class).filter(
            src_class.node_id == edge.src_id).first())
    else:
        src = None
    return src
Exemplo n.º 35
0
def _get_paths_from(src, app):
    if isinstance(src, type) and issubclass(src, Node):
        src_label = src.label
    else:
        src, src_label = Node.get_subclass(src), src
    if src_label not in app.graph_traversals:
        # GOTCHA: lazy initialization is not locked because 1) threading is not enabled
        # in production with uWSGI, and 2) this always generates the same result for the
        # same input so there's no racing condition to worry about
        start = time.time()
        app.graph_traversals[src_label] = construct_traversals_from_node(
            src, app)
        time_taken = int(round(time.time() - start))
        if time_taken > 0.5:
            app.logger.info(
                'Traversed the graph starting from "%s" in %.2f sec',
                src_label, time_taken)
    return app.graph_traversals[src_label]
Exemplo n.º 36
0
    def _run(connection):
        create_all(connection)

        # migrate indexes
        exist_index_uniqueness = dict(
            iter(
                connection.execute("SELECT i.relname, ix.indisunique "
                                   "FROM pg_class i, pg_index ix "
                                   "WHERE i.oid = ix.indexrelid")))
        for cls in Node.__subclasses__() + Edge.__subclasses__():
            for index in cls.__table__.indexes:
                uniq = exist_index_uniqueness.get(index.name, None)
                if uniq is None:
                    # create the missing index
                    index.create(connection)
                elif index.unique != uniq:
                    # recreate indexes whose uniqueness changed
                    index.drop(connection)
                    index.create(connection)
Exemplo n.º 37
0
    def parse_field(self, field, query_class):
        """Lookup the correct query class and add results, errors to this
        instance

        """

        if query_class and hasattr(query_class, 'parse'):
            pass
        elif isinstance(field, FragmentSpread):
            query_class = FragmentQuery
        elif Node.get_subclass(field.name):
            query_class = NodeSubclassQuery
        elif field.name.endswith('_count'):
            query_class = NodeCountQuery

        if query_class:
            self.subquery(query_class, field, self.result)
        else:
            self.errors.append("Cannot query field '{}' on 'Root'".format(
                field.name))
Exemplo n.º 38
0
def update_case_cache_append_only(graph):
    """Server-side update case cache for all entities

    1) Seed direct relationships from level L1 (1 step from case)

    2) Visit all nodes in levels stepping out from case and for each
       entity in that level L, add the related case edges from all
       parents in level L-1 that do not already exist in level L

    """

    cls_levels = get_levels()

    for cls in Node.get_subclasses():
        seed_level_1(graph, cls)

    for level in sorted(cls_levels)[2:]:
        print("\n\nLevel:", level)
        for cls in cls_levels[level]:
            append_cache_from_parents(graph, cls)
Exemplo n.º 39
0
def _munge_properties(source, nested=True):

    # Get properties from schema
    cls = Node.get_subclass(source)
    assert cls, 'No model for {}'.format(source)
    properties = cls.get_pg_properties()
    fields = properties.keys()

    # Add id to document
    id_name = '{}_id'.format(source)
    doc = Dict({id_name: STRING})

    # Add all properties to document
    for field in fields:
        _type = _get_es_type(properties[field] or [])
        # assign the type
        doc[field] = {'type': _type}
        if str(_type) == 'string':
            doc[field]['index'] = 'not_analyzed'
    return doc
Exemplo n.º 40
0
def fake_get_nodes(dids):
    nodes = []
    for did in dids:
        try:
            file_name = files.get(did, {})["data"]["file_name"]
        except ValueError:
            file_name = did
        nodes.append(
            Node(
                node_id=did,
                label="file",
                acl=["open"],
                properties={
                    "file_name": file_name,
                    "file_size": len("fake data for {}".format(did)),
                    "md5sum": "fake_md5sum",
                    "state": "live",
                },
            ))
    return nodes
def create_indexes(host, user, password, database):
    print('Creating indexes')
    engine = create_engine("postgres://{user}:{pwd}@{host}/{db}".format(
        user=user, host=host, pwd=password, db=database))
    index = lambda t, c: ["CREATE INDEX ON {} ({})".format(t, x) for x in c]
    for scls in Node.get_subclasses():
        tablename = scls.__tablename__
        map(engine.execute, index(
            tablename, [
                'node_id',
            ]))
        map(engine.execute, [
            "CREATE INDEX ON {} USING gin (_sysan)".format(tablename),
            "CREATE INDEX ON {} USING gin (_props)".format(tablename),
            "CREATE INDEX ON {} USING gin (_sysan, _props)".format(tablename),
        ])
    for scls in Edge.get_subclasses():
        map(engine.execute, index(
            scls.__tablename__, [
                'src_id',
                'dst_id',
                'dst_id, src_id',
            ]))
Exemplo n.º 42
0
    cache_related_cases_on_delete,
    related_cases_from_cache,
    related_cases_from_parents,
)

logger = get_logger('gdcdatamodel')

# These are properties that are defined outside of the JSONB column in
# the database, inform later code to skip these
excluded_props = ['id', 'type']


# At module load time, evaluate which classes have already been
# registered as subclasses of the abstract bases Node and Edge to
# prevent double-registering
loaded_nodes = [c.__name__ for c in Node.get_subclasses()]
loaded_edges = [c.__name__ for c in Edge.get_subclasses()]


def remove_spaces(s):
    """Returns a stripped string with all of the spaces removed.

    :param str s: String to remove spaces from

    """
    return s.replace(' ', '')


def register_class(cls):
    """Register a class in `globals`.  This allows us to import the ORM
    classes from :mod:`gdcdatamodel.models`
Exemplo n.º 43
0
def EdgeFactory(name, label, src_label, dst_label, src_dst_assoc,
                dst_src_assoc,
                _assigned_association_proxies=defaultdict(set)):
    """Returns an edge class.

    :param name: The name of the edge class.
    :param label: Assigned to ``edge.label``
    :param src_label: The label of the source edge
    :param dst_label: The label of the destination edge
    :param src_dst_assoc:
        The link name i.e. ``src.src_dst_assoc`` returns a list of
        destination type nodes
    :param dst_src_assoc:
        The backref name i.e. ``dst.dst_src_assoc`` returns a list of
        source type nodes
    :param _assigned_association_proxies:
        Don't pass this parameter. This will be used to store what
        links and backrefs have been assigned to the source and
        destination nodes.  This prevents clobbering a backref with a
        link or a link with a backref, as they would be from different
        nodes, should be different relationships, and would have
        different semantic meanings.

    """

    # Correctly format all of the names
    name = remove_spaces(name)
    label = remove_spaces(label)
    src_label = remove_spaces(src_label)
    dst_label = remove_spaces(dst_label)
    src_dst_assoc = remove_spaces(src_dst_assoc)
    dst_src_assoc = remove_spaces(dst_src_assoc)

    # Generate the tablename. If it is too long, it will be hashed and
    # truncated.
    tablename = generate_edge_tablename(src_label, label, dst_label)

    # Lookup the tablenames for the source and destination classes
    src_cls = Node.get_subclass(src_label)
    dst_cls = Node.get_subclass(dst_label)

    # Assert that we're not clobbering link names
    assert dst_src_assoc not in _assigned_association_proxies[dst_label], (
        "Attempted to assign backref '{link}' to node '{node}' but "
        "the node already has an attribute called '{link}'"
        .format(link=dst_src_assoc, node=dst_label))
    assert src_dst_assoc not in _assigned_association_proxies[src_label], (
        "Attempted to assign link '{link}' to node '{node}' but "
        "the node already has an attribute called '{link}'"
        .format(link=src_dst_assoc, node=src_label))

    # Remember that we're adding this link and this backref
    _assigned_association_proxies[dst_label].add(dst_src_assoc)
    _assigned_association_proxies[src_label].add(src_dst_assoc)

    hooks_before_insert = Edge._session_hooks_before_insert + [
        cache_related_cases_on_insert,
    ]

    hooks_before_update = Edge._session_hooks_before_update + [
        cache_related_cases_on_update,
    ]

    hooks_before_delete = Edge._session_hooks_before_delete + [
        cache_related_cases_on_delete,
    ]

    cls = type(name, (Edge,), {
        '__label__': label,
        '__tablename__': tablename,
        '__src_class__': get_class_name_from_id(src_label),
        '__dst_class__': get_class_name_from_id(dst_label),
        '__src_dst_assoc__': src_dst_assoc,
        '__dst_src_assoc__': dst_src_assoc,
        '__src_table__': src_cls.__tablename__,
        '__dst_table__': dst_cls.__tablename__,
        '_session_hooks_before_insert': hooks_before_insert,
        '_session_hooks_before_update': hooks_before_update,
        '_session_hooks_before_delete': hooks_before_delete,
    })

    return cls
Exemplo n.º 44
0
        if recurse(neighbor):
            construct_traversals(
                root, neighbor, visited+[node], path+[edge.__src_dst_assoc__])

    for edge in Edge._get_edges_with_dst(node.__name__):
        neighbor = [n for n in Node.get_subclasses()
                    if n.__name__ == edge.__src_class__][0]
        if recurse(neighbor):
            construct_traversals(
                root, neighbor, visited+[node], path+[edge.__dst_src_assoc__])

    traversals[root][node.label] = traversals[root].get(node.label) or set()
    traversals[root][node.label].add('.'.join(path))


for node in Node.get_subclasses():
    traversals[node.label] = {}
    construct_traversals(node.label, node, [node], [])


def union_subq_without_path(q, *args, **kwargs):
    return q.except_(union_subq_path(q, *args, **kwargs))


def union_subq_path(q, dst_label, post_filters=[]):
    src_label = q.entity().label
    if not traversals.get(src_label, {}).get(dst_label, {}):
        return q
    paths = list(traversals[src_label][dst_label])
    base = q.subq_path(paths.pop(), post_filters)
    while paths: