Skip to content

Instantly share code, notes, and snippets.

@cluelessperson
Last active May 6, 2019 02:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cluelessperson/11117723633076bacf1fdd447f5666ae to your computer and use it in GitHub Desktop.
Save cluelessperson/11117723633076bacf1fdd447f5666ae to your computer and use it in GitHub Desktop.
from .util.logging import root_logger as logger
from .util.config import FileConfig, GCloudFileConfig, EnvironmentalVariableConfig, CliConfig, ConfigCombiner
config = ConfigCombiner(
[
FileConfig,
GCloudFileConfig,
EnvironmentalVariableConfig,
CliConfig
],
parent_logger=logger
)
print(config.log_level)
import logging, pathlib, json, sys, subprocess, os
from .. import version
from .logging import root_logger as logger
class Config(object):
def __init__(self, parent_logger=logger):
self.log = parent_logger.getChild(self.__class__.__name__)
self.config = {"log_level": "INFO"}
def __getattr__(self, attr):
try:
return self.config[attr]
except KeyError:
return None
def __setattr__(self, attr, value):
if attr in ["log", "config"]:
super(Config, self).__setattr__(attr, value)
else:
self.config[attr] = value
class FileConfig(Config):
def __init__(self, *args, path="config.json", required=False, **kwargs):
super(FileConfig, self).__init__(*args, **kwargs)
self._load_config(path, required=required)
def _load_config(self, path, required=False):
path = pathlib.Path(path)
if path.is_file():
self.log.info("Config file found. - {}")
with open(path, 'r') as f:
config = json.load(f)
self.config.update(config)
else:
log = "Config file not found. - {}".format(path)
if required:
self.log.fatal(log)
raise FileNotFoundError(path)
else:
self.log.info(log)
class GCloudFileConfig(Config):
def __init__(self, *args, **kwargs):
super(GCloudFileConfig, self).__init__(*args, **kwargs)
project_name = self._get_cloud_project_name()
file_config = FileConfig(path=f"{project_name}.json", required=False, parent_logger=self.log)
self.config.update(file_config.config)
@staticmethod
def _get_cloud_project_name():
call = "gcloud config get-value project"
result = subprocess.check_output(call.split(" "), stderr=open(os.devnull, 'wb'))
project_name = result.decode('utf-8').strip()
return project_name
class EnvironmentalVariableConfig(Config):
def __init__(self, *args, **kwargs):
super(EnvironmentalVariableConfig, self).__init__(*args, **kwargs)
environmental_variable_config = self._get_environmental_key_values()
self.log.info(f"Checking for environmental variables. ( {version.NAME.upper()}_KEY )")
if environmental_variable_config:
self.log.info(environmental_variable_config)
self.config.update(environmental_variable_config)
@staticmethod
def _get_environmental_key_values():
def parse_environmental_variables():
prefix = version.NAME.upper() + "_"
for key in os.environ:
if key.startswith(prefix) and len(key) > len(prefix):
value = os.environ[key]
key = key[len(prefix):].lower()
yield key, value
return dict(parse_environmental_variables())
class CliConfig(Config):
def __init__(self, *args, **kwargs):
super(CliConfig, self).__init__(*args, **kwargs)
cli_config = self._get_cli_config()
self.log.debug(cli_config)
# if config file specified, load that
if 'config' in cli_config:
self.log.info("Config file specified. - {}".format(cli_config['config']))
file_config = FileConfig(path=cli_config['config'], required=True, parent_logger=self.log)
self.config.update(file_config.config)
self.config.update(cli_config)
@staticmethod
def _get_cli_config():
def get_cli_key_vals():
for i, arg in enumerate(sys.argv):
if "--" in arg and len(sys.argv)-1 > i:
key = arg[2:]
value = sys.argv[i+1]
yield key, value
return dict(get_cli_key_vals())
class ConfigCombiner(Config):
def __init__(self, config_classes, *args, **kwargs):
super(ConfigCombiner, self).__init__(*args, **kwargs)
for config_class in config_classes:
config = config_class(*args, parent_logger=self.log)
self.config.update(config.config)
(venv) zac@zwafer:~/work/PyCharmProjects/paste_pizza$ python3 -m paste_pizza
20190506T015138.109483Z | DEBUG | paste_pizza | Starting up. - 20190505_0_dev
20190506T015138.117844Z | INFO | paste_pizza.ConfigCombiner.FileConfig | Config file not found. - config.json
20190506T015138.334013Z | INFO | paste_pizza.ConfigCombiner.GCloudFileConfig.FileConfig | Config file not found. - paste-pizza.json
20190506T015138.334285Z | INFO | paste_pizza.ConfigCombiner.EnvironmentalVariableConfig | Checking for environmental variables. ( PASTE_PIZZA_KEY )
20190506T015138.334379Z | INFO | paste_pizza.ConfigCombiner.EnvironmentalVariableConfig | {'log_level': 'INFO'}
20190506T015138.334475Z | DEBUG | paste_pizza.ConfigCombiner.CliConfig | {}
INFO
(venv) zac@zwafer:~/work/PyCharmProjects/paste_pizza$ python3 -m paste_pizza --config cli.json --log_level DEBUG
20190506T015224.611133Z | DEBUG | paste_pizza | Starting up. - 20190505_0_dev
20190506T015224.619668Z | INFO | paste_pizza.ConfigCombiner.FileConfig | Config file not found. - config.json
20190506T015224.836832Z | INFO | paste_pizza.ConfigCombiner.GCloudFileConfig.FileConfig | Config file not found. - paste-pizza.json
20190506T015224.837123Z | INFO | paste_pizza.ConfigCombiner.EnvironmentalVariableConfig | Checking for environmental variables. ( PASTE_PIZZA_KEY )
20190506T015224.837206Z | INFO | paste_pizza.ConfigCombiner.EnvironmentalVariableConfig | {'log_level': 'INFO'}
20190506T015224.837308Z | DEBUG | paste_pizza.ConfigCombiner.CliConfig | {'config': 'cli.json', 'log_level': 'DEBUG'}
20190506T015224.837390Z | INFO | paste_pizza.ConfigCombiner.CliConfig | Config file specified. - cli.json
20190506T015224.837522Z | CRITICAL | paste_pizza.ConfigCombiner.CliConfig.FileConfig | Config file not found. - cli.json
Traceback (most recent call last):
File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/zac/work/PyCharmProjects/paste_pizza/paste_pizza/__main__.py", line 11, in <module>
parent_logger=logger
File "/home/zac/work/PyCharmProjects/paste_pizza/paste_pizza/util/config.py", line 112, in __init__
config = config_class(*args, parent_logger=self.log)
File "/home/zac/work/PyCharmProjects/paste_pizza/paste_pizza/util/config.py", line 91, in __init__
file_config = FileConfig(path=cli_config['config'], required=True, parent_logger=self.log)
File "/home/zac/work/PyCharmProjects/paste_pizza/paste_pizza/util/config.py", line 27, in __init__
self._load_config(path, required=required)
File "/home/zac/work/PyCharmProjects/paste_pizza/paste_pizza/util/config.py", line 40, in _load_config
raise FileNotFoundError(path)
FileNotFoundError: cli.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment