diff --git a/utilix/__init__.py b/utilix/__init__.py index 778c481..033314d 100644 --- a/utilix/__init__.py +++ b/utilix/__init__.py @@ -3,7 +3,7 @@ from . import config # try loading config, if it doesn't work then set uconfig to None -# this is needed so that strax(en) CI tests will work even without a config file +# this is needed so that strax(en) CI tests will work even without a config file uconfig = config.Config() if uconfig.is_configured: diff --git a/utilix/batchq.py b/utilix/batchq.py index 710f36f..b702a5a 100644 --- a/utilix/batchq.py +++ b/utilix/batchq.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Literal, Optional from pydantic import BaseModel, Field, validator from simple_slurm import Slurm # type: ignore -from utilix import logger +from . import logger USER: Optional[str] = os.environ.get("USER") if USER is None: diff --git a/utilix/config.py b/utilix/config.py index a2ae9d3..bcecbe8 100644 --- a/utilix/config.py +++ b/utilix/config.py @@ -5,6 +5,8 @@ def setup_logger(logging_level="WARNING"): logger = logging.getLogger("utilix") + if logger.hasHandlers(): + logger.handlers.clear() ch = logging.StreamHandler() ch.setLevel(logging_level) logger.setLevel(logging_level) diff --git a/utilix/rundb.py b/utilix/rundb.py index bad581e..2bf3911 100644 --- a/utilix/rundb.py +++ b/utilix/rundb.py @@ -5,20 +5,17 @@ import datetime import logging import pymongo +from typing import Tuple, Dict from warnings import warn import time -from . import uconfig, io -from .config import setup_logger +from . import uconfig, logger, io # Config the logger: if uconfig is not None: # type: ignore PREFIX = uconfig.get("RunDB", "rundb_api_url", fallback=None) # type: ignore BASE_HEADERS = {"Content-Type": "application/json", "Cache-Control": "no-cache"} - logger = setup_logger(uconfig.logging_level) # type: ignore -else: - logger = setup_logger() class NewTokenError(Exception): @@ -181,8 +178,24 @@ def write(self): class DB: """Wrapper around the RunDB API.""" - def __init__(self, token_path=None): + _instances: Dict[Tuple, "DB"] = {} + _initialized: Dict[Tuple, bool] = {} + def __new__(cls, *args, **kwargs): + key = (args, frozenset(kwargs.items())) + if key not in cls._instances: + cls._instances[key] = super(DB, cls).__new__(cls) + cls._initialized[key] = False + return cls._instances[key] + + def __init__(self, *args, **kwargs): + key = (args, frozenset(kwargs.items())) + if not self._initialized[key]: + self._instances[key].initialize(*args, **kwargs) + self._initialized[key] = True + return + + def initialize(self, token_path=None): if token_path is None: if "HOME" not in os.environ: logger.error("$HOME is not defined in the environment") @@ -505,10 +518,11 @@ class PyMongoCannotConnect(Exception): def test_collection(collection, url, raise_errors=False): - """Warn user if client can be troublesome if read preference is not specified :param collection: + """Warn user if client can be troublesome if read preference is not specified. - pymongo client :param url: the mongo url we are testing (for the error message) :param - raise_errors: if False (default) warn, otherwise raise an error. + :param collection: pymongo client + :param url: the mongo url we are testing (for the error message) + :param raise_errors: if False (default) warn, otherwise raise an error. """ try: