# Path: did/base.py
# class Config(object):
#     """ User config file """
# 
#     parser = None
# 
#     def __init__(self, config=None, path=None):
#         """
#         Read the config file
# 
#         Parse config from given string (config) or file (path).
#         If no config or path given, default to "~/.did/config" which
#         can be overrided by the ``DID_DIR`` environment variable.
#         """
#         # Read the config only once (unless explicitly provided)
#         if self.parser is not None and config is None and path is None:
#             return
#         Config.parser = configparser.ConfigParser(interpolation=None)
#         # If config provided as string, parse it directly
#         if config is not None:
#             log.info("Inspecting config file from string")
#             log.debug(utils.pretty(config))
#             self.parser.read_file(io.StringIO(config))
#             return
#         # Check the environment for config file override
#         # (unless path is explicitly provided)
#         if path is None:
#             path = Config.path()
#         # Parse the config from file
#         try:
#             log.info("Inspecting config file '{0}'.".format(path))
#             self.parser.readfp(codecs.open(path, "r", "utf8"))
#         except IOError as error:
#             log.debug(error)
#             Config.parser = None
#             raise ConfigFileError(
#                 "Unable to read the config file '{0}'.".format(path))
# 
#     @property
#     def plugins(self):
#         """ Custom plugins """
#         try:
#             return self.parser.get("general", "plugins")
#         except BaseException:
#             return None
# 
#     @property
#     def quarter(self):
#         """ The first month of the quarter, 1 by default """
#         try:
#             month = self.parser.get("general", "quarter", fallback=1)
#             month = int(month) % 3
#         except ValueError:
#             raise ConfigError(
#                 f"Invalid quarter start '{month}', should be integer.")
#         return month
# 
#     @property
#     def email(self):
#         """ User email(s) """
#         try:
#             return self.parser.get("general", "email")
#         except NoSectionError as error:
#             log.debug(error)
#             raise ConfigFileError(
#                 "No general section found in the config file.")
#         except NoOptionError as error:
#             log.debug(error)
#             raise ConfigFileError(
#                 "No email address defined in the config file.")
# 
#     @property
#     def width(self):
#         """ Maximum width of the report """
#         try:
#             return int(self.parser.get("general", "width"))
#         except (NoOptionError, NoSectionError):
#             return MAX_WIDTH
# 
#     def sections(self, kind=None):
#         """ Return all sections (optionally of given kind only) """
#         result = []
#         for section in self.parser.sections():
#             # Selected kind only if provided
#             if kind is not None:
#                 try:
#                     section_type = self.parser.get(section, "type")
#                     if section_type != kind:
#                         continue
#                 except NoOptionError:
#                     continue
#             result.append(section)
#         return result
# 
#     def section(self, section, skip=['type', 'order']):
#         """ Return section items, skip selected (type/order by default) """
#         return [(key, val) for key, val in self.parser.items(section)
#                 if key not in skip]
# 
#     def item(self, section, it):
#         """ Return content of given item in selected section """
#         for key, value in self.section(section, skip=[]):
#             if key == it:
#                 return value
#         raise ConfigError(
#             "Item '{0}' not found in section '{1}'".format(it, section))
# 
#     @staticmethod
#     def path():
#         """ Detect config file path """
#         # Detect config directory
#         try:
#             directory = os.environ["DID_DIR"]
#         except KeyError:
#             directory = CONFIG
#         # Detect config file (even before options are parsed)
#         filename = "config"
#         matched = re.search(r"--confi?g?[ =](\S+)", " ".join(sys.argv))
#         if matched:
#             filepath, filename = os.path.split(matched.groups()[0])
#             if filepath:
#                 directory = filepath
#         return directory.rstrip("/") + "/" + filename
# 
#     @staticmethod
#     def example():
#         """ Return config example """
#         return "[general]\nemail = Name Surname <email@example.org>\n"
# 
# class ConfigError(GeneralError):
#     """ Stats configuration problem """


import datetime
import pytest
import did.base
from did.base import Config, ConfigError
    from did.base import Config
    from did.base import Date
    from did.base import Date
    from did.base import User
    from did.base import ConfigError
    from did.base import ReportError
    # Custom login alias
    user = User("some@email.org; bz: bzlogin", stats="bz")
    assert user.login == "bzlogin"

    # Custom email alias in config section
    Config(config="[bz]\ntype = bugzilla\nemail = bugzilla@email.org")
    user = User("some@email.org", stats="bz")
    assert user.email == "bugzilla@email.org"
    assert user.login == "bugzilla"

    # Custom login alias in config section
    Config(config="[bz]\ntype = bugzilla\nlogin = bzlogin")
    user = User("some@email.org", stats="bz")
    assert user.login == "bzlogin"

    # User cloning
    user = User("some@email.org; bz: bzlogin")
    clone = user.clone("bz")
    assert clone.login == "bzlogin"


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  Exceptions
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def test_ConfigError():
    ''' Confirm ConfigError exception is defined '''

    try:
        raise ConfigError

