Add some basic logging to the application. Also for severe errors, track them in info.log file in local folder

This commit is contained in:
Alessandro
2020-04-11 15:27:05 +02:00
parent ab32fbbf98
commit eaeb51de65
10 changed files with 86 additions and 20 deletions

3
.gitignore vendored
View File

@@ -1,4 +1,4 @@
__pycache__ __PYCache__
Data Data
src/themes/__current_theme src/themes/__current_theme
designer.bat designer.bat
@@ -8,3 +8,4 @@ launch.bat
spec_files/**/output spec_files/**/output
*.txt *.txt
*.json *.json
info.log

View File

@@ -28,14 +28,13 @@ class ACFValue:
self._description = "" self._description = ""
self._value = value self._value = value
self._string = self._value self._string = self._value
try: if self._value.isdigit():
self.numeric_value = float(self._value) self.numeric_value = float(self._value)
except Exception:
self.is_numeric = False
self.numeric_value = 0.0
else:
self.is_numeric = True self.is_numeric = True
self._string += " ms" self._string += " ms"
else:
self.is_numeric = False
self.numeric_value = 0.0
@classmethod @classmethod
def list_from_series(cls, series): def list_from_series(cls, series):

View File

@@ -5,6 +5,7 @@ import webbrowser
import os import os
import sys import sys
from time import sleep, time from time import sleep, time
import logging
from pandas import read_csv from pandas import read_csv
@@ -58,6 +59,7 @@ from downloadtargetfactory import get_download_target
from settings import Settings from settings import Settings
from updatescontroller import UpdatesController from updatescontroller import UpdatesController
from urlbutton import UrlButton from urlbutton import UrlButton
import loggingconf # noqa 401
# import default_imgs_rc # import default_imgs_rc
@@ -256,6 +258,7 @@ class Artemis(QMainWindow, Ui_MainWindow):
font.setUnderline(self.settings.font['underline']) font.setUnderline(self.settings.font['underline'])
self.apply_font(font) self.apply_font(font)
except Exception: # Invalid font except Exception: # Invalid font
logging.warning("Invalid Font in settings.json")
pass pass
@pyqtSlot() @pyqtSlot()
@@ -357,6 +360,7 @@ class Artemis(QMainWindow, Ui_MainWindow):
try: try:
webbrowser.open(Constants.GFD_SITE + query.lower()) webbrowser.open(Constants.GFD_SITE + query.lower())
except Exception: except Exception:
logging.error("Cannot open browser")
pass pass
def set_initial_size(self): def set_initial_size(self):
@@ -445,7 +449,8 @@ class Artemis(QMainWindow, Ui_MainWindow):
else: else:
try: try:
is_checksum_ok = checksum_ok(db, get_db_hash_code()) is_checksum_ok = checksum_ok(db, get_db_hash_code())
except Exception: except ValueError as e:
logging.info(e)
pop_up(self, title=Messages.NO_CONNECTION, pop_up(self, title=Messages.NO_CONNECTION,
text=Messages.NO_CONNECTION_MSG).show() text=Messages.NO_CONNECTION_MSG).show()
else: else:
@@ -485,7 +490,8 @@ class Artemis(QMainWindow, Ui_MainWindow):
else: else:
try: try:
is_checksum_ok = checksum_ok(db, get_db_hash_code()) is_checksum_ok = checksum_ok(db, get_db_hash_code())
except Exception: except ValueError as e:
logging.info(e)
pop_up(self, title=Messages.NO_CONNECTION, pop_up(self, title=Messages.NO_CONNECTION,
text=Messages.NO_CONNECTION_MSG).show() text=Messages.NO_CONNECTION_MSG).show()
else: else:

45
src/loggingconf.py Normal file
View File

@@ -0,0 +1,45 @@
import logging
import logging.config
from constants import __BASE_FOLDER__
import os.path
"""Import the module to initialize the logging configuration"""
_LOGGING_CONFIG = {
'version': 1,
'formatters': {
'general': {
'format': '%(asctime)s::%(levelname)s::%(module)s::%(funcName)s::%(message)s',
'datefmt': '%d/%m/%Y %I:%M:%S %p'
}
},
'handlers': {
'console': {
'level': 'INFO',
'formatter': 'general',
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout',
},
'file': {
'class': 'logging.FileHandler',
'level': 'ERROR',
'filename': os.path.join(__BASE_FOLDER__, 'info.log'),
'mode': 'w',
'encoding': 'utf8',
'formatter': 'general'
}
},
'root': {
'level': 'DEBUG',
'handlers': ['console', 'file']
},
'loggers': {
'root.sublogger': {
'propagate': False,
'level': 'DEBUG',
'handlers': ['console', 'file']
}
}
}
logging.config.dictConfig(_LOGGING_CONFIG)

View File

@@ -1,6 +1,7 @@
import os.path import os.path
from constants import Constants from constants import Constants
import json import json
import logging
class Settings: class Settings:
@@ -16,7 +17,8 @@ class Settings:
try: try:
with open(Constants.SETTINGS_FILE, 'r') as settings_file: with open(Constants.SETTINGS_FILE, 'r') as settings_file:
self._dct = json.load(settings_file) self._dct = json.load(settings_file)
except Exception: except FileNotFoundError:
logging.info("No settings.json file")
pass # Invalid file. pass # Invalid file.
def save(self, **kwargs): def save(self, **kwargs):

