def test_load_out(self): file_path = os.path.join(os.path.dirname(__file__), 'files', 'config.yaml') self.assertEqual(ConfigFile.load_out(file_path), {"file": "yaml"}) file_path = os.path.join(os.path.dirname(__file__), 'files', 'config.json') self.assertEqual(ConfigFile.load_out(file_path), {"file": "json"})
def show(self, read_from_disc=False): if read_from_disc: self._config_file_obj = ConfigFile(self._config_file_path) self._config_file_obj.set_valid_keys(self._valid_keys) self._config_file_obj.load() else: if self._config_file_obj is None: raise RuntimeError("I need the run time obj") self._config_popup = Gtk.Window() self._config_popup.set_default_size(200, 200) self._config_popup.connect('delete_event', self._close_config_cb) table = Gtk.Table(12, 1, True) self._config_popup.add(table) row = 1 for i in self._config_items: hbox = self._create_param(i) table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) row = row + 1 hbox = Gtk.HBox() save_button = Gtk.Button.new_with_label('Save') save_button.set_size_request(50, 15) save_button.connect('pressed', self._save_config_cb) hbox.add(save_button) cancel_button = Gtk.Button.new_with_label('Cancel') cancel_button.set_size_request(50, 15) cancel_button.connect('pressed', self._close_config_cb) hbox.add(cancel_button) table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) self._config_popup.show_all()
class TestConfigFile(unittest.TestCase): configfile = None def setUp(self): # 创建对象 config_dir = os.path.abspath( os.path.join(os.path.dirname(__file__), 'files')) self.configfile = ConfigFile(config_dir) def test_is_app_exist(self): file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), 'files', 'config.json')) self.assertEqual(self.configfile.is_app_exist('config', 'json'), file_path) self.assertEqual(self.configfile.is_app_exist('config', 'None'), False) def test_load_app(self): self.assertEqual(self.configfile.load_app('config'), {"file": "yaml"}) self.assertEqual(self.configfile.load_app('None'), None) def test_load_out(self): file_path = os.path.join(os.path.dirname(__file__), 'files', 'config.yaml') self.assertEqual(ConfigFile.load_out(file_path), {"file": "yaml"}) file_path = os.path.join(os.path.dirname(__file__), 'files', 'config.json') self.assertEqual(ConfigFile.load_out(file_path), {"file": "json"}) def test_load_app_json(self): self.assertEqual(self.configfile.load_app_json('config'), {"file": "json"}) def test_dynamic_json(self): self.assertEqual( self.configfile.load_dynamic_json('config', callback, 3), {"timestamp": timestamp1}) time.sleep(1) self.assertEqual( self.configfile.load_dynamic_json('config', callback, 3), {"timestamp": timestamp1}) time.sleep(3) self.assertNotEqual( self.configfile.load_dynamic_json('config', callback, 3), {"timestamp": timestamp1}) file_path = os.path.join(self.configfile.config_dir, '.'.join(['config', 'dynamic', 'json'])) self.assertTrue(os.path.isfile(file_path)) self.configfile.del_dynamic_json('config') self.assertFalse(os.path.isfile(file_path))
def show(self, read_from_disc=False): if read_from_disc: self._config_file_obj = ConfigFile(self._config_file_path) self._config_file_obj.set_valid_keys(self._valid_keys) self._config_file_obj.load() else: if self._config_file_obj is None: raise RuntimeError("I need the run time obj") self._config_popup = gtk.Window() self._config_popup.set_default_size(200, 200) self._config_popup.connect('delete_event', self._close_config_cb) table = gtk.Table(12, 1, True) self._config_popup.add(table) row = 1 for i in self._config_items: hbox = self._create_param(i) table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) row = row + 1 hbox = gtk.HBox() save_button = gtk.Button('Save') save_button.set_size_request(50, 15) save_button.connect('pressed', self._save_config_cb) hbox.add(save_button) cancel_button = gtk.Button('Cancel') cancel_button.set_size_request(50, 15) cancel_button.connect('pressed', self._close_config_cb) hbox.add(cancel_button) table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) self._config_popup.show_all()
def __init__(self): print('Midi input devices:', mido.get_input_names()) print('Midi output devices:', mido.get_output_names()) selected_input = ConfigFile.get_midi_input() selected_output = ConfigFile.get_midi_output() print('Using midi input device:', selected_input) print('Using midi output device:', selected_output) self._control_change_dict = {} self._note_dict = {} is_connected = False waiting_time = 3 while not is_connected : try: self._outport = mido.open_output(selected_output) # pylint: disable=no-member self._inport = mido.open_input(selected_input, callback=self.handle_message) # pylint: disable=no-member is_connected = True except Exception: print(f"Connection to X-Touch-Mini not possible. Connected? Retry in {waiting_time}s.") time.sleep(waiting_time)
def maintain(cliargs): # 'conf' must be imported by the subpackages, so assign it globally global conf conf = ConfigFile({ 'db_path': cliargs.db_path, 'init_env': str(cliargs.init_env), 'revise': str(cliargs.revise), 'migrate': str(cliargs.migrate), }) models, api, static = _pre_run(False) if conf.get_bool('init_env'): models.init_migrations() elif conf.get_bool('revise'): models.create_revision() elif conf.get_bool('migrate'): models.create_migration() else: raise ValueError("Unspecified maintenance command")
def main(): parse_conf = ConfigFile('config.cfg') parse_conf.read_config_file() if not parse_conf.username: username = raw_input('Enter your username: '******'Logging in as {}'.format(username) password = getpass('Enter your password: '******'folder title'] download_images = raw_input('Download images? (y = yes, defaults to no) ') if download_images.lower() == 'y': dtl.download_images = True else: dtl.download_images = False dtl.base_path = os.path.join(dtl.base_path, dtl.docs_folder) print 'File path to save to is: ' + dtl.base_path dtl.download_folder_contents(docs_folder_feed['folder feed']) utilfunc.check_for_tex_extension(dtl.base_path) dtl.cleanup_leftover_comments() comp_latex = CompileLaTeX(dtl.base_path) comp_latex.replace_quote_characters() main_latex_file = raw_input('Enter the name of the main LaTeX file: ') if main_latex_file: comp_latex.compile_to_latex(main_latex_file) else: print 'No file name entered.' if not parse_conf.config_exists(): config_saved = """\ Your username ({}) and chosen folder ({}) have been saved in {}""".format( username, dtl.docs_folder, os.path.join(dtl.base_path, 'config.cfg')) print textwrap.dedent(config_saved) parse_conf.write_config_file(username=username, folder_name=dtl.docs_folder)
def __init__( self, collection_name, terms, event, pipe, total, config_data): self.log = logging.getLogger(self.__class__.__name__) self.collection_name = collection_name self.event = event self.terms = terms self.raw_pipe = pipe self.config_data = config_data self.listener = None self.client = None self.config = ConfigFile(config_data=self.config_data) self.initial_total = total if total is not None else 0 self.pipe = PipeMessenger(self.raw_pipe) self.client_status = CaptureStatus(CaptureStatus.STATUS_UNKNOWN)
def main(): parse_conf = ConfigFile('config.cfg') parse_conf.read_config_file() if not parse_conf.username: username = raw_input('Enter your username: '******'Logging in as {}'.format(username) password = getpass('Enter your password: '******'folder title'] download_images = raw_input('Download images? (y = yes, defaults to no) ') if download_images.lower() == 'y': dtl.download_images = True else: dtl.download_images = False dtl.base_path = os.path.join(dtl.base_path, dtl.docs_folder) print 'File path to save to is: ' + dtl.base_path dtl.download_folder_contents(docs_folder_feed['folder feed']) utilfunc.check_for_tex_extension(dtl.base_path) dtl.cleanup_leftover_comments() comp_latex = CompileLaTeX(dtl.base_path) comp_latex.replace_quote_characters() main_latex_file = raw_input('Enter the name of the main LaTeX file: ') if main_latex_file: comp_latex.compile_to_latex(main_latex_file) else: print 'No file name entered.' if not parse_conf.config_exists(): config_saved = """\ Your username ({}) and chosen folder ({}) have been saved in {}""".format(username, dtl.docs_folder, os.path.join(dtl.base_path, 'config.cfg')) print textwrap.dedent(config_saved) parse_conf.write_config_file(username=username, folder_name=dtl.docs_folder)
def test_wizard_from_config_file_path(test_config_file): keys = {} keys["nick"] = {"type": "text"} keys["account_id"] = {"type": "text"} keys["server"] = {"type": "text"} keys["port"] = {"type": "text"} keys["password"] = {"type": "text"} keys["register"] = {"type": "text"} c = ConfigFile(test_config_file) c.set_valid_keys(keys) c.set("nick", "rgs") c.set("account_id", "rgs@andromeda") c.set("server", "andromeda") c.set("port", 5223) c.set("password", "97c74fa0dc3b39b8c87f119fa53cced2b7040786") c.set("register", True) c.save() config_w = ConfigWizard(test_config_file) config_items = [ {"item_label": "Nickname", "item_type": "text", "item_name": "nick"}, {"item_label": "Account ID", "item_type": "text", "item_name": "account_id"}, {"item_label": "Server", "item_type": "text", "item_name": "server"}, {"item_label": "Port", "item_type": "text", "item_name": "port"}, {"item_label": "Password", "item_type": "text", "item_name": "password"}, {"item_label": "Register", "item_type": "text", "item_name": "register"}] config_w.set_config_items(config_items) config_w.show(True)
else: scan() return if not op.isdir("data"): os.mkdir("data") with utils.dirBongdi("data"): MY_PATH = os.getcwd() # op.dirname(__file__) TARGET_DIR = op.join(MY_PATH, REPO_NAME) CONFIG_FILE = op.join(MY_PATH, "configuration.do.not.edit") if op.isfile(CONFIG_FILE): pass # so that configFile can be made global else: print("Configuration file not found! Are you trying to setup?") if utils.replyIsYes(): utils.setup(TARGET_DIR, CONFIG_FILE) else: raise utils.UserCausedError("User refused to continue with setup") shutil.rmdir("data") configFile = ConfigFile(CONFIG_FILE, REPO_NAME) main()
class ClientWorker(object): """test...""" def __init__( self, collection_name, terms, event, pipe, total, config_data): self.log = logging.getLogger(self.__class__.__name__) self.collection_name = collection_name self.event = event self.terms = terms self.raw_pipe = pipe self.config_data = config_data self.listener = None self.client = None self.config = ConfigFile(config_data=self.config_data) self.initial_total = total if total is not None else 0 self.pipe = PipeMessenger(self.raw_pipe) self.client_status = CaptureStatus(CaptureStatus.STATUS_UNKNOWN) def initialize(self): """initialize the worker.""" output_config = self.config.getValue("output", {}) self.listener = RotatingFileListener( collection_name=self.collection_name, **output_config ) self.listener.data_callback = functools.partial( self.dataCallback, (self,) ) self.listener.stats.total = self.initial_total # create client self.client = TwitterClient( listener=self.listener, keywords=self.terms ) self.client.configure(self.config) # last stat update self.last_stat_update_time = datetime.now() def updateStatus(self, status): if status != self.client_status.value: self.client_status.value = status self.pipe.sendStatus(status) def shutdown(self): """shutdown the worker.""" self.updateStatus(CaptureStatus.STATUS_STOPPING) try: self.client.shutdown() except Exception: self.log.exception("Exception during client shutdown") try: self.listener.shutdown() except Exception: self.log.exception("Exception while shutting down listener") self.updateStatus(CaptureStatus.STATUS_STOPPED) def run(self): """run the collection.""" self.updateStatus(CaptureStatus.STATUS_STARTING) self.client.initialize() self.client.run() self.log.debug("run returned. ClientStatus -> Stopped") # self.updateStatus(CaptureStatus.STATUS_STOPPED) def dataCallback(self, listener, stats): """handle data callback by sending periodic updates.""" # self.log.debug("worker callback!") # self.log.debug("self: %s", repr(self)) # self.log.debug("listener: %s", repr(listener)) # self.log.debug("stats: %s", repr(stats)) # quitting? if self.event is None or self.event.is_set(): return False # update status if necessary self.updateStatus(CaptureStatus.STATUS_STARTED) now = datetime.now() delta = now - self.last_stat_update_time if delta.total_seconds() > 5: received = stats.received stats.calculate_rate() self.pipe.sendUpdate(now, received, stats.rate, stats.total) self.last_stat_update_time = now return True
from flask import Flask, send_file, make_response, redirect, request from ezmysql import TableDef from configfile import ConfigFile from requests import post as http_post CONFIG = ConfigFile('./itapps.cfg') DB_server = CONFIG.Get('DBServer') DB_user = CONFIG.Get('DBUser') DB_password = CONFIG.Get('DBPassword') TABLES = Config.Get('DBTables').split(',') # Configure table objects TABLES = [{"name" : a,"def" : TableDef(DB_server,DB_user,DB_password,a)} for a in TABLES] # Pull schema for thisTable in DB_tables: thisTable['schema'] = thisTable['def'].Schema() ROOT = '/var/www/python/dbedit' app = Flask(__name__) @app.route('/') def getroot(): return render_template('{}/templates/show_tables.html'.format(ROOT),tables=[a['name'] for a in DB_tables]) @app.routes('/<table>/list') def TableList(table): tableAr = [a for a in DB_tables if a['name'] == table] if len(tableAr) == 1:
class ConfigWizard(): """Simple configuration wizard window.""" def __init__(self, config_file_path): self._config_items = [] self._config_entries = {} self._config_file_path = config_file_path self._config_file_obj = None """ [ {item_label, item_type, item_name, item_with_value} , ... ] """ def set_config_items(self, items): self._config_items = items keys = {} for i in self._config_items: keys[i["item_name"]] = {"type": i["item_type"]} self._valid_keys = keys def set_config_file_obj(self, obj): self._config_file_obj = obj def get_config_file_obj(self, obj): return self._config_file_obj def show(self, read_from_disc=False): if read_from_disc: self._config_file_obj = ConfigFile(self._config_file_path) self._config_file_obj.set_valid_keys(self._valid_keys) self._config_file_obj.load() else: if self._config_file_obj is None: raise RuntimeError("I need the run time obj") self._config_popup = gtk.Window() self._config_popup.set_default_size(200, 200) self._config_popup.connect('delete_event', self._close_config_cb) table = gtk.Table(12, 1, True) self._config_popup.add(table) row = 1 for i in self._config_items: hbox = self._create_param(i) table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) row = row + 1 hbox = gtk.HBox() save_button = gtk.Button('Save') save_button.set_size_request(50, 15) save_button.connect('pressed', self._save_config_cb) hbox.add(save_button) cancel_button = gtk.Button('Cancel') cancel_button.set_size_request(50, 15) cancel_button.connect('pressed', self._close_config_cb) hbox.add(cancel_button) table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) self._config_popup.show_all() def _save_config_cb(self, widget): try: self._do_save_config() except Exception, e: w = gtk.Window() l = gtk.Label(e.message) w.add(l) w.show_all() finally:
def main_app(offline: bool): global_storage = GlobalStorage() sm = None aq = None ae = None if not offline: sm = SimConnect() aq = AircraftRequests(sm, _time=200) ae = AircraftEvents(sm) global_storage.set_aircraft_events(ae) global_storage.set_aircraft_requests(aq) else: global_storage.set_aircraft_events(MockAircraftEvents()) global_storage.set_aircraft_requests(MockAircraftRequests()) aircraft = aq.get('TITLE') print("Current aircraft:", aircraft) outport = mido.open_output('X-TOUCH MINI 1') # pylint: disable=no-member control_change_dict = {} note_dict = {} def handle_message(msg: mido.Message): # print(msg) if msg.type == 'control_change': if msg.control in control_change_dict: control_change_dict[msg.control].on_cc_data(msg.value) elif msg.type == 'note_on': if msg.note in note_dict: note_dict[msg.note].on_note_data(True) elif msg.type == 'note_off': if msg.note in note_dict: note_dict[msg.note].on_note_data(False) inport = mido.open_input('X-TOUCH MINI 0', callback=handle_message) # pylint: disable=no-member for e in range(1, 17): encoder = RotaryEncoder(e, outport) global_storage.add_encoder(encoder) for b in range(1, 33): btn = PushButton(b, outport) global_storage.add_button(btn) for f in range(1, 3): fader = Fader(f) global_storage.add_fader(fader) c = ConfigFile(aircraft) c.configure() triggers = c.triggers for encoder in GlobalStorage().encoders: control_change_dict[encoder.rotary_control_channel] = encoder note_dict[encoder.button_note] = encoder for btn in GlobalStorage().buttons: note_dict[btn.button_note] = btn for f in GlobalStorage().faders: control_change_dict[f.control_channel] = f triggers[0].on_simvar_data(1.0) while True: for obj in GlobalStorage().all_elements: if obj.bound_simvar and aq: sv = aq.get(obj.bound_simvar) obj.on_simvar_data(sv) current_aircraft = aq.get('TITLE') if current_aircraft and aircraft != current_aircraft: print("Aircraft changed from", aircraft, "to", current_aircraft) break time.sleep(0.05) global_storage.clear() inport.close() outport.close()
'root': { 'level': 'INFO', 'handlers': ['wsgi'] } }) app = Flask(__name__) # Debug mode (development environment) app.debug = False debug_mode = False # Init modules app.config.from_object(Config) configfile = ConfigFile(app, 'main.cfg') csvreader = CSVReader(configfile.laser_etch_QC['PNFile']) db = SQLAlchemy(app) migrate = Migrate(app, db) login = LoginManager(app) login.login_view = 'login' socketio = SocketIO(app, manage_session=False) Session(app) # Serial setup # PLC serial plc_ser = None from flask_serial import Serial
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see http://www.gnu.org/licenses/gpl-3.0.html . from irc import IrcClient from configfile import ConfigFile import man, xkcd, translator import datetime, getpass, os, random, re, select, signal, sys, time if len(sys.argv) != 2: print "Usage: " + sys.argv[0] + " path/to/config/file" sys.exit(1) config = ConfigFile(sys.argv[1]) server_and_port = config.get_server() if not server_and_port: print "Config file has no server entry" sys.exit(1) server, port = server_and_port channels = config.get_channels() if not channels: print "Config file has no channel entry" sys.exit(1) nick = config.get_nick() if not nick: print "Config file has no nick entry" sys.exit(1) realname = config.get_realname()
def _openConfig(self, path): return ConfigFile(path, self.CONF_VERSION)
class ConfigWizard(): """Simple configuration wizard window.""" def __init__(self, config_file_path): self._config_items = [] self._config_entries = {} self._config_file_path = config_file_path self._config_file_obj = None """ [ {item_label, item_type, item_name, item_with_value} , ... ] """ def set_config_items(self, items): self._config_items = items keys = {} for i in self._config_items: keys[i["item_name"]] = {"type": i["item_type"]} self._valid_keys = keys def set_config_file_obj(self, obj): self._config_file_obj = obj def get_config_file_obj(self, obj): return self._config_file_obj def show(self, read_from_disc=False): if read_from_disc: self._config_file_obj = ConfigFile(self._config_file_path) self._config_file_obj.set_valid_keys(self._valid_keys) self._config_file_obj.load() else: if self._config_file_obj is None: raise RuntimeError("I need the run time obj") self._config_popup = Gtk.Window() self._config_popup.set_default_size(200, 200) self._config_popup.connect('delete_event', self._close_config_cb) table = Gtk.Table(12, 1, True) self._config_popup.add(table) row = 1 for i in self._config_items: hbox = self._create_param(i) table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) row = row + 1 hbox = Gtk.HBox() save_button = Gtk.Button.new_with_label('Save') save_button.set_size_request(50, 15) save_button.connect('pressed', self._save_config_cb) hbox.add(save_button) cancel_button = Gtk.Button.new_with_label('Cancel') cancel_button.set_size_request(50, 15) cancel_button.connect('pressed', self._close_config_cb) hbox.add(cancel_button) table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) self._config_popup.show_all() def _save_config_cb(self, widget): try: self._do_save_config() except Exception as e: w = Gtk.Window() l = Gtk.Label(e.message) w.add(l) w.show_all() finally: self._config_popup.hide() def _do_save_config(self): for i in self._config_items: param_name = i["item_name"] v = self._config_entries[param_name] if v.__class__ is Gtk.Entry: value = v.get_text() elif v.__class__ is Gtk.CheckButton: value = v.get_active() else: raise RuntimeError("Don't recognize the class %s" % type(v)) self._config_file_obj.set(param_name, value) self._config_file_obj.save() """ {item_label, item_type, item_name, item_with_value} """ def _create_param(self, opts): param_name = opts["item_name"] with_value = opts["item_with_value"] if "item_with_value" in opts \ else True hbox = Gtk.HBox() if opts["item_type"] == "text": entry = Gtk.Entry() entry.set_size_request(150, 25) if with_value: value = self._config_file_obj.get(param_name, True) entry.set_text(str(value)) elif opts["item_type"] == "boolean": entry = Gtk.CheckButton() if with_value: value = self._config_file_obj.get(param_name, True) entry.set_active(value) self._config_entries[param_name] = entry label = Gtk.Label(opts["item_label"] + ': ') label.set_alignment(1.0, 0.5) label.set_size_request(100, 25) hbox.add(label) hbox.add(entry) return hbox def _close_config_cb(self, widget, event=None): self._config_popup.hide()
# but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see http://www.gnu.org/licenses/gpl-3.0.html . import irc from configfile import ConfigFile import misc import datetime, getpass, os, random, re, select, signal, sys, time if len(sys.argv) != 2: print "Usage: " + sys.argv[0] + " path/to/config/file" sys.exit(1) config = ConfigFile(sys.argv[1]) pipe = os.popen('git log --pretty=format:"git commit %h (%s)"') version = pipe.readline().strip() pipe.close() commandref = u'''!help <key> -- get help about <key> !man <section> <name> -- get the URL to an online man page !synopsis <section> <name> -- get the SYNOPSIS section of the specified man page !man <criteria> -- search for an online man page !xkcd -- get a link to a random xkcd comic !xkcd <number> -- get the link to the specified xkcd !xkcd-linux -- get a random xkcd comic that mentions Linux (Note: you can use "geek" instead of "linux" in the above command for geeky comics) !time -- show the current time !time <strftime> -- show the current time, with custom formatting. See "man strftime" for more.
def setUp(self): # 创建对象 config_dir = os.path.abspath( os.path.join(os.path.dirname(__file__), 'files')) self.configfile = ConfigFile(config_dir)
base_conf = ConfigFile( ( { 'host': 'localhost', 'port': '13502', 'proxy_url': '', 'origins': '', 'ssl_cert': '', 'ssl_key': '', 'workers': '1', 'force_development_server': 'false', 'db_path': os.path.join(datadir, 'db.sqlite'), 'client_conf': os.path.join(configdir, 'client.json'), 'user_script_dir': '/usr/share/wiki-monkey/' # No need to support 'debug' in the configuration file }, { 'archwiki': ( { 'origins': 'https://wiki.archlinux.org', }, {}, ), 'wikipedia': ( { 'origins': 'https://en.wikipedia.org', }, {}, ), }, ), inherit_options=True, )
# -*- coding: utf-8 -*- # Author: Ztj import logging import logging.config import os from configfile import ConfigFile from registry import Registry from libs.logger import JsonLogger """全局设置""" logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') """全局变量""" service_root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) """初始化配置""" GlobalConfigFile = ConfigFile(os.path.join(service_root_path, 'configs')) """加载配置文件""" app_options = Registry(GlobalConfigFile.load_app('app')) """配置日志""" log_options = GlobalConfigFile.load_app('log') if log_options is not None: logging.setLoggerClass(JsonLogger) logging.config.dictConfig(log_options) json_logger = logging.getLogger('json')