Repository: yt-dlp/yt-dlp
File: yt_dlp/utils.py (Python)

Code before:

def get_element_by_id(id, html, return_content=True):
    """Return the content or the tag with the specified ID in the passed HTML document"""
    return get_element_by_attribute('id', id, html, return_content=return_content)


def get_element_by_class(class_name, html, return_content=True):
    """Return the content or the first tag with the specified class in the passed HTML document"""
    retval = get_elements_by_class(class_name, html, return_content)
    return retval[0] if retval else None


def get_element_by_attribute(attribute, value, html, escape_value=True, return_content=True):
    retval = get_elements_by_attribute(attribute, value, html, escape_value, return_content)
    return retval[0] if retval else None


def get_elements_by_class(class_name, html, return_content=True):
    """Return the content or all tags with the specified class in the passed HTML document as a list"""
    return get_elements_by_attribute(
        'class', r'[^\'"]*\b%s\b[^\'"]*' % re.escape(class_name),
        html, escape_value=False, return_content=return_content)


def get_elements_by_attribute(attribute, value, html, escape_value=True, return_content=True):
    """Return the content or the tag with the specified attribute in the passed HTML document"""

    value = re.escape(value) if escape_value else value

    retlist = []
    for m in re.finditer(r'''(?xs)
        <(?P<tag>[a-zA-Z0-9:._-]+)
         (?:\s+[a-zA-Z0-9:._-]+(?:=[a-zA-Z0-9:._-]*|="[^"]*"|='[^']*'|))*?
         \s+%s=['"]?%s['"]?
         (?:\s+[a-zA-Z0-9:._-]+(?:=[a-zA-Z0-9:._-]*|="[^"]*"|='[^']*'|))*?
        \s*>
    ''' % (re.escape(attribute), value), html):
        whole, content = get_first_element_by_tag(m.group('tag'), html[m.start():])

        if return_content:
            res = unescapeHTML(re.sub(r'(?s)^(?P<q>["\'])(?P<_>.*)(?P=q)$', r'\g<_>', content))
        else:
            res = whole

        retlist.append(res)

    return retlist


class HTMLBreakOnClosingTagException(Exception):
    pass

Review comment (suggestion):
changing return value entirely based on an argument is generally bad practice. Better to have separate functions for it. Maybe `get_element_html_by_class` etc. You can have a `get_elements_text_and_html_by_attribute` that returns `text, whole` over which everything else can be wrapped

Code after:

def get_element_by_id(id, html):
    """Return the content of the tag with the specified ID in the passed HTML document"""
    return get_element_by_attribute('id', id, html)


def get_element_html_by_id(id, html):
    """Return the html of the tag with the specified ID in the passed HTML document"""
    return get_element_html_by_attribute('id', id, html)


def get_element_by_class(class_name, html):
    """Return the content of the first tag with the specified class in the passed HTML document"""
    retval = get_elements_by_class(class_name, html)
    return retval[0] if retval else None


def get_element_html_by_class(class_name, html):
    """Return the html of the first tag with the specified class in the passed HTML document"""
    retval = get_elements_html_by_class(class_name, html)
    return retval[0] if retval else None


def get_element_by_attribute(attribute, value, html, escape_value=True):
    retval = get_elements_by_attribute(attribute, value, html, escape_value)
    return retval[0] if retval else None


def get_element_html_by_attribute(attribute, value, html, escape_value=True):
    retval = get_elements_html_by_attribute(attribute, value, html, escape_value)
    return retval[0] if retval else None


def get_elements_by_class(class_name, html):
    """Return the content of all tags with the specified class in the passed HTML document as a list"""
    return get_elements_by_attribute(
        'class', r'[^\'"]*\b%s\b[^\'"]*' % re.escape(class_name),
        html, escape_value=False)


def get_elements_html_by_class(class_name, html):
    """Return the html of all tags with the specified class in the passed HTML document as a list"""
    return get_elements_html_by_attribute(
        'class', r'[^\'"]*\b%s\b[^\'"]*' % re.escape(class_name),
        html, escape_value=False)


def get_elements_by_attribute(*args, **kwargs):
    """Return the content of the tag with the specified attribute in the passed HTML document"""
    return [content for content, _ in get_elements_text_and_html_by_attribute(*args, **kwargs)]