# Path: rebulk/debug.py
# def defined_at():
#     """
#     Get definition location of a pattern or a match (outside of rebulk package).
#     :return:
#     :rtype:
#     """
#     if DEBUG:
#         frame = inspect.currentframe()
#         while frame:
#             try:
#                 if frame.f_globals['__package__'] != __package__:
#                     break
#             except KeyError:  # pragma:no cover
#                 # If package is missing, consider we are in. Workaround for python 3.3.
#                 break
#             frame = frame.f_back
#         ret = Frame(frame.f_lineno,
#                     frame.f_globals.get('__package__'),
#                     frame.f_globals.get('__name__'),
#                     frame.f_code.co_filename)
#         del frame
#         return ret
# 
# Path: rebulk/loose.py
# def ensure_list(param):
#     """
#     Retrieves a list from given parameter.
# 
#     :param param:
#     :type param:
#     :return:
#     :rtype:
#     """
#     if not param:
#         param = []
#     elif not is_iterable(param):
#         param = [param]
#     return param
# 
# def filter_index(collection, predicate=None, index=None):
#     """
#     Filter collection with predicate function and index.
# 
#     If index is not found, returns None.
#     :param collection:
#     :type collection: collection supporting iteration and slicing
#     :param predicate: function to filter the collection with
#     :type predicate: function
#     :param index: position of a single element to retrieve
#     :type index: int
#     :return: filtered list, or single element of filtered list if index is defined
#     :rtype: list or object
#     """
#     if index is None and isinstance(predicate, int):
#         index = predicate
#         predicate = None
#     if predicate:
#         collection = collection.__class__(filter(predicate, collection))
#     if index is not None:
#         try:
#             collection = collection[index]
#         except IndexError:
#             collection = None
#     return collection
# 
# Path: rebulk/utils.py
# def is_iterable(obj):
#     """
#     Are we being asked to look up a list of things, instead of a single thing?
#     We check for the `__iter__` attribute so that this can cover types that
#     don't have to be known by this module, such as NumPy arrays.
# 
#     Strings, however, should be considered as atomic values to look up, not
#     iterables.
# 
#     We don't need to check for the Python 2 `unicode` type, because it doesn't
#     have an `__iter__` attribute anyway.
#     """
#     # pylint: disable=consider-using-ternary
#     return hasattr(obj, '__iter__') and not isinstance(obj, str) or isinstance(obj, GeneratorType)


import copy
import itertools
from collections import OrderedDict
from collections import defaultdict
from collections.abc import MutableSequence
from .debug import defined_at
from .loose import ensure_list, filter_index
from .utils import is_iterable
        :rtype: set[Match]
        """
        return filter_index(_BaseMatches._base(self._name_dict[name]), predicate, index)

    def tagged(self, tag, predicate=None, index=None):
        """
        Retrieves a set of Match objects that have the given tag defined.
        :param tag:
        :type tag: str
        :param predicate:
        :type predicate:
        :param index:
        :type index: int
        :return: set of matches
        :rtype: set[Match]
        """
        return filter_index(_BaseMatches._base(self._tag_dict[tag]), predicate, index)

    def starting(self, start, predicate=None, index=None):
        """
        Retrieves a set of Match objects that starts at given index.
        :param start: the starting index
        :type start: int
        :param predicate:
        :type predicate:
        :param index:
        :type index: int
        :return: set of matches
        :rtype: set[Match]
        """

# Path: rebulk/debug.py
# def defined_at():
#     """
#     Get definition location of a pattern or a match (outside of rebulk package).
#     :return:
#     :rtype:
#     """
#     if DEBUG:
#         frame = inspect.currentframe()
#         while frame:
#             try:
#                 if frame.f_globals['__package__'] != __package__:
#                     break
#             except KeyError:  # pragma:no cover
#                 # If package is missing, consider we are in. Workaround for python 3.3.
#                 break
#             frame = frame.f_back
#         ret = Frame(frame.f_lineno,
#                     frame.f_globals.get('__package__'),
#                     frame.f_globals.get('__name__'),
#                     frame.f_code.co_filename)
#         del frame
#         return ret
# 
# Path: rebulk/loose.py
# def ensure_list(param):
#     """
#     Retrieves a list from given parameter.
# 
#     :param param:
#     :type param:
#     :return:
#     :rtype:
#     """
#     if not param:
#         param = []
#     elif not is_iterable(param):
#         param = [param]
#     return param
# 
# def filter_index(collection, predicate=None, index=None):
#     """
#     Filter collection with predicate function and index.
# 
#     If index is not found, returns None.
#     :param collection:
#     :type collection: collection supporting iteration and slicing
#     :param predicate: function to filter the collection with
#     :type predicate: function
#     :param index: position of a single element to retrieve
#     :type index: int
#     :return: filtered list, or single element of filtered list if index is defined
#     :rtype: list or object
#     """
#     if index is None and isinstance(predicate, int):
#         index = predicate
#         predicate = None
#     if predicate:
#         collection = collection.__class__(filter(predicate, collection))
#     if index is not None:
#         try:
#             collection = collection[index]
#         except IndexError:
#             collection = None
#     return collection
# 
# Path: rebulk/utils.py
# def is_iterable(obj):
#     """
#     Are we being asked to look up a list of things, instead of a single thing?
#     We check for the `__iter__` attribute so that this can cover types that
#     don't have to be known by this module, such as NumPy arrays.
# 
#     Strings, however, should be considered as atomic values to look up, not
#     iterables.
# 
#     We don't need to check for the Python 2 `unicode` type, because it doesn't
#     have an `__iter__` attribute anyway.
#     """
#     # pylint: disable=consider-using-ternary
#     return hasattr(obj, '__iter__') and not isinstance(obj, str) or isinstance(obj, GeneratorType)


# Path: rebulk/match.py
import copy
import itertools
from collections import OrderedDict
from collections import defaultdict
from collections.abc import MutableSequence
from .debug import defined_at
from .loose import ensure_list, filter_index
from .utils import is_iterable

        :rtype: set[Match]
        """
        return filter_index(_BaseMatches._base(self._name_dict[name]), predicate, index)

    def tagged(self, tag, predicate=None, index=None):
        """
        Retrieves a set of Match objects that have the given tag defined.
        :param tag:
        :type tag: str
        :param predicate:
        :type predicate:
        :param index:
        :type index: int
        :return: set of matches
        :rtype: set[Match]
        """
        return filter_index(_BaseMatches._base(self._tag_dict[tag]), predicate, index)

    def starting(self, start, predicate=None, index=None):
        """
        Retrieves a set of Match objects that starts at given index.
        :param start: the starting index
        :type start: int
        :param predicate:
        :type predicate:
        :param index:
        :type index: int
        :return: set of matches
        :rtype: set[Match]
        """

        return filter_index(_BaseMatches._base(self._start_dict[start]), predicate, index)