From d26bd910fa19dfaa726a998ca5585e5ca3659354 Mon Sep 17 00:00:00 2001 From: JimBo CA Date: Tue, 7 Apr 2020 13:50:17 -0700 Subject: [PATCH 1/3] Change logger based on suggestions from @firstone --- polyinterface/__init__.py | 8 +- polyinterface/polyinterface.py | 151 ++++++++++++++++----------------- polyinterface/polylogger.py | 53 ++++++++++++ polyinterface/polylogging.py | 40 --------- 4 files changed, 130 insertions(+), 122 deletions(-) create mode 100755 polyinterface/polylogger.py delete mode 100755 polyinterface/polylogging.py diff --git a/polyinterface/__init__.py b/polyinterface/__init__.py index 0ebe257..7754a5d 100755 --- a/polyinterface/__init__.py +++ b/polyinterface/__init__.py @@ -1,13 +1,9 @@ -import logging -LOGGER = logging.getLogger(__name__) -from .polylogging import set_log_format, setup_log -setup_log(LOGGER) +from .polylogger import LOGGER from .polyinterface import Interface, Node, Controller, unload_interface, get_network_interface - -__version__ = '2.0.36' +__version__ = '2.0.38' __description__ = 'UDI Polyglot v2 Interface' __url__ = 'https://github.com/UniversalDevicesInc/polyglot-v2-python-interface' __author__ = 'James Milne' diff --git a/polyinterface/polyinterface.py b/polyinterface/polyinterface.py index fbb80d1..93f8cda 100755 --- a/polyinterface/polyinterface.py +++ b/polyinterface/polyinterface.py @@ -25,6 +25,7 @@ from threading import Thread,current_thread import time import netifaces +from .polylogger import LOGGER DEBUG = False PY2 = sys.version_info[0] == 2 @@ -49,8 +50,6 @@ def write(self, message): def flush(self): pass -_LOGGER = logging.getLogger('polyinterface') - def get_network_interface(interface='default'): """ Returns the network interface which contains addr, broadcasts, and netmask elements @@ -59,21 +58,21 @@ def get_network_interface(interface='default'): """ # Get the default gateway gws = netifaces.gateways() - _LOGGER.debug("gws: {}".format(gws)) + LOGGER.debug("gws: {}".format(gws)) rt = False if interface in gws: gwd = gws[interface][netifaces.AF_INET] - _LOGGER.debug("gw: {}={}".format(interface,gwd)) + LOGGER.debug("gw: {}={}".format(interface,gwd)) ifad = netifaces.ifaddresses(gwd[1]) rt = ifad[netifaces.AF_INET] - _LOGGER.debug("ifad: {}={}".format(gwd[1],rt)) + LOGGER.debug("ifad: {}={}".format(gwd[1],rt)) return rt[0] - _LOGGER.error("No {} in gateways:{}".format(interface,gws)) + LOGGER.error("No {} in gateways:{}".format(interface,gws)) return {'addr': False, 'broadcast': False, 'netmask': False} def init_interface(): - sys.stdout = LoggerWriter(_LOGGER.debug) - sys.stderr = LoggerWriter(_LOGGER.error) + sys.stdout = LoggerWriter(LOGGER.debug) + sys.stderr = LoggerWriter(LOGGER.error) """ Grab the ~/.polyglot/.env file for variables @@ -84,7 +83,7 @@ def init_interface(): try: load_dotenv(join(expanduser("~") + '/.polyglot/.env')) except (UserWarning) as err: - _LOGGER.warning('File does not exist: {}.'.format(join(expanduser("~") + '/.polyglot/.env')), exc_info=True) + LOGGER.warning('File does not exist: {}.'.format(join(expanduser("~") + '/.polyglot/.env')), exc_info=True) # sys.exit(1) warnings.resetwarnings() @@ -104,16 +103,16 @@ def init_interface(): os.environ['MQTT_HOST'] = line['mqttHost'] os.environ['MQTT_PORT'] = line['mqttPort'] os.environ['TOKEN'] = line['token'] - _LOGGER.info('Received Config from STDIN.') + LOGGER.info('Received Config from STDIN.') except (Exception) as err: # e = sys.exc_info()[0] - _LOGGER.error('Invalid formatted input %s for line: %s', line, err, exc_info=True) + LOGGER.error('Invalid formatted input %s for line: %s', line, err, exc_info=True) def unload_interface(): sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ - _LOGGER.handlers = [] + LOGGER.handlers = [] class Interface(object): @@ -142,7 +141,7 @@ def __init__(self, envVar=None): if envVar is not None: self.profileNum = os.environ.get(envVar) if self.profileNum is None: - _LOGGER.error('Profile Number not found in STDIN or .env file. Exiting.') + LOGGER.error('Profile Number not found in STDIN or .env file. Exiting.') sys.exit(1) self.profileNum = str(self.profileNum) self.topicPolyglotConnection = 'udi/polyglot/connections/polyglot' @@ -150,7 +149,7 @@ def __init__(self, envVar=None): self.topicSelfConnection = 'udi/polyglot/connections/{}'.format(self.profileNum) self._threads = {} self._threads['socket'] = Thread(target = self._startMqtt, name = 'Interface') - _LOGGER.info('mqtt Client: name={}'.format(envVar)) + LOGGER.info('mqtt Client: name={}'.format(envVar)) self._mqttc = mqtt.Client(envVar+self.profileNum, True) # self._mqttc.will_set(self.topicSelfConnection, json.dumps({'node': self.profileNum, 'connected': False}), retain=True) self._mqttc.on_connect = self._connect @@ -177,7 +176,7 @@ def __init__(self, envVar=None): tls_version=ssl.PROTOCOL_TLSv1_2 ) # self._mqttc.tls_insecure_set(True) - # self._mqttc.enable_logger(logger=_LOGGER) + # self._mqttc.enable_logger(logger=LOGGER) # self.loop = asyncio.new_event_loop() self.loop = None self.inQueue = queue.Queue() @@ -193,10 +192,10 @@ def __init__(self, envVar=None): self.custom_params_pending_docs = '' try: self.network_interface = self.get_network_interface() - _LOGGER.info('Connect: Network Interface: {}'.format(self.network_interface)) + LOGGER.info('Connect: Network Interface: {}'.format(self.network_interface)) except: self.network_interface = False - _LOGGER.error('Failed to determine Network Interface', exc_info=True) + LOGGER.error('Failed to determine Network Interface', exc_info=True) def onConfig(self, callback): """ @@ -226,15 +225,15 @@ def _connect(self, mqttc, userdata, flags, rc): if rc == 0: self.connected = True results = [] - _LOGGER.info("MQTT Connected with result code " + str(rc) + " (Success)") + LOGGER.info("MQTT Connected with result code " + str(rc) + " (Success)") # result, mid = self._mqttc.subscribe(self.topicInput) results.append((self.topicInput, tuple(self._mqttc.subscribe(self.topicInput)))) results.append((self.topicPolyglotConnection, tuple(self._mqttc.subscribe(self.topicPolyglotConnection)))) for (topic, (result, mid)) in results: if result == 0: - _LOGGER.info("MQTT Subscribing to topic: " + topic + " - " + " MID: " + str(mid) + " Result: " + str(result)) + LOGGER.info("MQTT Subscribing to topic: " + topic + " - " + " MID: " + str(mid) + " Result: " + str(result)) else: - _LOGGER.info("MQTT Subscription to " + topic + " failed. This is unusual. MID: " + str(mid) + " Result: " + str(result)) + LOGGER.info("MQTT Subscription to " + topic + " failed. This is unusual. MID: " + str(mid) + " Result: " + str(result)) # If subscription fails, try to reconnect. self._mqttc.reconnect() self._mqttc.publish(self.topicSelfConnection, json.dumps( @@ -242,9 +241,9 @@ def _connect(self, mqttc, userdata, flags, rc): 'connected': True, 'node': self.profileNum }), retain=True) - _LOGGER.info('Sent Connected message to Polyglot') + LOGGER.info('Sent Connected message to Polyglot') else: - _LOGGER.error("MQTT Failed to connect. Result code: " + str(rc)) + LOGGER.error("MQTT Failed to connect. Result code: " + str(rc)) def _message(self, mqttc, userdata, msg): """ @@ -259,34 +258,34 @@ def _message(self, mqttc, userdata, msg): inputCmds = ['query', 'command', 'result', 'status', 'shortPoll', 'longPoll', 'delete'] parsed_msg = json.loads(msg.payload.decode('utf-8')) if DEBUG: - _LOGGER.debug('MQTT Received Message: {}: {}'.format(msg.topic, parsed_msg)) + LOGGER.debug('MQTT Received Message: {}: {}'.format(msg.topic, parsed_msg)) if 'node' in parsed_msg: if parsed_msg['node'] != 'polyglot': return del parsed_msg['node'] for key in parsed_msg: if DEBUG: - _LOGGER.debug('MQTT Processing Message: {}: {}'.format(msg.topic, parsed_msg)) + LOGGER.debug('MQTT Processing Message: {}: {}'.format(msg.topic, parsed_msg)) if key == 'config': self.inConfig(parsed_msg[key]) elif key == 'connected': self.polyglotConnected = parsed_msg[key] elif key == 'stop': - _LOGGER.debug('Received stop from Polyglot... Shutting Down.') + LOGGER.debug('Received stop from Polyglot... Shutting Down.') self.stop() elif key in inputCmds: self.input(parsed_msg) else: - _LOGGER.error('Invalid command received in message from Polyglot: {}'.format(key)) + LOGGER.error('Invalid command received in message from Polyglot: {}'.format(key)) else: - _LOGGER.error('MQTT Received Unknown Message: {}: {}'.format(msg.topic, parsed_msg)) + LOGGER.error('MQTT Received Unknown Message: {}: {}'.format(msg.topic, parsed_msg)) except (ValueError) as err: - _LOGGER.error('MQTT Received Payload Error: {}'.format(err), exc_info=True) + LOGGER.error('MQTT Received Payload Error: {}'.format(err), exc_info=True) except Exception as ex: # Can any other exception happen? template = "An exception of type {0} occured. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) - _LOGGER.error("MQTT Received Unknown Error: " + message, exc_info=True) + LOGGER.error("MQTT Received Unknown Error: " + message, exc_info=True) def _disconnect(self, mqttc, userdata, rc): """ @@ -298,31 +297,31 @@ def _disconnect(self, mqttc, userdata, rc): """ self.connected = False if rc != 0: - _LOGGER.info("MQTT Unexpected disconnection. Trying reconnect.") + LOGGER.info("MQTT Unexpected disconnection. Trying reconnect.") try: self._mqttc.reconnect() except Exception as ex: template = "An exception of type {0} occured. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) - _LOGGER.error("MQTT Connection error: " + message) + LOGGER.error("MQTT Connection error: " + message) else: - _LOGGER.info("MQTT Graceful disconnection.") + LOGGER.info("MQTT Graceful disconnection.") def _log(self, mqttc, userdata, level, string): """ Use for debugging MQTT Packets, disable for normal use, NOISY. """ if DEBUG: - _LOGGER.info('MQTT Log - {}: {}'.format(str(level), str(string))) + LOGGER.info('MQTT Log - {}: {}'.format(str(level), str(string))) pass def _subscribe(self, mqttc, userdata, mid, granted_qos): """ Callback for Subscribe message. Unused currently. """ - _LOGGER.info("MQTT Subscribed Succesfully for Message ID: {} - QoS: {}".format(str(mid), str(granted_qos))) + LOGGER.info("MQTT Subscribed Succesfully for Message ID: {} - QoS: {}".format(str(mid), str(granted_qos))) pass def _publish(self, mqttc, userdata, mid): """ Callback for publish message. Unused currently. """ if DEBUG: - _LOGGER.info("MQTT Published message ID: {}".format(str(mid))) + LOGGER.info("MQTT Published message ID: {}".format(str(mid))) pass def start(self): @@ -334,7 +333,7 @@ def _startMqtt(self): The client start method. Starts the thread for the MQTT Client and publishes the connected message. """ - _LOGGER.info('Connecting to MQTT... {}:{}'.format(self._server, self._port)) + LOGGER.info('Connecting to MQTT... {}:{}'.format(self._server, self._port)) done = False while not done: try: @@ -343,14 +342,14 @@ def _startMqtt(self): self._mqttc.loop_forever() done = True except ssl.SSLError as e: - _LOGGER.error("MQTT Connection SSLError: {}, Will retry in a few seconds.".format(e), exc_info=True) + LOGGER.error("MQTT Connection SSLError: {}, Will retry in a few seconds.".format(e), exc_info=True) time.sleep(3) except Exception as ex: template = "An exception of type {0} occurred. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) - _LOGGER.error("MQTT Connection error: {}".format(message), exc_info=True) + LOGGER.error("MQTT Connection error: {}".format(message), exc_info=True) done = True - _LOGGER.debug("MQTT Done:") + LOGGER.debug("MQTT Done:") def stop(self): """ @@ -363,7 +362,7 @@ def stop(self): # self._longPoll.cancel() # self._shortPoll.cancel() if self.connected: - _LOGGER.info('Disconnecting from MQTT... {}:{}'.format(self._server, self._port)) + LOGGER.info('Disconnecting from MQTT... {}:{}'.format(self._server, self._port)) self._mqttc.publish(self.topicSelfConnection, json.dumps({'node': self.profileNum, 'connected': False}), retain=True) self._mqttc.loop_stop() self._mqttc.disconnect() @@ -371,7 +370,7 @@ def stop(self): for watcher in self.__stopObservers: watcher() except KeyError as e: - _LOGGER.exception('KeyError in gotConfig: {}'.format(e), exc_info=True) + LOGGER.exception('KeyError in gotConfig: {}'.format(e), exc_info=True) def send(self, message): """ @@ -385,7 +384,7 @@ def send(self, message): message['node'] = self.profileNum self._mqttc.publish(self.topicInput, json.dumps(message), retain=False) except TypeError as err: - _LOGGER.error('MQTT Send Error: {}'.format(err), exc_info=True) + LOGGER.error('MQTT Send Error: {}'.format(err), exc_info=True) def addNode(self, node): """ @@ -393,7 +392,7 @@ def addNode(self, node): :param node: Dictionary of node settings. Keys: address, name, node_def_id, primary, and drivers are required. """ - _LOGGER.info('Adding node {}({})'.format(node.name, node.address)) + LOGGER.info('Adding node {}({})'.format(node.name, node.address)) message = { 'addnode': { 'nodes': [{ @@ -414,7 +413,7 @@ def saveCustomData(self, data): :param data: Dictionary of key value pairs to store in Polyglot database. """ - _LOGGER.info('Sending customData to Polyglot.') + LOGGER.info('Sending customData to Polyglot.') message = { 'customdata': data } self.send(message) @@ -424,7 +423,7 @@ def saveCustomParams(self, data): :param data: Dictionary of key value pairs to store in Polyglot database. """ - _LOGGER.info('Sending customParams to Polyglot.') + LOGGER.info('Sending customParams to Polyglot.') message = { 'customparams': data } self.send(message) @@ -434,7 +433,7 @@ def addNotice(self, data): :param data: String of characters to add as a notification in the front-end. """ - _LOGGER.info('Sending addnotice to Polyglot: {}'.format(data)) + LOGGER.info('Sending addnotice to Polyglot: {}'.format(data)) message = { 'addnotice': data } self.send(message) @@ -444,7 +443,7 @@ def removeNotice(self, data): :param data: Index of notices list to remove. """ - _LOGGER.info('Sending removenotice to Polyglot for index {}'.format(data)) + LOGGER.info('Sending removenotice to Polyglot for index {}'.format(data)) message = { 'removenotice': data } self.send(message) @@ -452,14 +451,14 @@ def restart(self): """ Send a command to Polyglot to restart this NodeServer """ - _LOGGER.info('Asking Polyglot to restart me.') + LOGGER.info('Asking Polyglot to restart me.') message = { 'restart': {} } self.send(message) def installprofile(self): - _LOGGER.info('Sending Install Profile command to Polyglot.') + LOGGER.info('Sending Install Profile command to Polyglot.') message = { 'installprofile': { 'reboot': False } } self.send(message) @@ -469,7 +468,7 @@ def delNode(self, address): :param node: Dictionary of node settings. Keys: address, name, node_def_id, primary, and drivers are required. """ - _LOGGER.info('Removing node {}'.format(address)) + LOGGER.info('Removing node {}'.format(address)) message = { 'removenode': { 'address': address @@ -487,7 +486,7 @@ def getNode(self, address): return node return False except KeyError: - _LOGGER.error('Usually means we have not received the config yet.', exc_info=True) + LOGGER.error('Usually means we have not received the config yet.', exc_info=True) return False def inConfig(self, config): @@ -504,7 +503,7 @@ def inConfig(self, config): self.send_custom_config_docs() except KeyError as e: - _LOGGER.error('KeyError in gotConfig: {}'.format(e), exc_info=True) + LOGGER.error('KeyError in gotConfig: {}'.format(e), exc_info=True) def input(self, command): self.inQueue.put(command) @@ -562,7 +561,7 @@ def save_typed_params(self, data): this (parent) is treated as object / list of objects by UI, otherwise, it's treated as a single / list of single values """ - _LOGGER.info('Sending typed parameters to Polyglot.') + LOGGER.info('Sending typed parameters to Polyglot.') if type(data) is not list: data = [ data ] message = { 'typedparams': data } @@ -582,19 +581,19 @@ def get_server_data(self,check_profile=True): with open(Interface.SERVER_JSON_FILE_NAME) as data: serverdata = json.load(data) except Exception as err: - _LOGGER.error('get_server_data: failed to read file {0}: {1}'.format(Interface.SERVER_JSON_FILE_NAME,err), exc_info=True) + LOGGER.error('get_server_data: failed to read file {0}: {1}'.format(Interface.SERVER_JSON_FILE_NAME,err), exc_info=True) return serverdata data.close() # Get the version info try: version = serverdata['credits'][0]['version'] except (KeyError, ValueError): - _LOGGER.info('Version (credits[0][version]) not found in server.json.') + LOGGER.info('Version (credits[0][version]) not found in server.json.') version = '0.0.0.0' serverdata['version'] = version if not 'profile_version' in serverdata: serverdata['profile_version'] = None - _LOGGER.debug('get_server_data: {}'.format(serverdata)) + LOGGER.debug('get_server_data: {}'.format(serverdata)) if check_profile: self.check_profile(serverdata) return serverdata @@ -605,22 +604,22 @@ def check_profile(self,serverdata): against the profile_version stored in the db customData The profile will be installed if necessary. """ - _LOGGER.debug('check_profile: config={}'.format(self.config)) + LOGGER.debug('check_profile: config={}'.format(self.config)) cdata = deepcopy(self.config['customData']) - _LOGGER.debug('check_profile: customData={}'.format(cdata)) - _LOGGER.debug('check_profile: profile_version={}'.format(serverdata['profile_version'])) + LOGGER.debug('check_profile: customData={}'.format(cdata)) + LOGGER.debug('check_profile: profile_version={}'.format(serverdata['profile_version'])) if serverdata['profile_version'] is None: LoGGER.info('check_profile: Ignoring since nodeserver does not have profile_version') return update_profile = False if not 'profile_version' in cdata: - _LOGGER.info('check_profile: Updated needed since it has never been recorded.') + LOGGER.info('check_profile: Updated needed since it has never been recorded.') update_profile = True elif serverdata['profile_version'] == cdata['profile_version']: - _LOGGER.info('check_profile: No updated needed: "{}" == "{}"'.format(serverdata['profile_version'],cdata['profile_version'])) + LOGGER.info('check_profile: No updated needed: "{}" == "{}"'.format(serverdata['profile_version'],cdata['profile_version'])) update_profile = False else: - _LOGGER.info('check_profile: Updated needed: "{}" == "{}"'.format(serverdata['profile_version'],cdata['profile_version'])) + LOGGER.info('check_profile: Updated needed: "{}" == "{}"'.format(serverdata['profile_version'],cdata['profile_version'])) update_profile = True if update_profile: st = self.installprofile() @@ -647,7 +646,7 @@ def __init__(self, controller, primary, address, name): self.enabled = None self.added = None except (KeyError) as err: - _LOGGER.error('Error Creating node: {}'.format(err), exc_info=True) + LOGGER.error('Error Creating node: {}'.format(err), exc_info=True) def _convertDrivers(self, drivers): return deepcopy(drivers) @@ -679,7 +678,7 @@ def reportDriver(self, driver, report, force): (str(d['value']) != str(driver['value']) or d['uom'] != driver['uom'] or force)): - _LOGGER.info('Updating Driver {} - {}: {}, uom: {}'.format(self.address, driver['driver'], driver['value'], driver['uom'])) + LOGGER.info('Updating Driver {} - {}: {}, uom: {}'.format(self.address, driver['driver'], driver['value'], driver['uom'])) d['value'] = deepcopy(driver['value']) if d['uom'] != driver['uom']: d['uom'] = deepcopy(driver['uom']) @@ -707,7 +706,7 @@ def reportCmd(self, command, value=None, uom=None): self.controller.poly.send(message) def reportDrivers(self): - _LOGGER.info('Updating All Drivers to ISY for {}({})'.format(self.name, self.address)) + LOGGER.info('Updating All Drivers to ISY for {}({})'.format(self.name, self.address)) self.updateDrivers(self.drivers) for driver in self.drivers: message = { @@ -746,7 +745,7 @@ def getDriver(self, dv): return None def toJSON(self): - _LOGGER.debug(json.dumps(self.__dict__)) + LOGGER.debug(json.dumps(self.__dict__)) def __rep__(self): return self.toJSON() @@ -794,7 +793,7 @@ def __init__(self, poly, name='Controller'): # self._threads = [] self._startThreads() except (KeyError) as err: - _LOGGER.error('Error Creating node: {}'.format(err), exc_info=True) + LOGGER.error('Error Creating node: {}'.format(err), exc_info=True) def _gotConfig(self, config): self.polyConfig = config @@ -810,7 +809,7 @@ def _gotConfig(self, config): n.added = node['added'] if self.address not in self._nodes: self.addNode(self) - _LOGGER.info('Waiting on Controller node to be added.......') + LOGGER.info('Waiting on Controller node to be added.......') if not self.started: self.nodes[self.address] = self self.started = True @@ -831,9 +830,9 @@ def _parseInput(self): try: self.nodes[input[key]['address']].runCmd(input[key]) except (Exception) as err: - _LOGGER.error('_parseInput: failed {}.runCmd({}) {}'.format(input[key]['address'], input[key]['cmd'], err), exc_info=True) + LOGGER.error('_parseInput: failed {}.runCmd({}) {}'.format(input[key]['address'], input[key]['cmd'], err), exc_info=True) else: - _LOGGER.error('_parseInput: received command {} for a node that is not in memory: {}'.format(input[key]['cmd'], input[key]['address'])) + LOGGER.error('_parseInput: received command {} for a node that is not in memory: {}'.format(input[key]['cmd'], input[key]['address'])) elif key == 'result': self._handleResult(input[key]) elif key == 'delete': @@ -855,7 +854,7 @@ def _parseInput(self): self.poly.inQueue.task_done() def _handleResult(self, result): - # _LOGGER.debug(self.nodesAdding) + # LOGGER.debug(self.nodesAdding) try: if 'addnode' in result: if result['addnode']['success']: @@ -867,7 +866,7 @@ def _handleResult(self, result): else: del self.nodes[result['addnode']['address']] except (KeyError, ValueError) as err: - _LOGGER.error('handleResult: {}'.format(err), exc_info=True) + LOGGER.error('handleResult: {}'.format(err), exc_info=True) def _delete(self): """ @@ -957,13 +956,13 @@ def start(self): def saveCustomData(self, data): if not isinstance(data, dict): - _LOGGER.error('saveCustomData: data isn\'t a dictionary. Ignoring.') + LOGGER.error('saveCustomData: data isn\'t a dictionary. Ignoring.') else: self.poly.saveCustomData(data) def addCustomParam(self, data): if not isinstance(data, dict): - _LOGGER.error('addCustomParam: data isn\'t a dictionary. Ignoring.') + LOGGER.error('addCustomParam: data isn\'t a dictionary. Ignoring.') else: newData = self.poly.config['customParams'] newData.update(data) @@ -975,14 +974,14 @@ def removeCustomParam(self, data): except NameError: # no, it doesn't (it's Python3); use 'str' instead basestring = str if not isinstance(data, basestring): - _LOGGER.error('removeCustomParam: data isn\'t a string. Ignoring.') + LOGGER.error('removeCustomParam: data isn\'t a string. Ignoring.') else: try: newData = deepcopy(self.poly.config['customParams']) newData.pop(data) self.poly.saveCustomParams(newData) except KeyError: - _LOGGER.error('{} not found in customParams. Ignoring...'.format(data), exc_info=True) + LOGGER.error('{} not found in customParams. Ignoring...'.format(data), exc_info=True) def getCustomParam(self, data): params = deepcopy(self.poly.config['customParams']) diff --git a/polyinterface/polylogger.py b/polyinterface/polylogger.py new file mode 100755 index 0000000..1ba6121 --- /dev/null +++ b/polyinterface/polylogger.py @@ -0,0 +1,53 @@ + +import os +import logging +from logging import handlers as log_handlers +import warnings + +class PolyLogger: + + NAME = __name__.split(".")[0] + LOGS_DIR= './logs' + LOG_FILE = 'debug.log' + LEVEL = logging.DEBUG + ROTATION = 'midnight' + WARN_LOGGER_NAME = 'py.warnings' + BACKUP_COUNT = 30 + FMT_STRING = '%(asctime)s %(threadName)-10s %(name)-18s %(levelname)-8s %(module)s:%(funcName)s: %(message)s' + + def __init__(self): + if not os.path.exists(PolyLogger.LOGS_DIR): + os.makedirs(PolyLogger.LOGS_DIR) + self.handler = log_handlers.TimedRotatingFileHandler( + os.path.join(PolyLogger.LOGS_DIR, PolyLogger.LOG_FILE), + when=PolyLogger.ROTATION, + backupCount=PolyLogger.BACKUP_COUNT + ) + logging.captureWarnings(True) + self.set_log_format(PolyLogger.FMT_STRING) + # Attach the handler to the logger + logging.basicConfig( + handlers=[self.handler], + level=PolyLogger.LEVEL + ) + + self.logger = logging.getLogger(PolyLogger.NAME) + self.logger.propagate = False # If True we get duplicates? + self.logger.addHandler(self.handler) + + self.warnlog = logging.getLogger(PolyLogger.WARN_LOGGER_NAME) + warnings.formatwarning = self.warning_on_one_line + self.warnlog.addHandler(self.handler) + + def set_log_format(self, fmt_string): + # Format each log message like this + formatter = logging.Formatter(fmt_string) + # Attach the formatter to the handler + self.handler.setFormatter(formatter) + + @staticmethod + def warning_on_one_line(message, category, filename, lineno, file=None, line=None): + return '{}:{}: {}: {}'.format(filename, lineno, category.__name__, message) + +LOG_HANDLER = PolyLogger() +LOGGER = LOG_HANDLER.logger diff --git a/polyinterface/polylogging.py b/polyinterface/polylogging.py deleted file mode 100755 index 75dd565..0000000 --- a/polyinterface/polylogging.py +++ /dev/null @@ -1,40 +0,0 @@ - -import logging,os,warnings -import logging.handlers - - -def warning_on_one_line(message, category, filename, lineno, file=None, line=None): - return '{}:{}: {}: {}'.format(filename, lineno, category.__name__, message) - -# Make a handler that writes to a file, -# Log Location -# path = os.path.dirname(sys.argv[0]) -if not os.path.exists('./logs'): - os.makedirs('./logs') -# making a new file at midnight and keeping 3 backups -# this is global because we add it to basicConfig, so when set_log_format -# is called we just want to modify our handler, not recreate it each time. -_handler = logging.handlers.TimedRotatingFileHandler("./logs/debug.log", when="midnight", backupCount=30) -def set_log_format(fmt_string='%(asctime)s %(threadName)-10s %(name)-18s %(levelname)-8s %(module)s:%(funcName)s: %(message)s'): - # Format each log message like this - formatter = logging.Formatter(fmt_string) - # Attach the formatter to the handler - _handler.setFormatter(formatter) - -def setup_log(logger): - # Don't need to do it again... - if logger.hasHandlers(): - return - # ### Logging Section ################################################################################ - logging.captureWarnings(True) - set_log_format() - # Attach the handler to the logger - logging.basicConfig( - handlers=[_handler], - level=logging.DEBUG - ) - logger.propagate = False # If True we get duplicates? - warnlog = logging.getLogger('py.warnings') - warnings.formatwarning = warning_on_one_line - logger.addHandler(_handler) - warnlog.addHandler(_handler) From ebd3de6d75d1646178965d9a5fb536a8578bd611 Mon Sep 17 00:00:00 2001 From: JimBo CA Date: Wed, 8 Apr 2020 09:23:11 -0700 Subject: [PATCH 2/3] Fixed bug for nodeservers that do not pass in name to polyinterface.Interface call --- CHANGELOG.md | 3 +++ polyinterface/__init__.py | 2 +- polyinterface/polyinterface.py | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a467670..684e022 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # __Changelog for Polyglot Python Interface v2__ +### Version 2.0.37 +- Fixed bug for nodeservers that do not pass in name to polyinterface.Interface call. + ### Version 2.0.36 - New logger format with name instead of module - Nodesrevers can call polyinterface.set_log_format if they don't like the default which is: diff --git a/polyinterface/__init__.py b/polyinterface/__init__.py index 7754a5d..5ec495d 100755 --- a/polyinterface/__init__.py +++ b/polyinterface/__init__.py @@ -3,7 +3,7 @@ from .polylogger import LOGGER from .polyinterface import Interface, Node, Controller, unload_interface, get_network_interface -__version__ = '2.0.38' +__version__ = '2.0.37' __description__ = 'UDI Polyglot v2 Interface' __url__ = 'https://github.com/UniversalDevicesInc/polyglot-v2-python-interface' __author__ = 'James Milne' diff --git a/polyinterface/polyinterface.py b/polyinterface/polyinterface.py index 93f8cda..a4ab5a3 100755 --- a/polyinterface/polyinterface.py +++ b/polyinterface/polyinterface.py @@ -149,8 +149,8 @@ def __init__(self, envVar=None): self.topicSelfConnection = 'udi/polyglot/connections/{}'.format(self.profileNum) self._threads = {} self._threads['socket'] = Thread(target = self._startMqtt, name = 'Interface') - LOGGER.info('mqtt Client: name={}'.format(envVar)) - self._mqttc = mqtt.Client(envVar+self.profileNum, True) + #LOGGER.info('mqtt Client: name={}'.format(envVar)) + self._mqttc = mqtt.Client(envVar, True) # self._mqttc.will_set(self.topicSelfConnection, json.dumps({'node': self.profileNum, 'connected': False}), retain=True) self._mqttc.on_connect = self._connect self._mqttc.on_message = self._message From f6708b2728a57adff9edf16fa9d410cb6f8c035e Mon Sep 17 00:00:00 2001 From: JimBo CA Date: Wed, 8 Apr 2020 09:28:05 -0700 Subject: [PATCH 3/3] 2.0.37 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 684e022..efd87b4 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Version 2.0.37 - Fixed bug for nodeservers that do not pass in name to polyinterface.Interface call. +- Added PyLogger class as suggested by @firstone ### Version 2.0.36 - New logger format with name instead of module