Beispiel #1
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)
            }
Beispiel #2
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)
            }
Beispiel #3
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"])
Beispiel #4
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,
        )
Beispiel #5
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,
        )
Beispiel #6
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)}
Beispiel #7
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
Beispiel #8
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]
Beispiel #9
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))
Beispiel #10
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
Beispiel #11
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
Beispiel #12
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
Beispiel #13
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