diff --git a/evering/__init__.py b/evering/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/evering/__main__.py b/evering/__main__.py new file mode 100644 index 0000000..7f9bc8e --- /dev/null +++ b/evering/__main__.py @@ -0,0 +1,48 @@ +import argparse +from pathlib import Path +from typing import Union +import logging + +from .colors import * + +logging.basicConfig(level=logging.DEBUG, style="{", format="{levelname:>7}: {message}") +logger = logging.getLogger(__name__) + + + + +def command_test_func(args): + logger.debug(styled("Debug", BLUE.fg, BOLD)) + logger.info(styled("Info", GREEN.fg, BOLD)) + logger.warning(styled("Warning", YELLOW.fg, BOLD)) + logger.error(styled("Error", RED.fg, BOLD)) + logger.info(styled("Test", BRIGHT_BLACK.fg, BOLD)) + + + + + + + + + + + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-c", "--config-file") + subparsers = parser.add_subparsers(title="commands") + + command_test = subparsers.add_parser("test") + command_test.set_defaults(func=command_test_func) + command_test.add_argument("some_file") + + args = parser.parse_args() + if "func" in args: + args.func(args) + else: + parser.print_help() + +if __name__ == "__main__": + main() diff --git a/evering/colors.py b/evering/colors.py new file mode 100644 index 0000000..12bf028 --- /dev/null +++ b/evering/colors.py @@ -0,0 +1,63 @@ +""" +This module includes functions to color the console output with ANSI +escape sequences. +""" + +from typing import Optional, Tuple +from dataclasses import dataclass + +__all__ = [ + "CSI", "ERASE_LINE", + "BOLD", "ITALIC", "UNDERLINE", + "Color", + "BLACK", "RED", "GREEN", "YELLOW", "BLUE", "MAGENTA", "CYAN", "WHITE", "BRIGHT_BLACK", "BRIGHT_RED", "BRIGHT_GREEN", "BRIGHT_YELLOW", "BRIGHT_BLUE", "BRIGHT_MAGENTA", "BRIGHT_CYAN", "BRIGHT_WHITE", + "style_sequence", "styled", +] + +# ANSI escape sequences +# See: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences + +CSI = "\u001b[" +ERASE_LINE = f"{CSI}2K" + +# Styles + +BOLD = 1 +ITALIC = 3 +UNDERLINE = 4 + +# Colors + +@dataclass +class Color: + fg: int + bg: int + +BLACK = Color(30, 40) +RED = Color(31, 41) +GREEN = Color(32, 42) +YELLOW = Color(33, 43) +BLUE = Color(34, 44) +MAGENTA = Color(35, 45) +CYAN = Color(36, 46) +WHITE = Color(37, 47) +BRIGHT_BLACK = Color(90, 100) +BRIGHT_RED = Color(91, 101) +BRIGHT_GREEN = Color(92, 102) +BRIGHT_YELLOW = Color(93, 103) +BRIGHT_BLUE = Color(94, 104) +BRIGHT_MAGENTA = Color(95, 105) +BRIGHT_CYAN = Color(96, 106) +BRIGHT_WHITE = Color(97, 107) + +def style_sequence(*args: int) -> str: + arglist = ";".join(str(arg) for arg in args) + return f"{CSI}{arglist}m" + +def styled(text: str, *args: int) -> str: + if args: + sequence = style_sequence(*args) + reset = style_sequence() + return f"{sequence}{text}{reset}" + else: + return text # No styling necessary diff --git a/evering/config.py b/evering/config.py new file mode 100644 index 0000000..c575e66 --- /dev/null +++ b/evering/config.py @@ -0,0 +1,43 @@ +""" +This module contains helper functions for locating and loading config +files. + +The result of loading a config file are the "local" variables, +including the modules loaded via "import". +""" + +from pathlib import Path + +__all__ = [] + +DEFAULT_LOCATIONS = [ + Path("~/.config/evering/config"), + Path("~/.evering/config"), + Path("~/.evering.conf"), +] + +class LoadConfigException(Exception): + pass + +def load_config(path: Path = None) -> Dict[str, Any]: + if path is not None: + return load_config_file(path) + else: + for path in DEFAULT_LOCATIONS: + try: + return load_config_file(path) + except LoadConfigException: + # Try the next default location + # TODO print a log message + pass + else: + raise LoadConfigException("no config file found in any of the default locations") + +def load_config_file(path: Path) -> Dict[str, Any]: + try: + with open(path) as f: + l = {} + exec(f.read(), locals=l, globals={}) + return l + except IOException as e: + raise LoadConfigException(str(e)) diff --git a/evering/eval.py b/evering/eval.py new file mode 100644 index 0000000..402d757 --- /dev/null +++ b/evering/eval.py @@ -0,0 +1,21 @@ +""" +This module contains helper functions for evaluating python code and +managing local variables. +""" + +import copy +import types +from typing import Dict, Any + +__all__ = ["copy_local_variables"] + +def copy_local_variables(local: Dict[str, Any]) -> Dict[str, Any]: + local_copy = {} + + for key, value in local: + if isinstance(value, types.ModuleType): + local_copy[key] = value + else: + local_copy[key] = copy.deepcopy(value) + + return local_copy diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..9adf49a --- /dev/null +++ b/mypy.ini @@ -0,0 +1,5 @@ +[mypy] +disallow_untyped_defs = True +disallow_incomplete_defs = True +no_implicit_optional = True +ignore_missing_imports = True