# Path: did/base.py
# class Config(object):
#     """ User config file """
# 
#     parser = None
# 
#     def __init__(self, config=None, path=None):
#         """
#         Read the config file
# 
#         Parse config from given string (config) or file (path).
#         If no config or path given, default to "~/.did/config" which
#         can be overrided by the ``DID_DIR`` environment variable.
#         """
#         # Read the config only once (unless explicitly provided)
#         if self.parser is not None and config is None and path is None:
#             return
#         Config.parser = configparser.ConfigParser(interpolation=None)
#         # If config provided as string, parse it directly
#         if config is not None:
#             log.info("Inspecting config file from string")
#             log.debug(utils.pretty(config))
#             self.parser.read_file(io.StringIO(config))
#             return
#         # Check the environment for config file override
#         # (unless path is explicitly provided)
#         if path is None:
#             path = Config.path()
#         # Parse the config from file
#         try:
#             log.info("Inspecting config file '{0}'.".format(path))
#             self.parser.readfp(codecs.open(path, "r", "utf8"))
#         except IOError as error:
#             log.debug(error)
#             Config.parser = None
#             raise ConfigFileError(
#                 "Unable to read the config file '{0}'.".format(path))
# 
#     @property
#     def plugins(self):
#         """ Custom plugins """
#         try:
#             return self.parser.get("general", "plugins")
#         except BaseException:
#             return None
# 
#     @property
#     def quarter(self):
#         """ The first month of the quarter, 1 by default """
#         try:
#             month = self.parser.get("general", "quarter", fallback=1)
#             month = int(month) % 3
#         except ValueError:
#             raise ConfigError(
#                 f"Invalid quarter start '{month}', should be integer.")
#         return month
# 
#     @property
#     def email(self):
#         """ User email(s) """
#         try:
#             return self.parser.get("general", "email")
#         except NoSectionError as error:
#             log.debug(error)
#             raise ConfigFileError(
#                 "No general section found in the config file.")
#         except NoOptionError as error:
#             log.debug(error)
#             raise ConfigFileError(
#                 "No email address defined in the config file.")
# 
#     @property
#     def width(self):
#         """ Maximum width of the report """
#         try:
#             return int(self.parser.get("general", "width"))
#         except (NoOptionError, NoSectionError):
#             return MAX_WIDTH
# 
#     def sections(self, kind=None):
#         """ Return all sections (optionally of given kind only) """
#         result = []
#         for section in self.parser.sections():
#             # Selected kind only if provided
#             if kind is not None:
#                 try:
#                     section_type = self.parser.get(section, "type")
#                     if section_type != kind:
#                         continue
#                 except NoOptionError:
#                     continue
#             result.append(section)
#         return result
# 
#     def section(self, section, skip=['type', 'order']):
#         """ Return section items, skip selected (type/order by default) """
#         return [(key, val) for key, val in self.parser.items(section)
#                 if key not in skip]
# 
#     def item(self, section, it):
#         """ Return content of given item in selected section """
#         for key, value in self.section(section, skip=[]):
#             if key == it:
#                 return value
#         raise ConfigError(
#             "Item '{0}' not found in section '{1}'".format(it, section))
# 
#     @staticmethod
#     def path():
#         """ Detect config file path """
#         # Detect config directory
#         try:
#             directory = os.environ["DID_DIR"]
#         except KeyError:
#             directory = CONFIG
#         # Detect config file (even before options are parsed)
#         filename = "config"
#         matched = re.search(r"--confi?g?[ =](\S+)", " ".join(sys.argv))
#         if matched:
#             filepath, filename = os.path.split(matched.groups()[0])
#             if filepath:
#                 directory = filepath
#         return directory.rstrip("/") + "/" + filename
# 
#     @staticmethod
#     def example():
#         """ Return config example """
#         return "[general]\nemail = Name Surname <email@example.org>\n"
# 
# class ConfigError(GeneralError):
#     """ Stats configuration problem """


# Path: tests/test_base.py
import datetime
import pytest
import did.base
from did.base import Config, ConfigError
    from did.base import Config
    from did.base import Date
    from did.base import Date
    from did.base import User
    from did.base import ConfigError
    from did.base import ReportError

    # Custom login alias
    user = User("some@email.org; bz: bzlogin", stats="bz")
    assert user.login == "bzlogin"

    # Custom email alias in config section
    Config(config="[bz]\ntype = bugzilla\nemail = bugzilla@email.org")
    user = User("some@email.org", stats="bz")
    assert user.email == "bugzilla@email.org"
    assert user.login == "bugzilla"

    # Custom login alias in config section
    Config(config="[bz]\ntype = bugzilla\nlogin = bzlogin")
    user = User("some@email.org", stats="bz")
    assert user.login == "bzlogin"

    # User cloning
    user = User("some@email.org; bz: bzlogin")
    clone = user.clone("bz")
    assert clone.login == "bzlogin"


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  Exceptions
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def test_ConfigError():
    ''' Confirm ConfigError exception is defined '''

    try:
        raise ConfigError

    except ConfigError: