<gh_stars>1-10
import logging
from pprintpp import pformat as pf, pprint as pp
from reprlib import Repr
import shutil
import sys
from textwrap import indent, wrap

import sqlparse as sp

from tlbx.object_utils import get_class_vars, get_caller


logging.basicConfig(format="%(message)s")


_repr = Repr()
_repr.maxstring = 60
_repr.maxother = 20
_repr.maxlist = 5
_repr.maxtuple = 5
_repr.maxset = 5
repr = _repr.repr

DEFAULT_TERM_WIDTH = 80


class FontSpecialChars:
    ENDC = "\033[0m"


class FontColors:
    BLACK = "\033[30m"
    RED = "\033[31m"
    GREEN = "\033[32m"
    YELLOW = "\033[33m"
    BLUE = "\033[34m"
    MAGENTA = "\033[35m"
    CYAN = "\033[36m"
    WHITE = "\033[37m"
    NONE = ""  # Will use default terminal coloring


RESERVED_COLORS = [
    "RED",  # errors
    "YELLOW",  # warnings
    "BLACK",  # to avoid conflicts with terminal defaults
    "WHITE",  # to avoid conflicts with terminal defaults
    "NONE",  # to avoid conflicts with terminal defaults
]

COLOR_OPTIONS = sorted(
    [x for x in get_class_vars(FontColors) if x not in RESERVED_COLORS]
)


class FontEffects:
    BOLD = "\033[1m"
    UNDERLINE = "\033[4m"
    INVERTED = "\033[7m"


def get_terminal_width():
    return shutil.get_terminal_size().columns


def get_logging_level(logger=None):
    if (not logger) or (not isinstance(logger, logging.Logger)):
        logger = logging.getLogger()
    return logger.getEffectiveLevel()


def sqlformat(sql, reindent=True, keyword_case=None):
    return sp.format(sql, reindent=reindent, keyword_case=keyword_case)


def format_msg(
    msg, label="parent", indent=None, color=None, autocolor=False, format_func=pf
):
    term_width = get_terminal_width() or DEFAULT_TERM_WIDTH
    effective_width = term_width
    indent_str = None

    if label == "parent":
        label = get_caller()

    if indent is not None:
        if indent == "label":
            assert label, "indent=label but no label given"
            indent_str = " " * (len(label) + 2)
        else:
            indent = int(indent)
            indent_str = " " * indent
        effective_width = (
            max(effective_width - len(indent_str), 0) or DEFAULT_TERM_WIDTH
        )

    if isinstance(format_func, str):
        format_func = globals()[format_func]

    if format_func and format_func != pf:
        msg = format_func(msg)
        if label and not indent:
            msg = "\n" + msg
    elif not isinstance(msg, str):
        msg = pf(msg, width=effective_width)
        if label and not indent:
            msg = "\n" + msg

    if indent is not None:
        lines = msg.splitlines(True)
        msg = "\n".join(["\n".join(wrap(line, effective_width)) for line in lines])
        if indent == "label":
            msg = indent_str.join(msg.splitlines(True))
        else:
            msg = indent_str + indent_str.join(msg.splitlines(True))
            if label:
                msg = "\n" + msg

    if label:
        msg = label.strip() + ": " + msg

    if (not color) and autocolor:
        assert label, "No label provided, can not use autocolor"
        color_index = ord(label[0]) % len(COLOR_OPTIONS)
        color = COLOR_OPTIONS[color_index]

    if color:
        msg = getattr(FontColors, color.upper()) + msg + FontSpecialChars.ENDC

    return msg


