diff --git a/my/core/__main__.py b/my/core/__main__.py index 0dfd7ac..3578037 100644 --- a/my/core/__main__.py +++ b/my/core/__main__.py @@ -320,6 +320,40 @@ def doctor(args: Namespace) -> None: modules_check(args) +def _requires(module: str) -> Sequence[str]: + from .discovery_pure import module_by_name + mod = module_by_name(module) + # todo handle when module is missing + r = mod.requires + if r is None: + error(f"Module {module} has no REQUIRES specification") + sys.exit(1) + return r + + +def module_requires(args: Namespace) -> None: + module: str = args.module + rs = [f"'{x}'" for x in _requires(module)] + eprint(f'dependencies of {module}') + for x in rs: + print(x) + + +def module_install(args: Namespace) -> None: + # TODO hmm. not sure how it's gonna work -- presumably people use different means of installing... + # how do I install into the 'same' environment?? + user: bool = args.user + module: str = args.module + import shlex + cmd = [ + sys.executable, '-m', 'pip', 'install', + *(['--user'] if user else []), # meh + *_requires(module), + ] + eprint('Running: ' + ' '.join(map(shlex.quote, cmd))) + check_call(cmd) + + from argparse import ArgumentParser def parser() -> ArgumentParser: p = ArgumentParser('Human Programming Interface', epilog=''' @@ -336,7 +370,7 @@ Work in progress, will be used for config management, troubleshooting & introspe dp.set_defaults(func=doctor) cp = sp.add_parser('config', help='Work with configuration') - scp = cp.add_subparsers(dest='mode') + scp = cp.add_subparsers(dest='config_mode') if True: ccp = scp.add_parser('check', help='Check config') ccp.set_defaults(func=config_check_cli) @@ -348,6 +382,23 @@ Work in progress, will be used for config management, troubleshooting & introspe mp.add_argument('--all' , action='store_true', help='List all modules, including disabled') mp.set_defaults(func=list_modules) + op = sp.add_parser('module', help='Module management') + ops = op.add_subparsers(dest='module_mode') + if True: + add_module_arg = lambda x: x.add_argument('module', type=str, help='Module name (e.g. my.reddit)') + + opsr = ops.add_parser('requires', help='Print module requirements') + # todo not sure, might be worth exposing outside... + add_module_arg(opsr) + opsr.set_defaults(func=module_requires) + + # todo support multiple + opsi = ops.add_parser('install', help='Install module dependencies') + add_module_arg(opsi) + opsi.add_argument('--user', action='store_true', help='same as pip --user') + opsi.set_defaults(func=module_install) + # todo could add functions to check specific module etc.. + return p diff --git a/my/orgmode.py b/my/orgmode.py index 869b124..0643653 100644 --- a/my/orgmode.py +++ b/my/orgmode.py @@ -1,6 +1,11 @@ ''' Programmatic access and queries to org-mode files on the filesystem ''' + +REQUIRES = [ + 'orgparse', +] + from datetime import datetime, date from pathlib import Path from typing import List, Sequence, Iterable, NamedTuple, Optional diff --git a/tox.ini b/tox.ini index 4844f5b..9dd4e17 100644 --- a/tox.ini +++ b/tox.ini @@ -4,28 +4,34 @@ minversion = 3.5 [testenv] passenv = CI CI_* -# TODO ugh. unclear how to reuse setup.cfg deps in tox -[testenv:tests] + +# just the very core tests with minimal dependencies +[testenv:tests-core] +commands = + pip install -e .[testing] + python3 -m pytest \ + tests/core.py \ + tests/get_files.py \ + {posargs} + + +# todo maybe also have core tests and misc tests? since ideally want them without dependencies +[testenv:tests-all] # deliberately set to nonexistent path to check the fallback logic +# TODO not sure if need it? setenv = MY_CONFIG = nonexistent commands = - # TODO core & modules should be tested separately? - pip install -e .[testing] - # python -m pytest {posargs} - # TODO install via helper script.. - # my.location.google deps - pip install geopy ijson + hpi module install my.location.google + pip install ijson # optional dependency - # my.time.tz.via_location dep - pip install timezonefinder + hpi module install my.time.tz.via_location - # my.calendar.holidays dep - pip install workalendar + hpi module install my.calendar.holidays # my.body.weight dep - pip install orgparse + hpi module install my.orgmode python3 -m pytest tests \ # ignore some tests which might take a while to run on ci.. @@ -45,7 +51,7 @@ commands = whitelist_externals = cat commands = pip install -e .[testing,optional] - pip install orgparse # used it core.orgparse? + pip install orgparse # used it core.orgmode? # todo add tests? python3 -m mypy -p my.core \ --txt-report .coverage.mypy-core \ @@ -56,18 +62,18 @@ commands = # specific modules that are known to be mypy compliant (to avoid false negatives) # todo maybe split into separate jobs? need to add comment how to run -# and install dependencies via AST thing? [testenv:mypy-misc] commands = pip install -e .[testing,optional] - pip install orgparse - pip install git+https://github.com/karlicoss/endoexport - pip install git+https://github.com/karlicoss/ghexport - pip install git+https://github.com/karlicoss/hypexport - pip install git+https://github.com/karlicoss/instapexport - pip install git+https://github.com/karlicoss/pockexport - pip install git+https://github.com/karlicoss/rexport - pip install git+https://github.com/karlicoss/stexport + + hpi module install my.orgmode + hpi module install my.endomondo + hpi module install my.github.ghexport + hpi module install my.hypothesis + hpi module install my.instapaper + hpi module install my.pocket + hpi module install my.reddit + hpi module install my.stackexchange.stexport # TODO fuck. -p my.github isn't checking the subpackages?? wtf... python3 -m mypy \