View File

@@ -272,17 +272,15 @@ class ThemeManager:
def apply_default_theme(self): def apply_default_theme(self):
"""Apply the default theme if no theme is set or the theme name is invalid.""" """Apply the default theme if no theme is set or the theme name is invalid."""
try: pretty_name = self._theme_names.get(self._pretty_name(ThemeConstants.DEFAULT), None)
self._theme_names[ if pretty_name is None:
self._pretty_name(ThemeConstants.DEFAULT)
].setChecked(True)
except Exception:
pop_up( pop_up(
self._owner, self._owner,
title=ThemeConstants.THEME_NOT_FOUND, title=ThemeConstants.THEME_NOT_FOUND,
text=ThemeConstants.MISSING_THEME text=ThemeConstants.MISSING_THEME
).show() ).show()
else: else:
pretty_name.setChecked(True)
self._apply(ThemeConstants.DEFAULT_THEME_PATH) self._apply(ThemeConstants.DEFAULT_THEME_PATH)
def start(self): def start(self):
@@ -291,11 +289,11 @@ class ThemeManager:
if self._owner.settings.theme is not None: if self._owner.settings.theme is not None:
theme_path = os.path.join(ThemeConstants.FOLDER, self._owner.settings.theme) theme_path = os.path.join(ThemeConstants.FOLDER, self._owner.settings.theme)
theme_name = self._pretty_name(os.path.basename(theme_path)) theme_name = self._pretty_name(os.path.basename(theme_path))
try: theme = self._theme_names.get(theme_name, None)
self._theme_names[theme_name].setChecked(True) if theme is None:
except Exception:
self.apply_default_theme() self.apply_default_theme()
else: else:
theme.setChecked(True)
self._apply(theme_path, save=False) self._apply(theme_path, save=False)
else: else:
self.apply_default_theme() self.apply_default_theme()

View File

@@ -1,3 +1,4 @@
import logging
import subprocess as sp import subprocess as sp
import webbrowser import webbrowser
from PyQt5.QtCore import QObject, pyqtSlot, QProcess from PyQt5.QtCore import QObject, pyqtSlot, QProcess
@@ -99,6 +100,7 @@ class UpdatesController(QObject):
try: try:
updater.startDetached(command) updater.startDetached(command)
except BaseException: except BaseException:
logging.error("Unable to start updater")
pass pass
else: else:
qApp.quit() qApp.quit()
@@ -122,6 +124,7 @@ class UpdatesController(QObject):
) as proc: ) as proc:
updater_version = proc.stdout.read().rstrip("\r\n") # Strip any possible newline, to be sure. updater_version = proc.stdout.read().rstrip("\r\n") # Strip any possible newline, to be sure.
except Exception: except Exception:
logging.error("Unable to query the updater")
updater_version = latest_updater_version updater_version = latest_updater_version
if latest_updater_version is None: if latest_updater_version is None:
return return

View File

@@ -1,3 +1,4 @@
import logging
from functools import partial from functools import partial
import hashlib import hashlib
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
@@ -107,7 +108,7 @@ def checksum_ok(data, reference_hash_code):
Expects a sha256 code as argument.""" Expects a sha256 code as argument."""
if reference_hash_code is None: if reference_hash_code is None:
raise Exception("ERROR: Invalid hash code.") raise ValueError("ERROR: Invalid hash code.")
code = hashlib.sha256() code = hashlib.sha256()
code.update(data) code.update(data)
return code.hexdigest() == reference_hash_code return code.hexdigest() == reference_hash_code
@@ -192,6 +193,7 @@ def safe_cast(value, cast_type, default=-1):
try: try:
r = cast_type(value) r = cast_type(value)
except Exception: except Exception:
logging.error("Cast type failure")
r = default r = default
finally: finally:
return r return r

View File

@@ -1,3 +1,4 @@
import logging
import re import re
from PyQt5.QtGui import QPixmap from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
@@ -347,6 +348,7 @@ class ForecastData(_BaseWeatherData):
self._set_dates(forecast, rows["solar_row"]) self._set_dates(forecast, rows["solar_row"])
self._set_labels_values(labels_table) self._set_labels_values(labels_table)
except Exception: except Exception:
logging.error("Update ForecastData failure")
pass pass
def remove_data(self): def remove_data(self):

View File

@@ -1,3 +1,4 @@
import logging
import os import os
import sys import sys
import urllib3 import urllib3
@@ -39,12 +40,19 @@ def _download_multiline_file_as_list(url=Database.LINK_REF):
try: try:
return download_file(url, encoding="UTF-8").splitlines()[-1].split(Database.DELIMITER) return download_file(url, encoding="UTF-8").splitlines()[-1].split(Database.DELIMITER)
except Exception: except Exception:
logging.error("Database metadata download failure")
return None return None
def get_folder_hash_code(): def get_folder_hash_code():
return _download_multiline_file_as_list()[0] f = _download_multiline_file_as_list()
if f is not None:
return f[0]
return None
def get_db_hash_code(): def get_db_hash_code():
return _download_multiline_file_as_list()[1] f = _download_multiline_file_as_list()
if f is not None:
return f[1]
return None