From 8fcffb5f3eabf1567fd852227648ca64cea27e1d Mon Sep 17 00:00:00 2001
From: jkerdreux-imt <jerome.kerdreux@imt-atlantique.fr>
Date: Tue, 26 Nov 2024 17:27:48 +0100
Subject: [PATCH] I changed the config loading to comply pylint/pyright

Since the begining this code was hacky. I switched to something more
linter friendly
---
 libs/lib/xaal/lib/__init__.py  |   2 +-
 libs/lib/xaal/lib/aioengine.py |   3 +-
 libs/lib/xaal/lib/config.py    | 113 +++++++++++++++++++++------------
 libs/lib/xaal/lib/engine.py    |   3 +-
 libs/lib/xaal/lib/helpers.py   |   2 +-
 libs/lib/xaal/lib/messages.py  |   3 +-
 libs/lib/xaal/lib/tools.py     |   2 +-
 7 files changed, 80 insertions(+), 48 deletions(-)

diff --git a/libs/lib/xaal/lib/__init__.py b/libs/lib/xaal/lib/__init__.py
index d341539d..7178c8fa 100644
--- a/libs/lib/xaal/lib/__init__.py
+++ b/libs/lib/xaal/lib/__init__.py
@@ -3,8 +3,8 @@
 # Load main class & modules.
 
 
+from .config import config
 from . import tools
-from . import config
 from . import bindings
 from . import aiohelpers as helpers
 
diff --git a/libs/lib/xaal/lib/aioengine.py b/libs/lib/xaal/lib/aioengine.py
index 1e6f3603..acb663f3 100644
--- a/libs/lib/xaal/lib/aioengine.py
+++ b/libs/lib/xaal/lib/aioengine.py
@@ -12,7 +12,8 @@ from uuid import UUID
 import aioconsole
 from tabulate import tabulate
 
-from . import config, core, tools
+from .config import config
+from . import core, tools
 from .aionetwork import AsyncNetworkConnector
 from .exceptions import CallbackError, XAALError
 from .messages import MessageParserError
diff --git a/libs/lib/xaal/lib/config.py b/libs/lib/xaal/lib/config.py
index 0989bc5b..4cf2af91 100644
--- a/libs/lib/xaal/lib/config.py
+++ b/libs/lib/xaal/lib/config.py
@@ -1,53 +1,82 @@
 
 # Default configuration
+
 import os
 import sys
 import binascii
 from configobj import ConfigObj
 
-self = sys.modules[__name__]
-
 # Default settings
-DEF_ADDR = '224.0.29.200'       # mcast address
-DEF_PORT = 1236                 # mcast port
-DEF_HOPS = 10                   # mcast hop
-DEF_ALIVE_TIMER = 100           # Time between two alive msg
-DEF_CIPHER_WINDOW = 60 * 2      # Time Window in seconds to avoid replay attacks
-DEF_QUEUE_SIZE = 10             # How many packet we can send in one loop
-DEF_LOG_LEVEL = 'DEBUG'         # should be INFO|DEBUG|None
-DEF_LOG_PATH  = '/var/log/xaal' # where log are 
-
-# TBD : Move this stuff
+DEF_ADDR = '224.0.29.200'
+DEF_PORT = 1236
+DEF_HOPS = 10
+DEF_ALIVE_TIMER = 100
+DEF_CIPHER_WINDOW = 60 * 2
+DEF_QUEUE_SIZE = 10
+DEF_LOG_LEVEL = 'DEBUG'
+DEF_LOG_PATH = '/var/log/xaal'
+
 STACK_VERSION = 7
 
+class Config:
+    def __init__(self):
+        self.conf_dir = os.environ.get('XAAL_CONF_DIR', os.path.expanduser("~/.xaal"))
+        self.address = DEF_ADDR
+        self.port = DEF_PORT
+        self.hops = DEF_HOPS
+        self.alive_timer = DEF_ALIVE_TIMER
+        self.cipher_window = DEF_CIPHER_WINDOW
+        self.queue_size = DEF_QUEUE_SIZE
+        self.log_level = DEF_LOG_LEVEL
+        self.log_path = DEF_LOG_PATH
+        self.key = b''
+        self.STACK_VERSION = STACK_VERSION
+
+    def load(self, name='xaal.ini'):
+        filename = os.path.join(self.conf_dir, name)
+        if not os.path.isfile(filename):
+            raise FileNotFoundError(f"Unable to load xAAL config file [{filename}]")
+
+        cfg = ConfigObj(filename)
+        self.address = self.safe_string(cfg.get('address'), DEF_ADDR)
+        self.port = self.safe_int(cfg.get('port'), DEF_PORT)
+        self.hops = self.safe_int(cfg.get('hops'), DEF_HOPS)
+        self.alive_timer = self.safe_int(cfg.get('alive_timer'), DEF_ALIVE_TIMER)
+        self.cipher_window = self.safe_int(cfg.get('cipher_window'), DEF_CIPHER_WINDOW)
+        self.queue_size = self.safe_int(cfg.get('queue_size'), DEF_QUEUE_SIZE)
+        self.log_level = self.safe_string(cfg.get('log_level'), DEF_LOG_LEVEL)
+        self.log_path = self.safe_string(cfg.get('log_path'), DEF_LOG_PATH)
+        key = cfg.get('key', None)
+        if key and type(key) is str:
+            self.key = binascii.unhexlify(key.encode('utf-8'))
+        else:
+            raise ValueError(f"Key not set in config file [{filename}]")
+
+    ## Helper functions
+    # Pylint enforce to sanity check the input. In fact, ConfigObj can do the job without issue
+    # but Pytlint assume cfg.get can return None (even w/ default set), so it warm about wrong
+    # type in all config setting. By doing this I insure that the value is of the right type.
+
+    @staticmethod
+    def safe_int(value, default):
+        try:
+            return int(value)
+        except (ValueError, TypeError):
+            return default
+
+    @staticmethod
+    def safe_string(value, default):
+        if value is None:
+            return default
+        try:
+            return str(value)
+        except (ValueError, TypeError):
+            return default
+
 
