def get_members(cls, member_class=None, is_member=None, sort_key=None, _parameter=None):
    """
        Collect all class level attributes matching the given criteria.

        :param class member_class: Class(es) to collect
        :param is_member: Function to determine if an object should be collected
        :param sort_key: Function to invoke on members to obtain ordering (Default is to use ordering from `creation_ordered`)

        :type is_member: (object) -> bool
        :type sort_key: (object) -> object
    """
    if member_class is None and is_member is None:
        raise TypeError("get_members either needs a member_class parameter or an is_member check function (or both)")

    members = OrderedDict()
    for base in cls.__bases__:
        if _parameter is None:
            inherited_members = get_members(base, member_class=member_class, is_member=is_member, sort_key=sort_key)
        else:
            # When user by @declarative, only traverse up the class inheritance to the decorated class.
            inherited_members = get_declared(base, _parameter)
        members.update(inherited_members)

    def generate_member_bindings():
        for name in cls.__dict__:
            if name.startswith('__'):
                continue
            obj = getattr(cls, name)
            if member_class is not None and isinstance(obj, member_class):
                yield name, obj
            elif is_member is not None and is_member(obj):
                yield name, obj
            elif type(obj) is tuple and len(obj) == 1 and isinstance(obj[0], member_class):
                raise TypeError("'%s' is a one-tuple containing what we are looking for.  Trailing comma much?  Don't... just don't." % name)  # pragma: no mutate

    bindings = generate_member_bindings()

    if sort_key is not None:
        try:
            sorted_bindings = sorted(bindings, key=lambda x: sort_key(x[1]))
        except AttributeError:
            if sort_key is default_sort_key:
                raise TypeError('Missing member ordering definition. Use @creation_ordered or specify sort_key')
            else:  # pragma: no covererage
                raise
        members.update(sorted_bindings)
    else:
        members.update(bindings)

    return members
Collect all class level attributes matching the given criteria.

        :param class member_class: Class(es) to collect
        :param is_member: Function to determine if an object should be collected
        :param sort_key: Function to invoke on members to obtain ordering (Default is to use ordering from `creation_ordered`)

        :type is_member: (object) -> bool
        :type sort_key: (object) -> object