Source code for pybel.struct.filters.node_predicate_builders

# -*- coding: utf-8 -*-

"""Functions for building node predicates."""

from collections import Iterable

from six import string_types

from ...constants import NAME
from ...dsl import BaseEntity

__all__ = [
    'function_inclusion_filter_builder',
    'data_missing_key_builder',
    'build_node_data_search',
    'build_node_graph_data_search',
    'build_node_key_search',
    'build_node_name_search',
]


def function_inclusion_filter_builder(func):
    """Build a filter that only passes on nodes of the given function(s).

    :param func: A BEL Function or list/set/tuple of BEL functions
    :type func: str or iter[str]
    :return: A node filter (graph, node) -> bool
    :rtype: (pybel.BELGraph, BaseEntity) -> bool
    """
    if isinstance(func, string_types):
        return _single_function_inclusion_filter_builder(func)

    elif isinstance(func, Iterable):
        return _collection_function_inclusion_builder(func)

    raise TypeError('Invalid type for argument: {}'.format(func))


def _single_function_inclusion_filter_builder(func):
    """
    :param str func: A BEL function
    :type func: str
    :return: (pybel.BELGraph, BaseEntity) -> bool
    """

    def function_inclusion_filter(graph, node):
        """Passes only for a node that has the enclosed function

        :param BELGraph graph: A BEL Graph
        :param BaseEntity node: A BEL node
        :return: If the node doesn't have the enclosed function
        :rtype: bool
        """
        return node.function == func

    return function_inclusion_filter


def _collection_function_inclusion_builder(funcs):
    """
    :param funcs: A sequence of BEL functions
    :type funcs: iter[str]
    :return: (pybel.BELGraph, BaseEntity) -> bool
    """
    funcs = set(funcs)

    if not funcs:
        raise ValueError('can not build function inclusion filter with empty list of functions')

    def functions_inclusion_filter(graph, node):
        """Passes only for a node that is one of the enclosed functions

        :param BELGraph graph: A BEL Graph
        :param BaseEntity node: A BEL node
        :return: If the node doesn't have the enclosed functions
        :rtype: bool
        """
        return node.function in funcs

    return functions_inclusion_filter


[docs]def data_missing_key_builder(key): """Build a filter that passes only on nodes that don't have the given key in their data dictionary. :param str key: A key for the node's data dictionary :return: A node filter (graph, node) -> bool :rtype: (pybel.BELGraph, BaseEntity) -> bool """ def data_does_not_contain_key(graph, node): """Pass only for a node that doesn't contain the enclosed key in its data dictionary. :param pybel.BELGraph graph: A BEL Graph :param tuple node: A BEL node :return: If the node doesn't contain the enclosed key in its data dictionary :rtype: bool """ return key not in graph.nodes[node] return data_does_not_contain_key
def build_node_graph_data_search(key, data_predicate): """Build a function for testing data associated with the node in the graph. :param str key: The node data dictionary key to check :param data_predicate: The filter to apply to the node data dictionary :type data_predicate: (Any) -> bool :return: A node predicate :rtype: (pybel.BELGraph, BaseEntity) -> bool """ def node_data_filter(graph, node): """Pass if the given node has a given data annotated and passes the contained filter. :type graph: pybel.BELGraph :type node: BaseEntity :return: If the node has the contained key in its data dictionary and passes the contained filter :rtype: bool """ value = graph.nodes[node].get(key) return value is not None and data_predicate(value) return node_data_filter def build_node_name_search(query): """Search nodes' names. Is a thin wrapper around :func:`build_node_key_search` with :data:`pybel.constants.NAME` :param query: The query string or strings to check if they're in the node name :type query: str or iter[str] :return: A node predicate :rtype: (pybel.BELGraph, BaseEntity) -> bool """ return build_node_key_search(query=query, key=NAME)