Source code for common.prosper_cli

"""Plumbum CLI wrapper for easier/common application writing"""
import logging
import os
import platform

from plumbum import cli

import prosper.common.prosper_logging as p_logging
import prosper.common.prosper_config as p_config


[docs]class ProsperApplication(cli.Application): """parent-wrapper for CLI applications""" debug = cli.Flag( ['d', '--debug'], help='DEBUG MODE: do not write to prod' ) verbose = cli.Flag( ['v', '--verbose'], help='enable verbose messaging' ) def __new__(cls, *args, **kwargs): """wrapper for ensuring expected variables""" if not hasattr(cls, 'config_path'): raise NotImplementedError( '`config_path` required path to default .cfg file' ) return super(cli.Application, cls).__new__(cls) # don't break cli.Application
[docs] @cli.switch( ['--config'], str, help='Override default config') def override_config(self, config_path): # pragma: no cover """override config object with local version""" self.config_path = config_path
[docs] @cli.switch( ['--dump-config'], help='Dump default config to stdout') def dump_config(self): # pragma: no cover """dumps configfile to stdout so users can edit/implement their own""" with open(self.config_path, 'r') as cfg_fh: base_config = cfg_fh.read() print(base_config) exit(2)
[docs] @cli.switch( ['--secret-cfg'], cli.ExistingFile, help='Secrets .ini file for jinja2 template' ) def load_secrets(self, secret_path): """render secrets into config object""" self._config = p_config.render_secrets(self.config_path, secret_path)
_logger = None @property def logger(self): """uses "global logger" for logging""" if self._logger: return self._logger else: log_builder = p_logging.ProsperLogger( self.PROGNAME, self.config.get_option('LOGGING', 'log_path'), config_obj=self.config ) if self.verbose: log_builder.configure_debug_logger() else: id_string = '({platform}--{version})'.format( platform=platform.node(), version=self.VERSION ) if self.config.get_option('LOGGING', 'discord_webhook'): log_builder.configure_discord_logger( custom_args=id_string ) if self.config.get_option('LOGGING', 'slack_webhook'): log_builder.configure_slack_logger( custom_args=id_string ) if self.config.get_option('LOGGING', 'hipchat_webhook'): log_builder.configure_hipchat_logger( custom_args=id_string ) self._logger = log_builder.get_logger() return self._logger _config = None @property def config(self): """uses "global config" for cfg""" if self._config: return self._config else: self._config = p_config.ProsperConfig(self.config_path) return self._config
OPTION_ARGS = ( 'debug', 'port', 'threaded', 'workers' )
[docs]class FlaskLauncher(ProsperApplication): """wrapper for launching (DEBUG) Flask apps""" port = cli.SwitchAttr( ['p', '--port'], int, help='port to launch Flask app on', default=int(os.environ.get('PROSPER_FLASK__port', 8000)), ) threaded = cli.SwitchAttr( ['t', '--threaded'], bool, help='Launch Werkzeug in threaded mode', default=os.environ.get('PROSPER_FLASK__threadded', False), ) workers = cli.SwitchAttr( ['w', '--workers'], int, help='Launch Werkzeug with multiple worker threads', default=int(os.environ.get('PROSPER_FLASK__workers', 1)), )
[docs] def get_host(self): """returns appropriate host configuration Returns: str: host IP (127.0.0.1 or 0.0.0.0) """ if self.debug: return '127.0.0.1' else: return '0.0.0.0'
[docs] def notify_launch(self, log_level='ERROR'): """logs launcher message before startup Args: log_level (str): level to notify at """ if not self.debug: self.logger.log( logging.getLevelName(log_level), 'LAUNCHING %s -- %s', self.PROGNAME, platform.node() ) flask_options = { key: getattr(self, key) for key in OPTION_ARGS } flask_options['host'] = self.get_host() self.logger.info('OPTIONS: %s', flask_options)
[docs]class ProsperTESTApplication(ProsperApplication): # pragma: no cover """test wrapper for CLI tests""" PROGNAME = 'CLITEST' VERSION = '0.0.0' HERE = os.path.abspath(os.path.dirname(__file__)) config_path = os.path.join(HERE, 'common_config.cfg')
[docs] def main(self): """do stuff""" self.logger.info('HELLO WORLD')
if __name__ == '__main__': # pragma: no cover ProsperTESTApplication.run() # test hook