diff --git a/doc/SETUP.org b/doc/SETUP.org index 6eb26c3..5d9f0f2 100644 --- a/doc/SETUP.org +++ b/doc/SETUP.org @@ -98,6 +98,7 @@ They aren't necessary, but will improve your experience. At the moment these are - [[https://github.com/karlicoss/cachew][cachew]]: automatic caching library, which can greatly speedup data access - [[https://github.com/metachris/logzero][logzero]]: a nice logging library, supporting colors +- [[https://github.com/python/mypy][mypy]]: mypy is used for checking configs and troubleshooting * Setting up modules This is an *optional step* as few modules work without extra setup. @@ -111,7 +112,6 @@ elaborating on some technical rationales behind the current configuration system ** private configuration (=my.config=) # TODO write about dynamic configuration # TODO add a command to edit config?? e.g. HPI config edit -# HPI doctor? If you're not planning to use private configuration (some modules don't need it) you can skip straight to the next step. Still, I'd recommend you to read anyway. The configuration contains paths to the data on your disks, links to external repositories, etc. @@ -119,7 +119,11 @@ The config is simply a *python package* (named =my.config=), expected to be in = Since it's a Python package, generally it's very *flexible* and there are many ways to set it up. -- *The simplest and the very minimum* you need is =~/.config/my/my/config.py=. For example: +- *The simplest way* + + After installing HPI, run =hpi config init=. + + This will create an empty config file for you (usually, in =~/.config/my=), which you can edit. Example configuration: #+begin_src python import pytz # yes, you can use any Python stuff in the config diff --git a/my/core/__main__.py b/my/core/__main__.py index c80bae3..1159907 100644 --- a/my/core/__main__.py +++ b/my/core/__main__.py @@ -9,14 +9,9 @@ from . import LazyLogger log = LazyLogger('HPI cli') -class Modes: - CONFIG = 'config' - DOCTOR = 'doctor' - MODULES = 'modules' - def run_mypy(pkg): - from .init import get_mycfg_dir + from .preinit import get_mycfg_dir mycfg_dir = get_mycfg_dir() # todo ugh. not sure how to extract it from pkg? @@ -73,6 +68,27 @@ class color: RESET = '\033[0m' +def config_create(args): + from .preinit import get_mycfg_dir + mycfg_dir = get_mycfg_dir() + + created = False + if not mycfg_dir.exists(): + # todo not sure about the layout... should I use my/config.py instead? + my_config = mycfg_dir / 'my' / 'config' / '__init__.py' + + my_config.parent.mkdir(parents=True) + my_config.touch() + info(f'created empty config: {my_config}') + created = True + else: + error(f"config directory '{mycfg_dir}' already exists, skipping creation") + + config_check(args) + if not created: + sys.exit(1) + + def config_check(args): try: import my.config as cfg @@ -127,9 +143,6 @@ def modules_check(args): info(f' - stats: {res}') - - - def list_modules(args): # todo with docs/etc? from .util import get_modules @@ -151,17 +164,20 @@ Tool for HPI. Work in progress, will be used for config management, troubleshooting & introspection ''') sp = p.add_subparsers(dest='mode') - dp = sp.add_parser(Modes.DOCTOR, help='Run various checks') + dp = sp.add_parser('doctor', help='Run various checks') dp.add_argument('--verbose', action='store_true', help='Print more diagnosic infomration') dp.set_defaults(func=doctor) - cp = sp.add_parser(Modes.CONFIG, help='Work with configuration') + cp = sp.add_parser('config', help='Work with configuration') scp = cp.add_subparsers(dest='mode') - # if True: - # ccp = scp.add_parser('check', help='Check config') - # ccp.set_defaults(func=config_check) + if True: + ccp = scp.add_parser('check', help='Check config') + ccp.set_defaults(func=config_check) - mp = sp.add_parser(Modes.MODULES, help='List available modules') + icp = scp.add_parser('create', help='Create user config') + icp.set_defaults(func=config_create) + + mp = sp.add_parser('modules', help='List available modules') mp.set_defaults(func=list_modules) return p diff --git a/my/core/init.py b/my/core/init.py index d2c7195..158a311 100644 --- a/my/core/init.py +++ b/my/core/init.py @@ -24,26 +24,13 @@ def assign_module(parent: str, name: str, module: ModuleType) -> None: del ModuleType -def get_mycfg_dir(): - import appdirs # type: ignore[import] - from pathlib import Path - import os - # not sure if that's necessary, i.e. could rely on PYTHONPATH instead - # on the other hand, by using MY_CONFIG we are guaranteed to load it from the desired path? - mvar = os.environ.get('MY_CONFIG') - if mvar is not None: - mycfg_dir = Path(mvar) - else: - mycfg_dir = Path(appdirs.user_config_dir('my')) - return mycfg_dir - - # separate function to present namespace pollution def setup_config() -> None: import sys import warnings from typing import Optional + from .preinit import get_mycfg_dir mycfg_dir = get_mycfg_dir() if not mycfg_dir.exists(): diff --git a/my/core/preinit.py b/my/core/preinit.py new file mode 100644 index 0000000..c05ee40 --- /dev/null +++ b/my/core/preinit.py @@ -0,0 +1,13 @@ +from pathlib import Path + +def get_mycfg_dir() -> Path: + import appdirs # type: ignore[import] + import os + # not sure if that's necessary, i.e. could rely on PYTHONPATH instead + # on the other hand, by using MY_CONFIG we are guaranteed to load it from the desired path? + mvar = os.environ.get('MY_CONFIG') + if mvar is not None: + mycfg_dir = Path(mvar) + else: + mycfg_dir = Path(appdirs.user_config_dir('my')) + return mycfg_dir