Added Application HolidayViewer

This commit is contained in:
Kodjo Sossouvi
2025-06-27 07:26:58 +02:00
parent 66ea45f501
commit 9f4b8ab4d0
87 changed files with 3756 additions and 212 deletions

View File

@@ -1,10 +1,8 @@
import logging
from components.BaseComponent import BaseComponent
SESSION_ID_KEY = "user_id"
NO_SESSION = "__NO_SESSION__"
NOT_LOGGED = "__NOT_LOGGED__"
from constants import NO_SESSION
from core.utils import get_user_id
logger = logging.getLogger("InstanceManager")
@@ -14,7 +12,8 @@ def debug_session(session):
return f"session={NO_SESSION}"
else:
return f"session={InstanceManager.get_session_id(session)}"
class InstanceManager:
_instances = {}
@@ -45,7 +44,7 @@ class InstanceManager:
if issubclass(instance_type, BaseComponent) \
else instance_type(instance_id, **kwargs)
InstanceManager._instances[key] = new_instance
return InstanceManager._instances[key]
@staticmethod
@@ -103,6 +102,4 @@ class InstanceManager:
@staticmethod
def get_session_id(session: dict | None):
return session[SESSION_ID_KEY] if session else NOT_LOGGED
return get_user_id(session)

View File

@@ -1,8 +1,8 @@
import logging
from datetime import datetime
from constants import NOT_LOGGED, NO_SESSION
from core.dbengine import DbEngine, TAG_PARENT, TAG_USER, TAG_DATE, DbException
from core.instance_manager import NO_SESSION, NOT_LOGGED
from core.settings_objects import *
load_settings_obj() # needed to make sure that the import of core is not removed
@@ -13,6 +13,10 @@ logger = logging.getLogger(__name__)
class NoDefaultCls:
"""
No Default value class
Return when no default value is provided.
"""
pass
@@ -155,6 +159,14 @@ class SettingsTransaction:
class GenericDbManager:
"""
Given an obj_entry (entry in DbEngine) and obj_type (object to serialize),
>>> db = GenericDbManager(session, settings_manager, obj_entry, obj_type)
>>> db.prop_name = value # will save the value to the database.
>>> db.prop_name # will load the value from the database.
"""
def __init__(self, session, settings_manager: SettingsManager, obj_entry, obj_type):
self.__dict__["_session"] = session
self.__dict__["_settings_manager"] = settings_manager
@@ -167,7 +179,7 @@ class GenericDbManager:
settings = self._settings_manager.load(self._session, self._obj_entry, self._obj_type())
if not (hasattr(settings, key)):
raise AttributeError(f"Settings {self._obj_entry.__name__} has no attribute {key}")
raise AttributeError(f"Settings '{self._obj_entry}' has no attribute '{key}'.")
setattr(settings, key, value)
self._settings_manager.save(self._session, self._obj_entry, settings)
@@ -178,6 +190,68 @@ class GenericDbManager:
settings = self._settings_manager.load(self._session, self._obj_entry, self._obj_type())
if not (hasattr(settings, item)):
raise AttributeError(f"Settings {self._obj_entry.__name__} has no attribute {item}")
raise AttributeError(f"Settings '{self._obj_entry}' has no attribute '{item}'.")
return getattr(settings, item)
class NestedSettingsManager:
"""
Manages access and modification of a specific subset of persistent settings.
The GenericSubDbManager class provides mechanisms to dynamically get and set
attributes for a specified settings object accessed through a session. It
handles the retrieval, modification, and persistence of settings using a
settings manager, ensuring that only valid attributes can be managed.
Given an obj_entry (entry in DbEngine) and obj_type (object to serialize),
>>> db = NestedSettingsManager(session, settings_manager, obj_entry, obj_type, obj_attribute)
>>> db.prop_name = value # will save obj_type.obj_attribute.prop_name in database
>>> db.prop_name # will load obj_type.obj_attribute.prop_name from database
"""
def __init__(self, session: dict, settings_manager: SettingsManager, obj_entry, obj_type, obj_attribute):
self.__dict__["_session"] = session
self.__dict__["_settings_manager"] = settings_manager
self.__dict__["_obj_entry"] = obj_entry
self.__dict__["_obj_type"] = obj_type
self.__dict__["_obj_attribute"] = obj_attribute
def __getattr__(self, item):
if item.startswith("_"):
return super().__getattribute__(item)
settings, obj = self._get_settings_and_object()
if not hasattr(obj, item):
raise AttributeError(f"Settings '{self._obj_attribute}' has no attribute '{item}'.")
return getattr(obj, item)
def __setattr__(self, key, value):
if key.startswith("_"):
super().__setattr__(key, value)
settings, obj = self._get_settings_and_object()
if not (hasattr(obj, key)):
raise AttributeError(f"Settings '{self._obj_attribute}', from '{self._obj_entry}' has no attribute '{key}'.")
setattr(obj, key, value)
self._settings_manager.save(self._session, self._obj_entry, settings)
def update(self, values: dict, ignore_missing=False):
settings, obj = self._get_settings_and_object()
for k, v in values.items():
if hasattr(obj, k):
setattr(obj, k, v)
elif not ignore_missing:
raise AttributeError(f"Settings '{self._obj_attribute}', from '{self._obj_entry}' has no attribute '{k}'.")
self._settings_manager.save(self._session, self._obj_entry, settings)
def _get_settings_and_object(self):
settings = self._settings_manager.load(self._session, self._obj_entry, self._obj_type())
if not hasattr(settings, self._obj_attribute):
raise AttributeError(f"Settings '{self._obj_entry}' has no attribute '{self._obj_attribute}'.")
return settings, getattr(settings, self._obj_attribute)

View File

@@ -8,9 +8,12 @@ import types
import uuid
from enum import Enum
from io import BytesIO
from urllib.parse import urlparse
import pandas as pd
from constants import SESSION_USER_ID_KEY, NOT_LOGGED, NO_SESSION
PRIMITIVES = (str, bool, type(None), int, float)
@@ -378,3 +381,39 @@ def merge_classes(*args):
return " ".join(unique_elements)
else:
return None
def get_user_id(session: dict | None):
return str(session.get(SESSION_USER_ID_KEY, NOT_LOGGED)) if session is not None else NO_SESSION
def split_host_port(url):
"""
Split a URL into host and port components.
Args:
url (str): The full URL to split
Returns:
tuple: (host, port) where port is an integer if specified, otherwise None
"""
parsed_url = urlparse(url)
# Get netloc (host:port part)
netloc = parsed_url.netloc
# Split netloc by ':' to separate host and port
if ':' in netloc:
host, port_str = netloc.split(':', 1)
port = int(port_str)
else:
host = netloc
# Use default ports based on scheme if port is not specified
if parsed_url.scheme == 'http':
port = 80
elif parsed_url.scheme == 'https':
port = 443
else:
port = None
return host, port