# Path: calliope/core/util/dataset.py
# def reorganise_xarray_dimensions(data):
# 
# Path: calliope/core/util/observed_dict.py
# class ObservedDict(dict):
# class UpdateObserverDict(ObservedDict):
#     def __init__(self, initial_dict, initial_yaml_string, on_changed=None, flat=False):
#     def __setitem__(self, key, value):
#     def update(self, other=None, **kwargs):
#     def notify(self, updated=None):
#     def __init__(
#         self,
#         name,
#         observer,
#         initial_dict=None,
#         initial_yaml_string=None,
#         *args,
#         **kwargs,
#     ):
#     def notify(self, updated=None):
# 
# Path: calliope/core/util/tools.py
# def get_from_dict(data_dict, map_list):
# def apply_to_dict(data_dict, map_list, func, args):
#     def __init__(self, func):
#     def __get__(self, obj, objtype=None):
#     def __call__(self, *args, **kw):
# def relative_path(base_path_file, path):
# def load_function(source):
# def plugin_load(name, builtin_module):
# class memoize_instancemethod(object):
# 
# Path: calliope/core/util/logging.py
# def log_time(
#     logger, timings, identifier, comment=None, level="info", time_since_run_start=False
# ):
#     if comment is None:
#         comment = identifier
# 
#     timings[identifier] = now = datetime.datetime.now()
# 
#     if time_since_run_start and "run_start" in timings:
#         time_diff = now - timings["run_start"]
#         comment += ". Time since start of model run: {}".format(time_diff)
# 
#     getattr(logger, level)(comment)
# 
# Path: calliope/core/util/generate_runs.py
# def generate_runs(model_file, scenarios=None, additional_args=None, override_dict=None):
#     """
#     Returns a list of "calliope run" invocations.
# 
#     ``scenarios`` must be specified as either a semicolon-separated
#     list of scenarios or a semicolon-separated list of comma-separated
#     individual override combinations, such as:
# 
#         ``override1,override2;override1,override3;...``
# 
#     If ``scenarios`` is not given, use all scenarios in the model
#     configuration, and if no scenarios given in the model configuration,
#     uses all individual overrides, one by one.
# 
#     """
#     if scenarios is None:
#         config = AttrDict.from_yaml(model_file)
#         if override_dict:
#             override = AttrDict.from_yaml_string(override_dict)
#             config.union(override, allow_override=True, allow_replacement=True)
# 
#         if "scenarios" in config:
#             runs = config.scenarios.keys()
#         else:
#             runs = config.overrides.keys()
#     else:
#         runs = scenarios.split(";")
# 
#     commands = []
# 
#     # len(str(x)) gives us the number of digits in x, for padding
#     i_string = "{:0>" + str(len(str(len(runs)))) + "d}"
# 
#     for i, run in enumerate(runs):
#         cmd = (
#             f"calliope run {model_file} --scenario {run} "
#             f"--save_netcdf out_{i_string.format(i + 1)}_{run}.nc "
#         ).strip()
# 
#         if override_dict:
#             cmd = cmd + ' --override_dict="{}"'.format(override_dict)
# 
#         if additional_args:
#             cmd = cmd + " " + additional_args
# 
#         commands.append(cmd)
# 
#     return commands
# 
# Path: calliope/test/common/util.py
# def build_test_model(
#     override_dict=None,
#     scenario=None,
#     model_file="model.yaml",
#     timeseries_dataframes=None,
# ):
# def check_error_or_warning(error_warning, test_string_or_strings):
# def check_variable_exists(backend_model, constraint, variable, idx=None):


import pytest  # noqa: F401
import calliope
import logging
import datetime
import os
import tempfile
import xarray as xr
from calliope.core.util import dataset, observed_dict
from calliope.core.util.tools import memoize, memoize_instancemethod
from calliope.core.util.logging import log_time
from calliope.core.util.generate_runs import generate_runs
from calliope.test.common.util import (
    python36_or_higher,
    check_error_or_warning,
)
        assert logging.getLogger("py.warnings").getEffectiveLevel() == 20
        assert (
            logging.getLogger("calliope.backend.pyomo.model").getEffectiveLevel() == 10
        )

    def test_timing_log(self):
        timings = {"model_creation": datetime.datetime.now()}
        logger = logging.getLogger("calliope.testlogger")

        # TODO: capture logging output and check that comment is in string
        log_time(logger, timings, "test", comment="test_comment", level="info")
        assert isinstance(timings["test"], datetime.datetime)

        log_time(logger, timings, "test2", comment=None, level="info")
        assert isinstance(timings["test2"], datetime.datetime)

        # TODO: capture logging output and check that time_since_run_start is in the string
        log_time(
            logger,
            timings,
            "test",
            comment=None,
            level="info",
            time_since_run_start=True,
        )


class TestGenerateRuns:
    @python36_or_higher
    def test_generate_runs_scenarios(self):