-if 'XAAL_CONF_DIR' in os.environ:
-    self.conf_dir = os.environ['XAAL_CONF_DIR']
-else:
-    self.conf_dir = os.path.expanduser("~") + '/.xaal'
-
-
-def load_config(name: str ='xaal.ini'):
-    filename = os.path.join(self.conf_dir, name)
-    if not os.path.isfile(filename):
-        print("Unable to load xAAL config file [%s]" % filename)
-        sys.exit(-1)
-
-    cfg = ConfigObj(filename)
-    self.address       = cfg.get('address',DEF_ADDR)
-    self.port          = int(cfg.get('port',DEF_PORT))
-    self.hops          = int(cfg.get('hops',DEF_HOPS))
-    self.alive_timer   = int(cfg.get('alive_timer',DEF_ALIVE_TIMER))
-    self.cipher_window = int(cfg.get('ciper_window',DEF_CIPHER_WINDOW))
-    self.queue_size    = int(cfg.get('queue_size',DEF_QUEUE_SIZE))
-    self.log_level     = cfg.get('log_level',DEF_LOG_LEVEL)
-    self.log_path      = cfg.get('log_path',DEF_LOG_PATH)
-    key = cfg.get('key',None)
-
-    if key:
-        self.key = binascii.unhexlify(key.encode('utf-8'))
-    else:
-        print("Please set key in config file [%s]" % filename)
-        self.key = None
-
-load_config()
+config = Config()
+try:
+    config.load()
+except Exception as e:
+    print(e)
+    sys.exit(-1)
diff --git a/libs/lib/xaal/lib/engine.py b/libs/lib/xaal/lib/engine.py
index b3c639fd..6bddc30d 100644
--- a/libs/lib/xaal/lib/engine.py
+++ b/libs/lib/xaal/lib/engine.py
@@ -25,7 +25,8 @@ import typing
 from enum import Enum
 from typing import Any, Optional
 
-from . import config, core
+from .config import config
+from . import core
 from .exceptions import CallbackError, MessageParserError, XAALError
 from .network import NetworkConnector
 
diff --git a/libs/lib/xaal/lib/helpers.py b/libs/lib/xaal/lib/helpers.py
index 3d9197eb..9e0d5720 100644
--- a/libs/lib/xaal/lib/helpers.py
+++ b/libs/lib/xaal/lib/helpers.py
@@ -12,7 +12,7 @@ from typing import Any, Optional
 import coloredlogs
 from decorator import decorator
 
-from . import config
+from .config import config
 
 
 def singleton(class_):
diff --git a/libs/lib/xaal/lib/messages.py b/libs/lib/xaal/lib/messages.py
index 174d0ef8..f80481e7 100644
--- a/libs/lib/xaal/lib/messages.py
+++ b/libs/lib/xaal/lib/messages.py
@@ -30,7 +30,8 @@ from typing import Any, Optional
 import pysodium
 from tabulate import tabulate
 
-from . import cbor, config, tools
+from . import cbor, tools
+from .config import config
 from .bindings import UUID
 from .exceptions import MessageError, MessageParserError
 
diff --git a/libs/lib/xaal/lib/tools.py b/libs/lib/xaal/lib/tools.py
index 0c4cbac6..bfcb52d3 100644
--- a/libs/lib/xaal/lib/tools.py
+++ b/libs/lib/xaal/lib/tools.py
@@ -27,7 +27,7 @@ from typing import Optional, Union
 import pysodium
 from configobj import ConfigObj
 
-from . import config
+from .config import config
 from .bindings import UUID
 
 XAAL_DEVTYPE_PATTERN = "^[a-zA-Z][a-zA-Z0-9_-]*\\.[a-zA-Z][a-zA-Z0-9_-]*$"
-- 
GitLab