src\wily\config.py
-- -- --- --- --- --- --- --- ------- ------- ------- | """
-- -- --- --- --- --- --- --- ------- ------- ------- | Configuration of wily.
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | TODO : Handle operator settings. Maybe a section for each operator and then pass kwargs to operators?
-- -- --- --- --- --- --- --- ------- ------- ------- | TODO : Better utilise default values and factory in @dataclass to replace DEFAULT_CONFIG
-- -- --- --- --- --- --- --- ------- ------- ------- | and replace the logic in load() to set default values.
-- -- --- --- --- --- --- --- ------- ------- ------- | """
-- -- --- --- --- --- --- --- ------- ------- ------- | import configparser
-- -- --- --- --- --- --- --- ------- ------- ------- | import hashlib
-- -- --- --- --- --- --- --- ------- ------- ------- | import logging
-- -- --- --- --- --- --- --- ------- ------- ------- | import pathlib
-- -- --- --- --- --- --- --- ------- ------- ------- | from dataclasses import InitVar, dataclass, field
-- -- --- --- --- --- --- --- ------- ------- ------- | from functools import lru_cache
-- -- --- --- --- --- --- --- ------- ------- ------- | from typing import Any, List
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily import operators
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily.archivers import ARCHIVER_GIT
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | logger = logging.getLogger(__name__)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | @lru_cache(maxsize=128)
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | def generate_cache_path(path):
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | """
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | Generate a reusable path to cache results.
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 |
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | Will use the --path of the target and hash into
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | a 9-character directory within the HOME folder.
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 |
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | :return: The cache path
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | :rtype: ``str``
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | """
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | logger.debug(f"Generating cache for {path}")
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | sha = hashlib.sha1(str(path).encode()).hexdigest()[:9]
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | HOME = pathlib.Path.home()
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | cache_path = str(HOME / ".wily" / sha)
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | logger.debug(f"Cache path is {cache_path}")
-- 01 001 004 002 004 005 006 0013.93 0006.97 0000.50 | return cache_path
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | @dataclass
03 -- --- --- --- --- --- --- ------- ------- ------- | class WilyConfig:
03 -- --- --- --- --- --- --- ------- ------- ------- | """
03 -- --- --- --- --- --- --- ------- ------- ------- | Wily configuration.
03 -- --- --- --- --- --- --- ------- ------- ------- |
03 -- --- --- --- --- --- --- ------- ------- ------- | A data class to reflect the configurable options within Wily.
03 -- --- --- --- --- --- --- ------- ------- ------- | """
03 -- --- --- --- --- --- --- ------- ------- ------- |
03 -- --- --- --- --- --- --- ------- ------- ------- | operators: List[str]
03 -- --- --- --- --- --- --- ------- ------- ------- | archiver: Any
03 -- --- --- --- --- --- --- ------- ------- ------- | path: str
03 -- --- --- --- --- --- --- ------- ------- ------- | max_revisions: int
03 -- --- --- --- --- --- --- ------- ------- ------- | include_ipynb: bool = True
03 -- --- --- --- --- --- --- ------- ------- ------- | ipynb_cells: bool = True
03 -- --- --- --- --- --- --- ------- ------- ------- | targets: List[str] = None
03 -- --- --- --- --- --- --- ------- ------- ------- | checkout_options: dict = field(default_factory=dict)
03 -- --- --- --- --- --- --- ------- ------- ------- | _cache_path: InitVar[str] = ""
03 -- --- --- --- --- --- --- ------- ------- ------- |
03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | def __post_init__(self, _cache_path):
03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | """Parse operators string to list and clone targets as a list of path."""
03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if isinstance(self.operators, str):
03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | self.operators = self._parse_to_list(self.operators)
03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if self.targets is None or "":
03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | self.targets = [self.path]
03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | self._cache_path = _cache_path
03 -- --- --- --- --- --- --- ------- ------- ------- |
03 -- --- --- --- --- --- --- ------- ------- ------- | @property
03 -- --- --- --- --- --- --- ------- ------- ------- | def cache_path(self):
03 -- --- --- --- --- --- --- ------- ------- ------- | """Path to the cache."""
03 -- --- --- --- --- --- --- ------- ------- ------- | if not self._cache_path:
03 -- --- --- --- --- --- --- ------- ------- ------- | self._cache_path = generate_cache_path(pathlib.Path(self.path).absolute())
03 -- --- --- --- --- --- --- ------- ------- ------- | return self._cache_path
03 -- --- --- --- --- --- --- ------- ------- ------- |
03 -- --- --- --- --- --- --- ------- ------- ------- | @cache_path.setter
03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def cache_path(self, value):
03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """Override the cache path."""
03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | logger.debug(f"Setting custom cache path to {value}")
03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self._cache_path = value
03 -- --- --- --- --- --- --- ------- ------- ------- |
03 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def _parse_to_list(string, separator=","):
03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | items = []
03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | for raw_item in string.split(separator):
03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | item = raw_item.strip()
03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | if item:
03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | items.append(item)
03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return items
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | # Default values for Wily
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | """ The default operators """
-- -- --- --- --- --- --- --- ------- ------- ------- | DEFAULT_OPERATORS = {
-- -- --- --- --- --- --- --- ------- ------- ------- | operators.OPERATOR_RAW.name,
-- -- --- --- --- --- --- --- ------- ------- ------- | operators.OPERATOR_MAINTAINABILITY.name,
-- -- --- --- --- --- --- --- ------- ------- ------- | operators.OPERATOR_CYCLOMATIC.name,
-- -- --- --- --- --- --- --- ------- ------- ------- | operators.OPERATOR_HALSTEAD.name,
-- -- --- --- --- --- --- --- ------- ------- ------- | }
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | """ The name of the default archiver """
-- -- --- --- --- --- --- --- ------- ------- ------- | DEFAULT_ARCHIVER = ARCHIVER_GIT.name
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | """ The default configuration file name """
-- -- --- --- --- --- --- --- ------- ------- ------- | DEFAULT_CONFIG_PATH = "wily.cfg"
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | """ The default section name in the config """
-- -- --- --- --- --- --- --- ------- ------- ------- | DEFAULT_CONFIG_SECTION = "wily"
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | """ The default maximum number of revisions to archiver """
-- -- --- --- --- --- --- --- ------- ------- ------- | DEFAULT_MAX_REVISIONS = 50
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | DEFAULT_PATH = "."
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | """ The default configuration for Wily (if no config file exists) """
-- -- --- --- --- --- --- --- ------- ------- ------- | DEFAULT_CONFIG = WilyConfig(
-- -- --- --- --- --- --- --- ------- ------- ------- | operators=DEFAULT_OPERATORS,
-- -- --- --- --- --- --- --- ------- ------- ------- | archiver=DEFAULT_ARCHIVER,
-- -- --- --- --- --- --- --- ------- ------- ------- | path=DEFAULT_PATH,
-- -- --- --- --- --- --- --- ------- ------- ------- | max_revisions=DEFAULT_MAX_REVISIONS,
-- -- --- --- --- --- --- --- ------- ------- ------- | )
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | """ Default table style in console. See tabulate docs for more. """
-- -- --- --- --- --- --- --- ------- ------- ------- | DEFAULT_GRID_STYLE = "fancy_grid"
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | def load(config_path=DEFAULT_CONFIG_PATH):
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | """
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | Load config file and set values to defaults where no present.
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | :return: The configuration ``WilyConfig``
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | :rtype: :class:`wily.config.WilyConfig`
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | """
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | if not pathlib.Path(config_path).exists():
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | logger.debug(f"Could not locate {config_path}, using default config.")
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | return DEFAULT_CONFIG
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | config = configparser.ConfigParser(default_section=DEFAULT_CONFIG_SECTION)
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | config.read(config_path)
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | operators = config.get(
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | section=DEFAULT_CONFIG_SECTION, option="operators", fallback=DEFAULT_OPERATORS
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | )
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | archiver = config.get(
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | section=DEFAULT_CONFIG_SECTION, option="archiver", fallback=DEFAULT_ARCHIVER
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | )
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | path = config.get(section=DEFAULT_CONFIG_SECTION, option="path", fallback=".")
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | cache_path = config.get(
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | section=DEFAULT_CONFIG_SECTION, option="cache_path", fallback=""
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | )
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | max_revisions = config.getint(
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | section=DEFAULT_CONFIG_SECTION,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | option="max_revisions",
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | fallback=DEFAULT_MAX_REVISIONS,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | )
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | include_ipynb = config.getboolean(
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | section=DEFAULT_CONFIG_SECTION, option="include_ipynb", fallback=True
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | )
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | ipynb_cells = config.getboolean(
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | section=DEFAULT_CONFIG_SECTION, option="ipynb_cells", fallback=True
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | )
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | return WilyConfig(
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | operators=operators,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | archiver=archiver,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | path=path,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | _cache_path=cache_path,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | max_revisions=max_revisions,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | include_ipynb=include_ipynb,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | ipynb_cells=ipynb_cells,
-- -- 001 001 001 001 002 002 0002.00 0001.00 0000.50 | )