def select(self, selector, _candidate_generator=None):
            """Perform a CSS selection operation on the current element."""
            tokens = selector.split()
            current_context = [self]

            if tokens[-1] in self._selector_combinators:
                raise ValueError(
                    'Final combinator "%s" is missing an argument.' % tokens[-1])
            if self._select_debug:
                print 'Running CSS selector "%s"' % selector
            for index, token in enumerate(tokens):
                if self._select_debug:
                    print ' Considering token "%s"' % token
                recursive_candidate_generator = None
                tag_name = None
                if tokens[index-1] in self._selector_combinators:
                    # This token was consumed by the previous combinator. Skip it.
                    if self._select_debug:
                        print '  Token was consumed by the previous combinator.'
                    continue
                # Each operation corresponds to a checker function, a rule
                # for determining whether a candidate matches the
                # selector. Candidates are generated by the active
                # iterator.
                checker = None

                m = self.attribselect_re.match(token)
                if m is not None:
                    # Attribute selector
                    tag_name, attribute, operator, value = m.groups()
                    checker = self._attribute_checker(operator, attribute, value)

                elif '#' in token:
                    # ID selector
                    tag_name, tag_id = token.split('#', 1)
                    def id_matches(tag):
                        return tag.get('id', None) == tag_id
                    checker = id_matches

                elif '.' in token:
                    # Class selector
                    tag_name, klass = token.split('.', 1)
                    classes = set(klass.split('.'))
                    def classes_match(candidate):
                        return classes.issubset(candidate.get('class', []))
                    checker = classes_match

                elif ':' in token:
                    # Pseudo-class
                    tag_name, pseudo = token.split(':', 1)
                    if tag_name == '':
                        raise ValueError(
                            "A pseudo-class must be prefixed with a tag name.")
                    pseudo_attributes = re.match('([a-zA-Z\d-]+)\(([a-zA-Z\d]+)\)', pseudo)
                    found = []
                    if pseudo_attributes is not None:
                        pseudo_type, pseudo_value = pseudo_attributes.groups()
                        if pseudo_type == 'nth-of-type':
                            try:
                                pseudo_value = int(pseudo_value)
                            except:
                                raise NotImplementedError(
                                    'Only numeric values are currently supported for the nth-of-type pseudo-class.')
                            if pseudo_value < 1:
                                raise ValueError(
                                    'nth-of-type pseudo-class value must be at least 1.')
                            class Counter(object):
                                def __init__(self, destination):
                                    self.count = 0
                                    self.destination = destination

                                def nth_child_of_type(self, tag):
                                    self.count += 1
                                    if self.count == self.destination:
                                        return True
                                    if self.count > self.destination:
                                        # Stop the generator that's sending us
                                        # these things.
                                        raise StopIteration()
                                    return False
                            checker = Counter(pseudo_value).nth_child_of_type
                        else:
                            raise NotImplementedError(
                                'Only the following pseudo-classes are implemented: nth-of-type.')

                elif token == '*':
                    # Star selector -- matches everything
                    pass
                elif token == '>':
                    # Run the next token as a CSS selector against the
                    # direct children of each tag in the current context.
                    recursive_candidate_generator = lambda tag: tag.children
                elif token == '~':
                    # Run the next token as a CSS selector against the
                    # siblings of each tag in the current context.
                    recursive_candidate_generator = lambda tag: tag.next_siblings
                elif token == '+':
                    # For each tag in the current context, run the next
                    # token as a CSS selector against the tag's next
                    # sibling that's a tag.
                    def next_tag_sibling(tag):
                        yield tag.find_next_sibling(True)
                    recursive_candidate_generator = next_tag_sibling

                elif self.tag_name_re.match(token):
                    # Just a tag name.
                    tag_name = token
                else:
                    raise ValueError(
                        'Unsupported or invalid CSS selector: "%s"' % token)

                if recursive_candidate_generator:
                    # This happens when the selector looks like  "> foo".
                    #
                    # The generator calls select() recursively on every
                    # member of the current context, passing in a different
                    # candidate generator and a different selector.
                    #
                    # In the case of "> foo", the candidate generator is
                    # one that yields a tag's direct children (">"), and
                    # the selector is "foo".
                    next_token = tokens[index+1]
                    def recursive_select(tag):
                        if self._select_debug:
                            print '    Calling select("%s") recursively on %s %s' % (next_token, tag.name, tag.attrs)
                            print '-' * 40
                        for i in tag.select(next_token, recursive_candidate_generator):
                            if self._select_debug:
                                print '(Recursive select picked up candidate %s %s)' % (i.name, i.attrs)
                            yield i
                        if self._select_debug:
                            print '-' * 40
                    _use_candidate_generator = recursive_select
                elif _candidate_generator is None:
                    # By default, a tag's candidates are all of its
                    # children. If tag_name is defined, only yield tags
                    # with that name.
                    if self._select_debug:
                        if tag_name:
                            check = "[any]"
                        else:
                            check = tag_name
                        print '   Default candidate generator, tag name="%s"' % check
                    if self._select_debug:
                        # This is redundant with later code, but it stops
                        # a bunch of bogus tags from cluttering up the
                        # debug log.
                        def default_candidate_generator(tag):
                            for child in tag.descendants:
                                if not isinstance(child, Tag):
                                    continue
                                if tag_name and not child.name == tag_name:
                                    continue
                                yield child
                        _use_candidate_generator = default_candidate_generator
                    else:
                        _use_candidate_generator = lambda tag: tag.descendants
                else:
                    _use_candidate_generator = _candidate_generator

                new_context = []
                new_context_ids = set([])
                for tag in current_context:
                    if self._select_debug:
                        print "    Running candidate generator on %s %s" % (
                            tag.name, repr(tag.attrs))
                    for candidate in _use_candidate_generator(tag):
                        if not isinstance(candidate, Tag):
                            continue
                        if tag_name and candidate.name != tag_name:
                            continue
                        if checker is not None:
                            try:
                                result = checker(candidate)
                            except __HOLE__:
                                # The checker has decided we should no longer
                                # run the generator.
                                break
                        if checker is None or result:
                            if self._select_debug:
                                print "     SUCCESS %s %s" % (candidate.name, repr(candidate.attrs))
                            if id(candidate) not in new_context_ids:
                                # If a tag matches a selector more than once,
                                # don't include it in the context more than once.
                                new_context.append(candidate)
                                new_context_ids.add(id(candidate))
                        elif self._select_debug:
                            print "     FAILURE %s %s" % (candidate.name, repr(candidate.attrs))

                current_context = new_context

            if self._select_debug:
                print "Final verdict:"
                for i in current_context:
                    print " %s %s" % (i.name, i.attrs)
            return current_context

        # Old names for backwards compatibility
dataset/ETHPy150Open mtlevolio/pylinkchecker/pylinkchecker/bs4/element.py/Tag.select