def info(msg, label="parent", logger=None, autocolor=True, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.INFO:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(msg, label=label, autocolor=autocolor, **kwargs)
    logger.info(msg)


def dbg(msg, label="parent", logger=None, autocolor=True, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.DEBUG:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(msg, label=label, autocolor=autocolor, **kwargs)
    logger.debug(msg)


def dbgsql(msg, label="parent", logger=None, autocolor=True, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.DEBUG:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(
        msg, label=label, autocolor=autocolor, format_func=sqlformat, **kwargs
    )
    logger.debug(msg)


def warn(msg, label="parent", logger=None, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.WARNING:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(msg, label=label, color="yellow", **kwargs)
    logger.warning(msg)


def error(msg, label="parent", logger=None, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.ERROR:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(msg, label=label, color="red", **kwargs)
    logger.error(msg)


class PrintMixin:
    repr_attrs = []

    def __repr__(self):
        if self.repr_attrs:
            return "<%s %s>" % (
                type(self).__name__,
                " ".join(
                    [
                        "%s=%s" % (field, repr(getattr(self, field)))
                        for field in self.repr_attrs
                    ]
                ),
            )
        return "<%s %s>" % (type(self).__name__, id(self))

    def __str__(self):
        return str(pf(vars(self)))

import logging
from pprintpp import pformat as pf, pprint as pp
from reprlib import Repr
import shutil
import sys
from textwrap import indent, wrap

import sqlparse as sp

from tlbx.object_utils import get_class_vars, get_caller


logging.basicConfig(format="%(message)s")


_repr = Repr()
_repr.maxstring = 60
_repr.maxother = 20
_repr.maxlist = 5
_repr.maxtuple = 5
_repr.maxset = 5
repr = _repr.repr

DEFAULT_TERM_WIDTH = 80


class FontSpecialChars:
    ENDC = "\033[0m"


class FontColors:
    BLACK = "\033[30m"
    RED = "\033[31m"
    GREEN = "\033[32m"
    YELLOW = "\033[33m"
    BLUE = "\033[34m"
    MAGENTA = "\033[35m"
    CYAN = "\033[36m"
    WHITE = "\033[37m"
    NONE = ""  # Will use default terminal coloring


RESERVED_COLORS = [
    "RED",  # errors
    "YELLOW",  # warnings
    "BLACK",  # to avoid conflicts with terminal defaults
    "WHITE",  # to avoid conflicts with terminal defaults
    "NONE",  # to avoid conflicts with terminal defaults
]

COLOR_OPTIONS = sorted(
    [x for x in get_class_vars(FontColors) if x not in RESERVED_COLORS]
)


class FontEffects:
    BOLD = "\033[1m"
    UNDERLINE = "\033[4m"
    INVERTED = "\033[7m"


def get_terminal_width():
    return shutil.get_terminal_size().columns


def get_logging_level(logger=None):
    if (not logger) or (not isinstance(logger, logging.Logger)):
        logger = logging.getLogger()
    return logger.getEffectiveLevel()


def sqlformat(sql, reindent=True, keyword_case=None):
    return sp.format(sql, reindent=reindent, keyword_case=keyword_case)


def format_msg(
    msg, label="parent", indent=None, color=None, autocolor=False, format_func=pf
):
    term_width = get_terminal_width() or DEFAULT_TERM_WIDTH
    effective_width = term_width
    indent_str = None

    if label == "parent":
        label = get_caller()

    if indent is not None:
        if indent == "label":
            assert label, "indent=label but no label given"
            indent_str = " " * (len(label) + 2)
        else:
            indent = int(indent)
            indent_str = " " * indent
        effective_width = (
            max(effective_width - len(indent_str), 0) or DEFAULT_TERM_WIDTH
        )

    if isinstance(format_func, str):
        format_func = globals()[format_func]

    if format_func and format_func != pf:
        msg = format_func(msg)
        if label and not indent:
            msg = "\n" + msg
    elif not isinstance(msg, str):
        msg = pf(msg, width=effective_width)
        if label and not indent:
            msg = "\n" + msg

    if indent is not None:
        lines = msg.splitlines(True)
        msg = "\n".join(["\n".join(wrap(line, effective_width)) for line in lines])
        if indent == "label":
            msg = indent_str.join(msg.splitlines(True))
        else:
            msg = indent_str + indent_str.join(msg.splitlines(True))
            if label:
                msg = "\n" + msg

    if label:
        msg = label.strip() + ": " + msg

    if (not color) and autocolor:
        assert label, "No label provided, can not use autocolor"
        color_index = ord(label[0]) % len(COLOR_OPTIONS)
        color = COLOR_OPTIONS[color_index]

    if color:
        msg = getattr(FontColors, color.upper()) + msg + FontSpecialChars.ENDC

    return msg


def info(msg, label="parent", logger=None, autocolor=True, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.INFO:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(msg, label=label, autocolor=autocolor, **kwargs)
    logger.info(msg)


def dbg(msg, label="parent", logger=None, autocolor=True, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.DEBUG:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(msg, label=label, autocolor=autocolor, **kwargs)
    logger.debug(msg)


def dbgsql(msg, label="parent", logger=None, autocolor=True, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.DEBUG:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(
        msg, label=label, autocolor=autocolor, format_func=sqlformat, **kwargs
    )
    logger.debug(msg)


def warn(msg, label="parent", logger=None, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.WARNING:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(msg, label=label, color="yellow", **kwargs)
    logger.warning(msg)


def error(msg, label="parent", logger=None, **kwargs):
    logger = logger or logging
    if get_logging_level(logger) > logging.ERROR:
        return
    if label == "parent":
        label = get_caller()
    msg = format_msg(msg, label=label, color="red", **kwargs)
    logger.error(msg)


class PrintMixin:
    repr_attrs = []

    def __repr__(self):
        if self.repr_attrs:
            return "<%s %s>" % (
                type(self).__name__,
                " ".join(
                    [
                        "%s=%s" % (field, repr(getattr(self, field)))
                        for field in self.repr_attrs
                    ]
                ),
            )
        return "<%s %s>" % (type(self).__name__, id(self))

    def __str__(self):
        return str(pf(vars(self)))
# Will use default terminal coloring # errors # warnings # to avoid conflicts with terminal defaults # to avoid conflicts with terminal defaults # to avoid conflicts with terminal defaults