| |
| |
| |
| |
| |
| |
|
|
| import ast |
| import os |
| import sys |
|
|
| from .. import run_as_module |
| from . import * |
|
|
| if run_as_module: |
| from ..configs import Var |
|
|
|
|
| Redis = MongoClient = psycopg2 = Database = None |
| if Var.REDIS_URI or Var.REDISHOST: |
| try: |
| from redis import Redis |
| except ImportError: |
| LOGS.info("Installing 'redis' for database.") |
| os.system(f"{sys.executable} -m pip install -q redis hiredis") |
| from redis import Redis |
| elif Var.MONGO_URI: |
| try: |
| from pymongo import MongoClient |
| except ImportError: |
| LOGS.info("Installing 'pymongo' for database.") |
| os.system(f"{sys.executable} -m pip install -q pymongo[srv]") |
| from pymongo import MongoClient |
| elif Var.DATABASE_URL: |
| try: |
| import psycopg2 |
| except ImportError: |
| LOGS.info("Installing 'pyscopg2' for database.") |
| os.system(f"{sys.executable} -m pip install -q psycopg2-binary") |
| import psycopg2 |
| else: |
| try: |
| from localdb import Database |
| except ImportError: |
| LOGS.info("Using local file as database.") |
| os.system(f"{sys.executable} -m pip install -q localdb.json") |
| from localdb import Database |
|
|
| |
|
|
|
|
| class _BaseDatabase: |
| def __init__(self, *args, **kwargs): |
| self._cache = {} |
|
|
| def get_key(self, key): |
| if key in self._cache: |
| return self._cache[key] |
| value = self._get_data(key) |
| self._cache.update({key: value}) |
| return value |
|
|
| def re_cache(self): |
| self._cache.clear() |
| for key in self.keys(): |
| self._cache.update({key: self.get_key(key)}) |
|
|
| def ping(self): |
| return 1 |
|
|
| @property |
| def usage(self): |
| return 0 |
|
|
| def keys(self): |
| return [] |
|
|
| def del_key(self, key): |
| if key in self._cache: |
| del self._cache[key] |
| self.delete(key) |
| return True |
|
|
| def _get_data(self, key=None, data=None): |
| if key: |
| data = self.get(str(key)) |
| if data and isinstance(data, str): |
| try: |
| data = ast.literal_eval(data) |
| except BaseException: |
| pass |
| return data |
|
|
| def set_key(self, key, value, cache_only=False): |
| value = self._get_data(data=value) |
| self._cache[key] = value |
| if cache_only: |
| return |
| return self.set(str(key), str(value)) |
|
|
| def rename(self, key1, key2): |
| _ = self.get_key(key1) |
| if _: |
| self.del_key(key1) |
| self.set_key(key2, _) |
| return 0 |
| return 1 |
|
|
|
|
| class MongoDB(_BaseDatabase): |
| def __init__(self, key, dbname="UltroidDB"): |
| self.dB = MongoClient(key, serverSelectionTimeoutMS=5000) |
| self.db = self.dB[dbname] |
| super().__init__() |
|
|
| def __repr__(self): |
| return f"<Ultroid.MonGoDB\n -total_keys: {len(self.keys())}\n>" |
|
|
| @property |
| def name(self): |
| return "Mongo" |
|
|
| @property |
| def usage(self): |
| return self.db.command("dbstats")["dataSize"] |
|
|
| def ping(self): |
| if self.dB.server_info(): |
| return True |
|
|
| def keys(self): |
| return self.db.list_collection_names() |
|
|
| def set(self, key, value): |
| if key in self.keys(): |
| self.db[key].replace_one({"_id": key}, {"value": str(value)}) |
| else: |
| self.db[key].insert_one({"_id": key, "value": str(value)}) |
| return True |
|
|
| def delete(self, key): |
| self.db.drop_collection(key) |
|
|
| def get(self, key): |
| if x := self.db[key].find_one({"_id": key}): |
| return x["value"] |
|
|
| def flushall(self): |
| self.dB.drop_database("UltroidDB") |
| self._cache.clear() |
| return True |
|
|
|
|
| |
|
|
| |
| |
| |
| |
|
|
|
|
| class SqlDB(_BaseDatabase): |
| def __init__(self, url): |
| self._url = url |
| self._connection = None |
| self._cursor = None |
| try: |
| self._connection = psycopg2.connect(dsn=url) |
| self._connection.autocommit = True |
| self._cursor = self._connection.cursor() |
| self._cursor.execute( |
| "CREATE TABLE IF NOT EXISTS Ultroid (ultroidCli varchar(70))" |
| ) |
| except Exception as error: |
| LOGS.exception(error) |
| LOGS.info("Invaid SQL Database") |
| if self._connection: |
| self._connection.close() |
| sys.exit() |
| super().__init__() |
|
|
| @property |
| def name(self): |
| return "SQL" |
|
|
| @property |
| def usage(self): |
| self._cursor.execute( |
| "SELECT pg_size_pretty(pg_relation_size('Ultroid')) AS size" |
| ) |
| data = self._cursor.fetchall() |
| return int(data[0][0].split()[0]) |
|
|
| def keys(self): |
| self._cursor.execute( |
| "SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ultroid'" |
| ) |
| data = self._cursor.fetchall() |
| return [_[0] for _ in data] |
|
|
| def get(self, variable): |
| try: |
| self._cursor.execute(f"SELECT {variable} FROM Ultroid") |
| except psycopg2.errors.UndefinedColumn: |
| return None |
| data = self._cursor.fetchall() |
| if not data: |
| return None |
| if len(data) >= 1: |
| for i in data: |
| if i[0]: |
| return i[0] |
|
|
| def set(self, key, value): |
| try: |
| self._cursor.execute(f"ALTER TABLE Ultroid DROP COLUMN IF EXISTS {key}") |
| except (psycopg2.errors.UndefinedColumn, psycopg2.errors.SyntaxError): |
| pass |
| except BaseException as er: |
| LOGS.exception(er) |
| self._cache.update({key: value}) |
| self._cursor.execute(f"ALTER TABLE Ultroid ADD {key} TEXT") |
| self._cursor.execute(f"INSERT INTO Ultroid ({key}) values (%s)", (str(value),)) |
| return True |
|
|
| def delete(self, key): |
| try: |
| self._cursor.execute(f"ALTER TABLE Ultroid DROP COLUMN {key}") |
| except psycopg2.errors.UndefinedColumn: |
| return False |
| return True |
|
|
| def flushall(self): |
| self._cache.clear() |
| self._cursor.execute("DROP TABLE Ultroid") |
| self._cursor.execute( |
| "CREATE TABLE IF NOT EXISTS Ultroid (ultroidCli varchar(70))" |
| ) |
| return True |
|
|
|
|
| |
|
|
|
|
| class RedisDB(_BaseDatabase): |
| def __init__( |
| self, |
| host, |
| port, |
| password, |
| platform="", |
| logger=LOGS, |
| *args, |
| **kwargs, |
| ): |
| if host and ":" in host: |
| spli_ = host.split(":") |
| host = spli_[0] |
| port = int(spli_[-1]) |
| if host.startswith("http"): |
| logger.error("Your REDIS_URI should not start with http !") |
| import sys |
|
|
| sys.exit() |
| elif not host or not port: |
| logger.error("Port Number not found") |
| import sys |
|
|
| sys.exit() |
| kwargs["host"] = host |
| kwargs["password"] = password |
| kwargs["port"] = port |
|
|
| if platform.lower() == "qovery" and not host: |
| var, hash_, host, password = "", "", "", "" |
| for vars_ in os.environ: |
| if vars_.startswith("QOVERY_REDIS_") and vars.endswith("_HOST"): |
| var = vars_ |
| if var: |
| hash_ = var.split("_", maxsplit=2)[1].split("_")[0] |
| if hash: |
| kwargs["host"] = os.environ.get(f"QOVERY_REDIS_{hash_}_HOST") |
| kwargs["port"] = os.environ.get(f"QOVERY_REDIS_{hash_}_PORT") |
| kwargs["password"] = os.environ.get(f"QOVERY_REDIS_{hash_}_PASSWORD") |
| self.db = Redis(**kwargs) |
| self.set = self.db.set |
| self.get = self.db.get |
| self.keys = self.db.keys |
| self.delete = self.db.delete |
| super().__init__() |
|
|
| @property |
| def name(self): |
| return "Redis" |
|
|
| @property |
| def usage(self): |
| return sum(self.db.memory_usage(x) for x in self.keys()) |
|
|
|
|
| |
|
|
|
|
| class LocalDB(_BaseDatabase): |
| def __init__(self): |
| self.db = Database("ultroid") |
| self.get = self.db.get |
| self.set = self.db.set |
| self.delete = self.db.delete |
| super().__init__() |
|
|
| @property |
| def name(self): |
| return "LocalDB" |
|
|
| def keys(self): |
| return self._cache.keys() |
|
|
| def __repr__(self): |
| return f"<Ultroid.LocalDB\n -total_keys: {len(self.keys())}\n>" |
|
|
|
|
| def UltroidDB(): |
| _er = False |
| from .. import HOSTED_ON |
|
|
| try: |
| if Redis: |
| return RedisDB( |
| host=Var.REDIS_URI or Var.REDISHOST, |
| password=Var.REDIS_PASSWORD or Var.REDISPASSWORD, |
| port=Var.REDISPORT, |
| platform=HOSTED_ON, |
| decode_responses=True, |
| socket_timeout=5, |
| retry_on_timeout=True, |
| ) |
| elif MongoClient: |
| return MongoDB(Var.MONGO_URI) |
| elif psycopg2: |
| return SqlDB(Var.DATABASE_URL) |
| else: |
| LOGS.critical( |
| "No DB requirement fullfilled!\nPlease install redis, mongo or sql dependencies...\nTill then using local file as database." |
| ) |
| return LocalDB() |
| except BaseException as err: |
| LOGS.exception(err) |
| exit() |
|
|
|
|
| |
|
|