Created
February 27, 2018 13:37
-
-
Save mangecoeur/25a4658ea9a8d5dbe7dd5373f5537426 to your computer and use it in GitHub Desktop.
Dummy config module for importing a master shared config file from a parent folder.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Background | |
---------- | |
One of the simplest configuration approaches in python is to just use python files, | |
giving you the full power of python - the least hassle approach in a trusted environment. | |
However, importing config modules can be problematic in interactive environments. | |
For example, when using jupyter notebooks organised into sub-folders, | |
we want to access a common config file in the overall project root. | |
However, when using the jupyter notebook, the current working directory | |
is the directory of the notebook and the parent project folder is ignored. | |
Attempting to import a module from the parent directory would raise the error | |
`attempted relative import beyond top-level package`. | |
Instead of copying the config file into every sub-folder and trying to | |
keep them all up to date, copy this module which will find the master | |
config file and import the variables from it. | |
Description | |
----------- | |
This is a dummy config module that loads the real config from the first file called | |
'config.py' found in the parent directories of the current directory. Searches | |
each parent folder in turn for a file of the right name, aborting when it | |
reaches to filesystem root. | |
All non-underscore-prefixed names will be imported from the found config file | |
into this module's global namespace. | |
Usage | |
----- | |
Place a copy of this in every folder where you need to be able to import the config directly, | |
when the parent folders are not part of your current working directory. | |
""" | |
# rename imports to hide from calling module | |
import os as _os | |
import sys as _sys | |
if _os.getcwd() not in _sys.path: | |
_sys.path.append(_os.getcwd()) | |
def _search_for_config(config_name='config.py'): | |
to_scan = _os.path.abspath('..') | |
while True: | |
files = _os.scandir(to_scan) | |
conf_search = [f for f in files if f.name == config_name] | |
if len(conf_search) == 1: | |
conf_dat = conf_search[0] | |
return _os.path.abspath(conf_dat.path) | |
else: | |
# Check if we are in the file system root by checking if trying to going up one level | |
# doesn't change the current path | |
new_path = _os.path.abspath(_os.path.join(to_scan, '..')) | |
if new_path == to_scan: | |
raise RuntimeError(f'No file "{config_name}" found in the parent folders of this folder.' | |
' Config could not be loaded.') | |
else: | |
to_scan = new_path | |
def _load_config_to_current_module(): | |
import runpy | |
conf_path = _search_for_config() | |
config = runpy.run_path(conf_path) | |
for name, value in config.items(): | |
if not name.startswith('_'): | |
globals()[name] = value | |
_load_config_to_current_module() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I don't quite understand why you are renaming os to _os.