# Path: slo_generator/utils.py
#     GCS_ENABLED = True
#     GCS_ENABLED = False
# LOGGER = logging.getLogger(__name__)
# def load_configs(path, ctx=os.environ, kind=None):
# def load_config(path, ctx=os.environ, kind=None):
# def parse_config(path=None, content=None, ctx=os.environ):
#     def replace_env_vars(content, ctx):
# def setup_logging():
# def get_human_time(timestamp, timezone=None):
# def get_exporters(config, spec):
# def get_backend(config, spec):
# def get_error_budget_policy(config, spec):
# def get_backend_cls(backend):
# def get_exporter_cls(exporter):
# def import_cls(cls_name, expected_type):
# def import_dynamic(package, name, prefix="class"):
# def capitalize(word):
# def snake_to_caml(word):
# def caml_to_snake(word):
# def dict_snake_to_caml(data):
# def apply_func_dict(data, func):
# def str2bool(string):
# def download_gcs_file(url):
# def decode_gcs_url(url):
# def get_files(source, extensions=['yaml', 'yml', 'json']):
# def get_target_path(source_dir, target_dir, relative_path, mkdir=True):
# def fmt_traceback(exc):
# 
# Path: slo_generator/constants.py
# COLORED_OUTPUT = int(os.environ.get("COLORED_OUTPUT", "0"))
# 
# MIN_VALID_EVENTS = int(os.environ.get("MIN_VALID_EVENTS", "1"))
# 
# NO_DATA = -1
# 
# class Colors:
#     """Colors for console output."""
#     HEADER = '\033[95m'
#     OKBLUE = '\033[94m'
#     OKGREEN = '\033[92m'
#     WARNING = '\033[93m'
#     FAIL = '\033[91m'
#     ENDC = '\033[0m'
#     BOLD = '\033[1m'
#     UNDERLINE = '\033[4m'


import logging
from dataclasses import asdict, dataclass, fields, field
from slo_generator import utils
from slo_generator.constants import (COLORED_OUTPUT, MIN_VALID_EVENTS, NO_DATA,
                                     Colors)
            data = method(self.timestamp, self.window, config)
            LOGGER.debug(f'{self.info} | Backend response: {data}')
        except Exception as exc:  # pylint:disable=broad-except
            self.errors.append(utils.fmt_traceback(exc))
            return None
        return data

    def get_sli(self, data):
        """Compute SLI value and good / bad counts from the backend result.

        Some backends (e.g: Prometheus) are computing and returning the SLI
        value directly, others are sending a tuple (good_count, bad_count) and
        SLI value is computed from there.

        Args:
            data (obj): Backend data.

        Returns:
            tuple: A tuple of 3 values to unpack (float, int, int).
                float: SLI value.
                int: Good events count.
                int: Bad events count.

        Raises:
            Exception: When the backend does not return a proper result.
        """
        if isinstance(data, tuple):  # good, bad count
            good_count, bad_count = data
            if good_count == NO_DATA:
                good_count = 0

# Path: slo_generator/utils.py
#     GCS_ENABLED = True
#     GCS_ENABLED = False
# LOGGER = logging.getLogger(__name__)
# def load_configs(path, ctx=os.environ, kind=None):
# def load_config(path, ctx=os.environ, kind=None):
# def parse_config(path=None, content=None, ctx=os.environ):
#     def replace_env_vars(content, ctx):
# def setup_logging():
# def get_human_time(timestamp, timezone=None):
# def get_exporters(config, spec):
# def get_backend(config, spec):
# def get_error_budget_policy(config, spec):
# def get_backend_cls(backend):
# def get_exporter_cls(exporter):
# def import_cls(cls_name, expected_type):
# def import_dynamic(package, name, prefix="class"):
# def capitalize(word):
# def snake_to_caml(word):
# def caml_to_snake(word):
# def dict_snake_to_caml(data):
# def apply_func_dict(data, func):
# def str2bool(string):
# def download_gcs_file(url):
# def decode_gcs_url(url):
# def get_files(source, extensions=['yaml', 'yml', 'json']):
# def get_target_path(source_dir, target_dir, relative_path, mkdir=True):
# def fmt_traceback(exc):
# 
# Path: slo_generator/constants.py
# COLORED_OUTPUT = int(os.environ.get("COLORED_OUTPUT", "0"))
# 
# MIN_VALID_EVENTS = int(os.environ.get("MIN_VALID_EVENTS", "1"))
# 
# NO_DATA = -1
# 
# class Colors:
#     """Colors for console output."""
#     HEADER = '\033[95m'
#     OKBLUE = '\033[94m'
#     OKGREEN = '\033[92m'
#     WARNING = '\033[93m'
#     FAIL = '\033[91m'
#     ENDC = '\033[0m'
#     BOLD = '\033[1m'
#     UNDERLINE = '\033[4m'


# Path: slo_generator/report.py
import logging
from dataclasses import asdict, dataclass, fields, field
from slo_generator import utils
from slo_generator.constants import (COLORED_OUTPUT, MIN_VALID_EVENTS, NO_DATA,
                                     Colors)

            data = method(self.timestamp, self.window, config)
            LOGGER.debug(f'{self.info} | Backend response: {data}')
        except Exception as exc:  # pylint:disable=broad-except
            self.errors.append(utils.fmt_traceback(exc))
            return None
        return data

    def get_sli(self, data):
        """Compute SLI value and good / bad counts from the backend result.

        Some backends (e.g: Prometheus) are computing and returning the SLI
        value directly, others are sending a tuple (good_count, bad_count) and
        SLI value is computed from there.

        Args:
            data (obj): Backend data.

        Returns:
            tuple: A tuple of 3 values to unpack (float, int, int).
                float: SLI value.
                int: Good events count.
                int: Bad events count.

        Raises:
            Exception: When the backend does not return a proper result.
        """
        if isinstance(data, tuple):  # good, bad count
            good_count, bad_count = data
            if good_count == NO_DATA:
                good_count = 0

            if bad_count == NO_DATA: