Merge pull request #13 from karlicoss/my.config

initial steps for my.config
This commit is contained in:
karlicoss 2020-04-11 22:30:39 +01:00 committed by GitHub
commit f31ff71e6f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 90 additions and 38 deletions

26
demo.py
View file

@ -30,20 +30,19 @@ def run():
], stderr=DEVNULL) ], stderr=DEVNULL)
# #
# 4. point my.config to the Hypothesis data
# 4. create private with_my file and set path to private configuration
with_my = 'my_repo/with_my'
copy('my_repo/with_my.example', with_my)
mycfg_root = abspath('my_repo/mycfg_template') mycfg_root = abspath('my_repo/mycfg_template')
# edit the config and set path to private configuration init_file = Path(mycfg_root) / 'my/config/__init__.py'
my = Path(with_my).read_text().replace("MYCFG_DIR = ''", "MYCFG_DIR = '{}'".format(mycfg_root)) init_file.write_text(init_file.read_text().replace(
Path(with_my).write_text(my) '/path/to/hypothesis/data',
hypothesis_backups,
))
# #
# 5. now we can use it! # 4. now we can use it!
os.chdir(my_repo)
check_call(['my_repo/with_my', 'python3', '-c', ''' check_call(['python3', '-c', '''
import my.hypothesis import my.hypothesis
pages = my.hypothesis.get_pages() pages = my.hypothesis.get_pages()
@ -54,7 +53,12 @@ for page in islice(pages, 0, 8):
print('Title: ' + page.title) print('Title: ' + page.title)
print('{} annotations'.format(len(page.highlights))) print('{} annotations'.format(len(page.highlights)))
print() print()
''']) '''], env={
# this is just to prevent demo.py from using real data
# normally, it will rely on having my.config in ~/.config/my
'MY_CONFIG': mycfg_root,
**os.environ,
})
# that should result in something like this: # that should result in something like this:

8
doc/DEVELOPMENT.org Normal file
View file

@ -0,0 +1,8 @@
* IDE setup: make sure my.config is in your package search path
In runtime, ~my.config~ is imported from the user config directory dynamically.
However, Pycharm/Emacs/whatever you use won't be able to figure that out, so you'd need to adjust your IDE configuration.
- Pycharm: basically, follow the instruction [[https://stackoverflow.com/a/55278260/706389][here]]
i.e. create a new interpreter configuration (e.g. name it "Python 3.7 (for HPI)"), and add =~/.config/my=.

View file

@ -1,12 +0,0 @@
# TODO how to make it mypy friendly? maybe defensive import? or mypy config? or interface file?
try:
import mycfg
except ImportError:
import warnings
warnings.warn("mycfg package isn't found! That might result in issues")
from . import mycfg_stub as mycfg # type: ignore[no-redef]
import sys
sys.modules['mycfg'] = mycfg
del sys

View file

@ -1,13 +1,15 @@
""" """
Hypothes.is highlights and annotations Hypothes.is highlights and annotations
""" """
from . import init
from .common import PathIsh from .common import PathIsh
import mycfg.repos.hypexport as hypexport import my.config.repos.hypexport as hypexport
from my.config.repos.hypexport import dal
from mycfg import paths from my.config import hypothesis as config
export_path: PathIsh = paths.hypothesis.export_path export_path: PathIsh = config.export_path
### ###
@ -17,7 +19,6 @@ from .common import get_files, cproperty, group_by_key
from .error import Res, sort_res_by from .error import Res, sort_res_by
from mycfg.repos.hypexport import dal
# TODO weird. not sure why e.g. from dal import Highlight doesn't work.. # TODO weird. not sure why e.g. from dal import Highlight doesn't work..

47
my/init.py Normal file
View file

@ -0,0 +1,47 @@
'''
A hook to insert user's config directory into Python's search path.
- Ideally that would be in __init__.py (so it's executed without having to import explicityly)
But, with namespace packages, we can't have __init__.py in the parent subpackage
(see http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html#the-init-py-trap)
Please let me know if you are aware of a better way of dealing with this!
'''
# separate function to present namespace pollution
def setup_config():
from pathlib import Path
import sys
import os
import warnings
# 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:
# TODO use appdir??
cfg_dir = Path('~/.config').expanduser()
mycfg_dir = cfg_dir / 'my'
# TODO maybe try importing first and if it's present, don't do anything?
if not mycfg_dir.exists():
warnings.warn(f"my.config package isn't found! (expected at {mycfg_dir}). This might result in issues.")
from . import mycfg_stub as mycfg
sys.modules['my.config'] = mycfg
else:
mp = str(mycfg_dir)
if mp not in sys.path:
sys.path.insert(0, mp)
try:
import my.config
except ImportError as ex:
warnings.warn(f"Importing my.config failed! (error: {ex}). This might result in issues.")
setup_config()
del setup_config

View file

@ -0,0 +1,8 @@
"""
Feel free to remove this if you don't need it/add your own custom settings and use them
"""
class hypothesis:
# expects outputs from https://github.com/karlicoss/hypexport
# (it's just the standard Hypothes.is export format)
export_path = '/path/to/hypothesis/data'

View file

@ -1,6 +0,0 @@
class paths:
"""
Feel free to remove this if you don't need it/add your own custom settings and use them
"""
class hypothesis:
export_path = '/tmp/my_demo/backups/hypothesis'

View file

@ -37,6 +37,7 @@ def main():
'testing': [ 'testing': [
'pytest', 'pytest',
'pytz', 'pytz',
'pylint',
], ],
}, },
) )

11
tox.ini
View file

@ -6,13 +6,13 @@ skip_missing_interpreters = True
# TODO ugh. unclear how to reuse setup.cfg deps in tox # TODO ugh. unclear how to reuse setup.cfg deps in tox
[testenv] [testenv]
passenv = CI CI_* CIRCLE* passenv = CI CI_* CIRCLE*
changedir = {toxworkdir}/{envname} setenv = MY_CONFIG = mycfg_template
commands = commands =
# pip install -e .[testing] pip install -e .
# TODO ?? # TODO ??
# python -m pytest {posargs} # python -m pytest {posargs}
python3 -c 'import my; print(my.__path__)' python3 -c 'import my.init; import my.config; print(my.config.__path__)'
python3 -c 'import my; import mycfg.repos' # shouldn't fail at least python3 -c 'import my.init; import my.config; import my.config.repos' # shouldn't fail at least
# TODO run demo.py? just make sure with_my is a bit cleverer? # TODO run demo.py? just make sure with_my is a bit cleverer?
# TODO e.g. under CI, rely on installing # TODO e.g. under CI, rely on installing
@ -40,4 +40,5 @@ skip_install = true
commands = commands =
pip install -e .[testing] pip install -e .[testing]
# for now ignore import errors until I figure out how to import everything for CI checking.. # for now ignore import errors until I figure out how to import everything for CI checking..
python -m pylint -E -d import-error my # TODO FIXME ugh. fix later, after properly switched to my.config
# python -m pylint -E -d import-error my