diff --git a/ACKNOWLEDGMENTS b/ACKNOWLEDGMENTS index a1f9607..fc85219 100644 --- a/ACKNOWLEDGMENTS +++ b/ACKNOWLEDGMENTS @@ -217,15 +217,6 @@ Copyright (c) Python Software Foundation, Kenneth Reitz, Cory Benfield, Ian Cord 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. -darkdetect: -________________________________________________________________________ -Copyright (c) 2019, Alberto Sottile All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of "darkdetect" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL "Alberto Sottile" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - PySide6: ________________________________________________________________________ Qt is available under the GNU Lesser General Public License version 3. diff --git a/pyinstaller.spec b/pyinstaller.spec index 34d6087..83681f2 100644 --- a/pyinstaller.spec +++ b/pyinstaller.spec @@ -140,6 +140,6 @@ app = BUNDLE( 'CFBundleVersion': build_version, 'NSHumanReadableCopyright': 'Copyright © 2023, Lennart Haack.', 'LSApplicationCategoryType': 'public.app-category.utilities', - 'NSAppleEventsUsageDescription': 'swiftGuard is requesting access to System Events to provide the ability to shutdown and hibernate your Mac.\nThis permission will NEVER be used for any other purpose.', + 'NSAppleEventsUsageDescription': 'swiftGuard is requesting access to System Events to provide the ability to shutdown and hibernate your Mac.\nThis permission will NEVER be used for any other purposes.', }, ) diff --git a/src/swiftguard/app.py b/src/swiftguard/app.py index 87a5b01..151828f 100644 --- a/src/swiftguard/app.py +++ b/src/swiftguard/app.py @@ -370,44 +370,47 @@ class TrayApp: :ivar app: The main Qt application instance. :type app: QApplication - :ivar theme: The current system theme (e.g., Light or Dark). - :type theme: str - :ivar resources: The resource paths for icons and images based on - the current theme. + :ivar style_hints: Style hints for real-time theme changes. + :type style_hints: QStyleHints + :ivar resources: Resource paths for icons and images based on the + current theme. :type resources: dict | None - :ivar start_devices_count: A Counter object to keep track of - initially connected USB devices. - :type start_devices_count: collections.Counter - :ivar allowed_devices_count: A Counter object to keep track of - allowed USB devices. - :type allowed_devices_count: collections.Counter - :ivar current_devices_count: A Counter object to keep track of - currently connected USB devices. - :type current_devices_count: collections.Counter + :ivar config: Application configuration. + :type config: configparser.ConfigParser + :ivar app_icon: The system tray icon. + :type app_icon: QSystemTrayIcon + :ivar listen_usb: USB device listener. + :type listen_usb: listeners.ListenerUSB + :ivar listen_usb_thread: Thread for USB device listener. + :type listen_usb_thread: QThread :methods: - - usb_worker_handle: Start or stop the USB worker thread for - monitoring connected devices. + - __init__: Initialize the TrayApp instance and set up the + system tray icon. - menu_devices_update: Update the device menu based on connected and allowed devices. - whitelist_update: Add or remove devices from the whitelist. - worker_handle: Start or stop the main worker thread for manipulation detection. - - defuse: Defuse the manipulation detection and reset the alarm. - - manipulation: Handle manipulation detection and display - the alarm. + - defuse: Reset the alarm and return to normal monitoring mode. + - manipulation: Handle manipulation detection and display the + alarm. - config_update: Update the application configuration based on - user settings. - - theme_worker_handle: Start or stop the theme listener thread. - - theme_listener: Listen for changes in the system theme and - update application resources accordingly. + user input. + - theme_update: Update the application theme based on system + settings. + - update_box: Display an update message if a new version is + available. - create_tray_icon: Create and configure the system tray icon and its menu. - - help: Display a help message with instructions for using - the application. - - about: Display an about message with information about the - application and its author. - - exit_handler: Handle application exit and cleanup. + - acknowledgments: Display acknowledgments for third-party + libraries used. + - help: Display instructions for using the program. + - about: Display information about the application and its + author. + - handle_exception: Custom exception handler for uncaught + exceptions. + - exit_handler: Handle application exit and cleanup tasks. :param None: :return: None @@ -467,6 +470,7 @@ def __init__(self): self.worker_thread = None self.worker_handle("Guarding") + self.menu_tray = None self.menu_settings = None self.submenu = None self.menu_enabled = None @@ -478,8 +482,7 @@ def __init__(self): # Create the listener for USB devices (for dynamic menu update). listeners.Listeners.config = self.config - listeners.Listeners.intervall = 10 - self.listen_usb = listeners.ListenerUSB() + self.listen_usb = listeners.ListenerUSB(intervall=1000) # If a new device is connected, update the device menu. self.listen_usb.triggered.connect(self.menu_devices_update) @@ -504,19 +507,18 @@ def __init__(self): if new_vers := check_updates(): self.update_box(new_vers) + # self.update_box("0.2.0") + def menu_devices_update(self): """ Update the device menu based on connected and allowed devices. - This function updates the device menu in the system tray based - on the currently connected USB devices and the devices allowed - in the whitelist. It can be called at startup and when devices - change. - - :param startup: A boolean indicating whether the update is - occurring at application startup. - :type startup: bool + The menu_devices_update function updates the device menu in the + system tray based on the currently connected USB devices and + the devices allowed in the whitelist. It can be called at + startup and when devices change. + :param self: Refer to the instance of the class :return: None """ @@ -847,8 +849,8 @@ def update_box(self, new_vers): # Bold text. msg_box.setText( - f"Update available!\n\n" - f"Installed version: {__version__}\nLatest version: " + f"Update Available!\n\n" + f"Currently Installed: {__version__}\nLatest Release: " f"{new_vers}\n" ) @@ -890,8 +892,6 @@ def update_box(self, new_vers): self.config["Application"]["check_updates"] = "0" conf.write(self.config) - # TODO: implement focus on dialog / move dialog to front. - def create_tray_icon(self): """ Create and configure the system tray icon and its menu. @@ -910,11 +910,10 @@ def create_tray_icon(self): tray_icon.setIcon(QIcon(self.resources["app-icon"])) - menu_tray = QMenu() - self.menu_tray = menu_tray + self.menu_tray = QMenu() # Create a submenu for "Devices" initially disabled. - self.submenu = menu_tray.addMenu("Devices") + self.submenu = self.menu_tray.addMenu("Devices") self.submenu.setIcon(QIcon(self.resources["usb-connection"])) submenu_dummy = QAction("Searching ...", self.submenu) submenu_dummy.setEnabled(False) @@ -936,24 +935,24 @@ def create_tray_icon(self): self.menu_enabled.entry.setVisible(False) else: self.menu_enabled.entry.setVisible(True) - menu_tray.addAction(self.menu_enabled.entry) + self.menu_tray.addAction(self.menu_enabled.entry) # Create hidden "Manipulation" menu item. - self.menu_tamper = QAction("Manipulation", menu_tray) + self.menu_tamper = QAction("Manipulation", self.menu_tray) self.menu_tamper.setIcon(QIcon(self.resources["shield-tamper"])) if self.worker.tampered_var: self.menu_tamper.setVisible(True) else: self.menu_tamper.setVisible(False) self.menu_tamper.setShortcut(QKeySequence(Qt.CTRL | Qt.Key_E)) - menu_tray.addAction(self.menu_tamper) + self.menu_tray.addAction(self.menu_tamper) self.menu_tamper.triggered.connect(self.defuse) - menu_tray.addSeparator() + self.menu_tray.addSeparator() # Create a "Settings" menu. - self.menu_settings = QMenu(" Settings", menu_tray) - menu_tray.addMenu(self.menu_settings) + self.menu_settings = QMenu(" Settings", self.menu_tray) + self.menu_tray.addMenu(self.menu_settings) # Create an "Action" submenu within "Settings." entry01 = ToggleEntry( @@ -1028,25 +1027,25 @@ def create_tray_icon(self): self.menu_settings.addAction(entry09.entry) # Create "Help" menu item. - menu_help = QAction(" Help", menu_tray) - menu_tray.addAction(menu_help) + menu_help = QAction(" Help", self.menu_tray) + self.menu_tray.addAction(menu_help) menu_help.triggered.connect(self.help) # Create "About" menu item. - menu_about = QAction(" About", menu_tray) - menu_tray.addAction(menu_about) + menu_about = QAction(" About", self.menu_tray) + self.menu_tray.addAction(menu_about) menu_about.triggered.connect(self.about) - menu_tray.addSeparator() + self.menu_tray.addSeparator() # Create an "Exit" menu item and connect it to the exit handler. - menu_exit = QAction(" Exit", menu_tray) + menu_exit = QAction(" Exit", self.menu_tray) menu_exit.setShortcut(QKeySequence(Qt.CTRL | Qt.Key_Q)) menu_exit.triggered.connect(self.exit_handler) - menu_tray.addAction(menu_exit) + self.menu_tray.addAction(menu_exit) # Set the system tray menu. - tray_icon.setContextMenu(menu_tray) + tray_icon.setContextMenu(self.menu_tray) return tray_icon diff --git a/src/swiftguard/resources/ACKNOWLEDGMENTS b/src/swiftguard/resources/ACKNOWLEDGMENTS index a1f9607..fc85219 100644 --- a/src/swiftguard/resources/ACKNOWLEDGMENTS +++ b/src/swiftguard/resources/ACKNOWLEDGMENTS @@ -217,15 +217,6 @@ Copyright (c) Python Software Foundation, Kenneth Reitz, Cory Benfield, Ian Cord 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. -darkdetect: -________________________________________________________________________ -Copyright (c) 2019, Alberto Sottile All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of "darkdetect" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL "Alberto Sottile" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - PySide6: ________________________________________________________________________ Qt is available under the GNU Lesser General Public License version 3. diff --git a/src/swiftguard/utils/autostart.py b/src/swiftguard/utils/autostart.py index e83eb02..5a1ca8f 100644 --- a/src/swiftguard/utils/autostart.py +++ b/src/swiftguard/utils/autostart.py @@ -20,7 +20,7 @@ import os import shutil -from swiftguard.const import APP_PATH, CURRENT_PLATFORM, USER_HOME +from swiftguard import const # Child logger. LOGGER = logging.getLogger(__name__) @@ -29,10 +29,8 @@ def add_autostart(): # TODO: docstring. # macOS: Create launch agent. - if CURRENT_PLATFORM.startswith("DARWIN"): - launch_agent_dest = ( - f"{USER_HOME}/Library/LaunchAgents/dev.lennolium.swiftguard.plist" - ) + if const.CURRENT_PLATFORM.startswith("DARWIN"): + launch_agent_dest = f"{const.USER_HOME}/Library/LaunchAgents/dev.lennolium.swiftguard.plist" try: # Create LaunchAgents directory if it does not exist. if not os.path.isdir(os.path.dirname(launch_agent_dest)): @@ -47,7 +45,9 @@ def add_autostart(): if not os.path.isfile(launch_agent_dest): shutil.copy( os.path.join( - APP_PATH, "install", "dev.lennolium.swiftguard.plist" + const.APP_PATH, + "install", + "dev.lennolium.swiftguard.plist", ), launch_agent_dest, ) @@ -58,8 +58,8 @@ def add_autostart(): except Exception as e: LOGGER.error( f"Autostart could not be configured. Could not copy " - f"launch agent plist from {APP_PATH} to {launch_agent_dest}.\n" - f"Error: {str(e)}" + f"launch agent plist from {const.APP_PATH} to " + f"{launch_agent_dest}.\nError: {str(e)}" ) return False @@ -100,10 +100,8 @@ def add_autostart(): def del_autostart(): # macOS: Delete launch agent. - if CURRENT_PLATFORM.startswith("DARWIN"): - launch_agent_dest = ( - f"{USER_HOME}/Library/LaunchAgents/dev.lennolium.swiftguard.plist" - ) + if const.CURRENT_PLATFORM.startswith("DARWIN"): + launch_agent_dest = f"{const.USER_HOME}/Library/LaunchAgents/dev.lennolium.swiftguard.plist" # If the launch agent exists, delete it. if os.path.isfile(launch_agent_dest): diff --git a/src/swiftguard/utils/conf.py b/src/swiftguard/utils/conf.py index e7cf38e..8a526b8 100644 --- a/src/swiftguard/utils/conf.py +++ b/src/swiftguard/utils/conf.py @@ -24,7 +24,7 @@ import os import shutil -from swiftguard.const import APP_PATH, CONFIG_FILE +from swiftguard import const # Child logger. LOGGER = logging.getLogger(__name__) @@ -42,33 +42,33 @@ def create(force_restore=False): """ # If no config file exists, copy the default config file. - if os.path.isfile(CONFIG_FILE) and not force_restore: + if os.path.isfile(const.CONFIG_FILE) and not force_restore: return try: # If no config directory exists, create it. - if not os.path.isdir(os.path.dirname(CONFIG_FILE)): - os.mkdir(os.path.dirname(CONFIG_FILE)) + if not os.path.isdir(os.path.dirname(const.CONFIG_FILE)): + os.mkdir(os.path.dirname(const.CONFIG_FILE)) # Copy config file to config dir or overwrite existing one. shutil.copy( - os.path.join(APP_PATH, "install", "swiftguard.ini"), - CONFIG_FILE, + os.path.join(const.APP_PATH, "install", "swiftguard.ini"), + const.CONFIG_FILE, ) except Exception as e: raise e from RuntimeError( - f"Could not create config file at {CONFIG_FILE}!\n" + f"Could not create config file at {const.CONFIG_FILE}!\n" f"Error: {str(e)}" ) if force_restore: LOGGER.warning( - f"Config file at {CONFIG_FILE} was overwritten with " + f"Config file at {const.CONFIG_FILE} was overwritten with " f"default values." ) return - LOGGER.info(f"Created config file at {CONFIG_FILE}.") + LOGGER.info(f"Created config file at {const.CONFIG_FILE}.") def validate(config): @@ -92,7 +92,7 @@ def validate(config): for item in value: if not config.has_option(key, item): create(force_restore=True) - config.read(CONFIG_FILE, encoding="utf-8") + config.read(const.CONFIG_FILE, encoding="utf-8") # Further checks are not needed, because of overwrite. return config @@ -159,7 +159,7 @@ def validate(config): # If default values were needed, write config file on disk. if default_needed: LOGGER.warning( - f"One or more values in {CONFIG_FILE} were incorrect or not " + f"One or more values in {const.CONFIG_FILE} were incorrect or not " f"set. Corrected them to default values and wrote config file " f"on disk.", ) @@ -181,7 +181,7 @@ def load(config): # Parse config file. try: - config.read(CONFIG_FILE, encoding="utf-8") + config.read(const.CONFIG_FILE, encoding="utf-8") except ( configparser.MissingSectionHeaderError, @@ -189,7 +189,7 @@ def load(config): ) as e: LOGGER.error(f"Error while parsing config file: {str(e)}.") create(force_restore=True) - config.read(CONFIG_FILE, encoding="utf-8") + config.read(const.CONFIG_FILE, encoding="utf-8") # Further checks are not needed, because of overwrite. return config @@ -208,10 +208,5 @@ def write(config): :return: None """ - # TODO: vor dem schreiben config[whitelist] in str umwandeln und - # liste entfernen (erster und letzter char) und dann wieder in - # config speichern -> so sparen wir uns das parsen mit literal_eval - # überall in den anderen modulen. müsste man in load auch anpassen. - - with open(CONFIG_FILE, "w", encoding="utf-8") as config_file: + with open(const.CONFIG_FILE, "w", encoding="utf-8") as config_file: config.write(config_file) diff --git a/src/swiftguard/utils/helpers.py b/src/swiftguard/utils/helpers.py index 855c0d6..eb453c1 100644 --- a/src/swiftguard/utils/helpers.py +++ b/src/swiftguard/utils/helpers.py @@ -25,12 +25,7 @@ import requests -from swiftguard.const import ( - APP_PATH, - CURRENT_MODE, - CURRENT_PLATFORM, - DEVICE_RE, - ) +from swiftguard import const from swiftguard.utils import conf from swiftguard.utils.autostart import ( add_autostart, @@ -79,7 +74,7 @@ def devices_state(interface): def check_encryption(): # TODO: docstring # macOS: Check if FileVault (fv) is enabled. - if CURRENT_PLATFORM.startswith("DARWIN"): + if const.CURRENT_PLATFORM.startswith("DARWIN"): fv_command = ["/usr/bin/fdesetup", "isactive"] fv_process = subprocess.run( # nosec B603 @@ -113,16 +108,18 @@ def check_encryption(): def check_os(): - if CURRENT_PLATFORM.startswith("DARWIN"): + if const.CURRENT_PLATFORM.startswith("DARWIN"): LOGGER.info("Host system is supported (macOS).") - elif CURRENT_PLATFORM.startswith("LINUX"): + elif const.CURRENT_PLATFORM.startswith("LINUX"): # LOGGER.info("Host system is supported (Linux).") # return 0, "LINUX" raise NotImplementedError("Linux-support is still work in progress.") else: - raise RuntimeError(f"Host system not supported: {CURRENT_PLATFORM}") + raise RuntimeError( + f"Host system not supported: {const.CURRENT_PLATFORM}" + ) def startup(): @@ -136,7 +133,9 @@ def startup(): """ LOGGER.info("--------- Startup: ---------") - LOGGER.debug(f"APP_Path: {APP_PATH} \nCURRENT_MODE: {CURRENT_MODE}") + LOGGER.debug( + f"APP_Path: {const.APP_PATH} \n" f"CURRENT_MODE: {const.CURRENT_MODE}" + ) LOGGER.info("Starting swiftGuard and running startup checks ...") LOGGER.info( f"You are running swiftGuard version: {__version__} " f"({__build__})." @@ -222,7 +221,7 @@ def startup(): # conf_file.read_encrypted(CONFIG_FILE_ENC) # Get autostart setting and apply it (only supported in GUI mode). - if CURRENT_MODE == "app": + if const.CURRENT_MODE == "app": if config["User"]["autostart"] == "0": del_autostart() @@ -623,7 +622,7 @@ def _check_inside(result, devices): # Vendor ID. try: - vendor_id = DEVICE_RE[1].findall(result["vendor_id"])[0] + vendor_id = const.DEVICE_RE[1].findall(result["vendor_id"])[0] except IndexError: # Assume this is not a standard vendor_id (probably # apple_vendor_id instead of 0x....). @@ -631,7 +630,7 @@ def _check_inside(result, devices): # Product ID. try: - product_id = DEVICE_RE[1].findall(result["product_id"])[0] + product_id = const.DEVICE_RE[1].findall(result["product_id"])[0] except IndexError: # Assume this is not a standard product_id (0x....). product_id = result["product_id"] diff --git a/src/swiftguard/utils/listeners.py b/src/swiftguard/utils/listeners.py index 4737eda..809f97d 100644 --- a/src/swiftguard/utils/listeners.py +++ b/src/swiftguard/utils/listeners.py @@ -61,8 +61,8 @@ def listen(self): class ListenerUSB(Listeners): - def __init__(self): - super().__init__() + def __init__(self, intervall=1000): + super().__init__(intervall) self.start_connect_count = None self.start_allow_count = None @@ -85,11 +85,8 @@ def listen(self): self.start_connect_count == current_connect_count and self.start_allow_count == current_allow_count ): - print("KEIN menu update nötig") return - print("menu update NÖTIG") - # Update the start connected and allowed devices count, for next # function call/iteration. self.start_connect_count = current_connect_count @@ -98,7 +95,3 @@ def listen(self): # Emit signal to main thread to update the device menu with # passed device and whitelist data. self.triggered.emit() - - -# TODO: auch für update checking implementieren? intervall von 24h oder -# anhand von datetime oder runtime der app? QDate.currentDate()? diff --git a/src/swiftguard/utils/log.py b/src/swiftguard/utils/log.py index b455fc7..9969c78 100644 --- a/src/swiftguard/utils/log.py +++ b/src/swiftguard/utils/log.py @@ -18,18 +18,12 @@ # Imports. import logging import os -import platform import sys from logging.handlers import RotatingFileHandler import pyoslog -# Constants. -CURRENT_PLATFORM = platform.uname()[0].upper() -USER_HOME = os.path.expanduser("~") -APP_PATH = os.path.dirname(os.path.realpath(__file__)) -CONFIG_FILE = f"{USER_HOME}/Library/Preferences/swiftguard/swiftguard.ini" -LOG_FILE = f"{USER_HOME}/Library/Logs/swiftguard/swiftguard.log" +from swiftguard import const # Custom logging handler to count warnings, errors and criticals. @@ -51,15 +45,15 @@ def emit(self, record): def create_logger(counter): # Prepare directory for log file. - if not os.path.isdir(os.path.dirname(LOG_FILE)): - os.mkdir(os.path.dirname(LOG_FILE)) + if not os.path.isdir(os.path.dirname(const.LOG_FILE)): + os.mkdir(os.path.dirname(const.LOG_FILE)) # Create root logger. logger = logging.getLogger() # Log file: Rotate log file every 2 MB and keep 5 old log files. file_handler = RotatingFileHandler( - LOG_FILE, backupCount=5, maxBytes=2000000 + const.LOG_FILE, backupCount=5, maxBytes=2000000 ) # Stdout: Print log messages to stdout (only for startup). @@ -90,7 +84,7 @@ def create_logger(counter): def add_handler(logger_obj, dest): if dest == "syslog": # Syslog/Console: Log to syslog on macOS and to console on Linux. - if CURRENT_PLATFORM.startswith("DARWIN"): + if const.CURRENT_PLATFORM.startswith("DARWIN"): syslog_handler = pyoslog.Handler() syslog_handler.setSubsystem("dev.lennolium.swiftguard", "client") else: diff --git a/src/swiftguard/utils/upgrade.py b/src/swiftguard/utils/upgrade.py index 2479391..16f2cfd 100644 --- a/src/swiftguard/utils/upgrade.py +++ b/src/swiftguard/utils/upgrade.py @@ -16,3 +16,7 @@ __status__ = "Development" # Imports. + +# TODO: auch für update checking implementieren? intervall von 24h oder +# anhand von datetime oder runtime der app? QDate.currentDate()? +# also mit listeners class. diff --git a/src/swiftguard/utils/workers.py b/src/swiftguard/utils/workers.py index b067dea..746d123 100644 --- a/src/swiftguard/utils/workers.py +++ b/src/swiftguard/utils/workers.py @@ -26,7 +26,7 @@ from PySide6.QtCore import QObject, QThread, Signal -from swiftguard.const import CONFIG_FILE +from swiftguard import const from swiftguard.utils.helpers import ( bt_devices, devices_state, @@ -128,7 +128,7 @@ def whitelist(self): except Exception as e: raise e from RuntimeError( f"Could not parse allowed devices from config " - f"file. Please check your config file at {CONFIG_FILE} " + f"file. Please check your config file at {const.CONFIG_FILE} " f"for right formatting.\nExiting ... \nError: {str(e)}" )