# Path: breadability/_compat.py
# PY3 = version_info[0] == 3
# def unicode_compatible(cls):
# def to_string(object):
# def to_bytes(object):
# def to_unicode(object):
# def instance_to_bytes(instance):
# def instance_to_unicode(instance):
# 
# Path: breadability/utils.py
# def cached_property(getter):
#     """
#     Decorator that converts a method into memoized property.
#     The decorator works as expected only for classes with
#     attribute '__dict__' and immutable properties.
#     """
#     def decorator(self):
#         key = "_cached_property_" + getter.__name__
# 
#         if not hasattr(self, key):
#             setattr(self, key, getter(self))
# 
#         return getattr(self, key)
# 
#     decorator.__name__ = getter.__name__
#     decorator.__module__ = getter.__module__
#     decorator.__doc__ = getter.__doc__
# 
#     return property(decorator)
# 
# @contextmanager
# def ignored(*exceptions):
#     try:
#         yield
#     except tuple(exceptions):
#         pass


import logging
import re
import chardet
from lxml.etree import ParserError, XMLSyntaxError, tounicode
from lxml.html import HTMLParser, document_fromstring
from ._compat import to_bytes, to_unicode, unicode, unicode_compatible
from .utils import cached_property, ignored



logger = logging.getLogger("breadability")


TAG_MARK_PATTERN = re.compile(to_bytes(r"</?[^>]*>\s*"))
UTF8_PARSER = HTMLParser(encoding="utf8")
CHARSET_META_TAG_PATTERN = re.compile(
    br"""<meta[^>]+charset=["']?([^'"/>\s]+)""",
    re.IGNORECASE
)


def decode_html(html):
    """
    Converts bytes stream containing an HTML page into Unicode.
    Tries to guess character encoding from meta tag of by "chardet" library.
    """
    if isinstance(html, unicode):
        return html

    match = CHARSET_META_TAG_PATTERN.search(html)
    if match:
        declared_encoding = match.group(1).decode("ASCII")
        # proceed unknown encoding as if it wasn't found at all
        with ignored(LookupError):
            return html.decode(declared_encoding, "ignore")

    # try to enforce UTF-8 firstly

# Path: breadability/_compat.py
# PY3 = version_info[0] == 3
# def unicode_compatible(cls):
# def to_string(object):
# def to_bytes(object):
# def to_unicode(object):
# def instance_to_bytes(instance):
# def instance_to_unicode(instance):
# 
# Path: breadability/utils.py
# def cached_property(getter):
#     """
#     Decorator that converts a method into memoized property.
#     The decorator works as expected only for classes with
#     attribute '__dict__' and immutable properties.
#     """
#     def decorator(self):
#         key = "_cached_property_" + getter.__name__
# 
#         if not hasattr(self, key):
#             setattr(self, key, getter(self))
# 
#         return getattr(self, key)
# 
#     decorator.__name__ = getter.__name__
#     decorator.__module__ = getter.__module__
#     decorator.__doc__ = getter.__doc__
# 
#     return property(decorator)
# 
# @contextmanager
# def ignored(*exceptions):
#     try:
#         yield
#     except tuple(exceptions):
#         pass


# Path: breadability/document.py
import logging
import re
import chardet
from lxml.etree import ParserError, XMLSyntaxError, tounicode
from lxml.html import HTMLParser, document_fromstring
from ._compat import to_bytes, to_unicode, unicode, unicode_compatible
from .utils import cached_property, ignored




logger = logging.getLogger("breadability")


TAG_MARK_PATTERN = re.compile(to_bytes(r"</?[^>]*>\s*"))
UTF8_PARSER = HTMLParser(encoding="utf8")
CHARSET_META_TAG_PATTERN = re.compile(
    br"""<meta[^>]+charset=["']?([^'"/>\s]+)""",
    re.IGNORECASE
)


def decode_html(html):
    """
    Converts bytes stream containing an HTML page into Unicode.
    Tries to guess character encoding from meta tag of by "chardet" library.
    """
    if isinstance(html, unicode):
        return html

    match = CHARSET_META_TAG_PATTERN.search(html)
    if match:
        declared_encoding = match.group(1).decode("ASCII")
        # proceed unknown encoding as if it wasn't found at all
        with ignored(LookupError):
            return html.decode(declared_encoding, "ignore")

    # try to enforce UTF-8 firstly

    with ignored(UnicodeDecodeError):