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

Code before:

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


class HTMLBreakOnClosingTagParser(compat_HTMLParser):
    """
    HTML parser which raises HTMLBreakOnClosingTagException upon reaching the
    closing tag for the first opening tag it has encountered, and can be used
    as a context manager
    """

    def __init__(self):
        self.tagstack = collections.deque()

Review comment (suggestion):
The tests are green again, but this regex does not match such an element:
```html
  <div id="player_div_id"
       data-kwik_image="https://www.megatv.com/wp-content/uploads/2021/10/ΠΕΙΡΑΙΑΣ-1024x450.jpg"
       data-share_url="https://www.megatv.com/2021/10/23/egkainia-gia-ti-nea-skini-omega-tou-dimotikou-theatrou-peiraia/"
       data-kwik_source="https://c98db5952cb54b358365984178fb898a.msvdn.net/vod/gUgEuW3fjIhP/playlist.m3u8"
       data-kwik_theurl="https%3A%2F%2Fwww.megatv.com%2F2021%2F10%2F23%2Fegkainia-gia-ti-nea-skini-omega-tou-dimotikou-theatrou-peiraia&description_url=https%3A%2F%2Fwww.megatv.com%2F2021%2F10%2F23%2Fegkainia-gia-ti-nea-skini-omega-tou-dimotikou-theatrou-peiraia&cust_params=Category%3Dnews%2Cautoplay%26SubCategory%3Dmesimvrino-deltio-eidisen%26Item_Id%3D520979%26Tags%3DMEGA%2CMEGA-%CE%93%CE%95%CE%93%CE%9F%CE%9D%CE%9F%CE%A4%CE%91%2C%CE%93%CE%99%CE%91%CE%9D%CE%9D%CE%97%CE%A3-%CE%9C%CE%A9%CE%A1%CE%91%CE%9B%CE%97%CE%A3%2C%CE%98%CE%95%CE%91%CE%A4%CE%A1%CE%9F%2C%CE%A0%CE%95%CE%99%CE%A1%CE%91%CE%99%CE%91%CE%A3"
       data-kwik_start="true"
       data-kwik_category="news"
       data-kwik_label = "Μεσημβρινό Δελτίο Ειδήσεων: Εγκαίνια για τη νέα σκηνή «Ωμέγα» του δημοτικού θεάτρου Πειραιά"
       data-kwik_subs=""></div>
```

So I'm still looking into it.

Code after:
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)]


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


def get_elements_text_and_html_by_attribute(attribute, value, html, escape_value=True):
    """
    Return the text (content) and the html (whole) of the tag with the specified
    attribute in the passed HTML document
    """