# Path: calliope/core/util/dataset.py
# def reorganise_xarray_dimensions(data):
# 
# Path: calliope/core/util/observed_dict.py
# class ObservedDict(dict):
# class UpdateObserverDict(ObservedDict):
#     def __init__(self, initial_dict, initial_yaml_string, on_changed=None, flat=False):
#     def __setitem__(self, key, value):
#     def update(self, other=None, **kwargs):
#     def notify(self, updated=None):
#     def __init__(
#         self,
#         name,
#         observer,
#         initial_dict=None,
#         initial_yaml_string=None,
#         *args,
#         **kwargs,
#     ):
#     def notify(self, updated=None):
# 
# Path: calliope/core/util/tools.py
# def get_from_dict(data_dict, map_list):
# def apply_to_dict(data_dict, map_list, func, args):
#     def __init__(self, func):
#     def __get__(self, obj, objtype=None):
#     def __call__(self, *args, **kw):
# def relative_path(base_path_file, path):
# def load_function(source):
# def plugin_load(name, builtin_module):
# class memoize_instancemethod(object):
# 
# Path: calliope/core/util/logging.py
# def log_time(
#     logger, timings, identifier, comment=None, level="info", time_since_run_start=False
# ):
#     if comment is None:
#         comment = identifier
# 
#     timings[identifier] = now = datetime.datetime.now()
# 
#     if time_since_run_start and "run_start" in timings:
#         time_diff = now - timings["run_start"]
#         comment += ". Time since start of model run: {}".format(time_diff)
# 
#     getattr(logger, level)(comment)
# 
# Path: calliope/core/util/generate_runs.py
# def generate_runs(model_file, scenarios=None, additional_args=None, override_dict=None):
#     """
#     Returns a list of "calliope run" invocations.
# 
#     ``scenarios`` must be specified as either a semicolon-separated
#     list of scenarios or a semicolon-separated list of comma-separated
#     individual override combinations, such as:
# 
#         ``override1,override2;override1,override3;...``
# 
#     If ``scenarios`` is not given, use all scenarios in the model
#     configuration, and if no scenarios given in the model configuration,
#     uses all individual overrides, one by one.
# 
#     """
#     if scenarios is None:
#         config = AttrDict.from_yaml(model_file)
#         if override_dict:
#             override = AttrDict.from_yaml_string(override_dict)
#             config.union(override, allow_override=True, allow_replacement=True)
# 
#         if "scenarios" in config:
#             runs = config.scenarios.keys()
#         else:
#             runs = config.overrides.keys()
#     else:
#         runs = scenarios.split(";")
# 
#     commands = []
# 
#     # len(str(x)) gives us the number of digits in x, for padding
#     i_string = "{:0>" + str(len(str(len(runs)))) + "d}"
# 
#     for i, run in enumerate(runs):
#         cmd = (
#             f"calliope run {model_file} --scenario {run} "
#             f"--save_netcdf out_{i_string.format(i + 1)}_{run}.nc "
#         ).strip()
# 
#         if override_dict:
#             cmd = cmd + ' --override_dict="{}"'.format(override_dict)
# 
#         if additional_args:
#             cmd = cmd + " " + additional_args
# 
#         commands.append(cmd)
# 
#     return commands
# 
# Path: calliope/test/common/util.py
# def build_test_model(
#     override_dict=None,
#     scenario=None,
#     model_file="model.yaml",
#     timeseries_dataframes=None,
# ):
# def check_error_or_warning(error_warning, test_string_or_strings):
# def check_variable_exists(backend_model, constraint, variable, idx=None):


# Path: calliope/test/test_core_util.py
import pytest  # noqa: F401
import calliope
import logging
import datetime
import os
import tempfile
import xarray as xr
from calliope.core.util import dataset, observed_dict
from calliope.core.util.tools import memoize, memoize_instancemethod
from calliope.core.util.logging import log_time
from calliope.core.util.generate_runs import generate_runs
from calliope.test.common.util import (
    python36_or_higher,
    check_error_or_warning,
)

        assert logging.getLogger("py.warnings").getEffectiveLevel() == 20
        assert (
            logging.getLogger("calliope.backend.pyomo.model").getEffectiveLevel() == 10
        )

    def test_timing_log(self):
        timings = {"model_creation": datetime.datetime.now()}
        logger = logging.getLogger("calliope.testlogger")

        # TODO: capture logging output and check that comment is in string
        log_time(logger, timings, "test", comment="test_comment", level="info")
        assert isinstance(timings["test"], datetime.datetime)

        log_time(logger, timings, "test2", comment=None, level="info")
        assert isinstance(timings["test2"], datetime.datetime)

        # TODO: capture logging output and check that time_since_run_start is in the string
        log_time(
            logger,
            timings,
            "test",
            comment=None,
            level="info",
            time_since_run_start=True,
        )


class TestGenerateRuns:
    @python36_or_higher
    def test_generate_runs_scenarios(self):

        runs = generate_runs(