Source code for fastapi_contrib.db.utils

import importlib
import motor.motor_asyncio
import pkgutil
import pyclbr
import random
import inspect

from typing import List

from fastapi import FastAPI

from fastapi_contrib.common.utils import logger, resolve_dotted_path
from fastapi_contrib.conf import settings


[docs]def default_id_generator(bit_size: int = 32) -> int: """ Generator of IDs for newly created MongoDB rows. :return: `bit_size` long int """ return random.getrandbits(bit_size)
[docs]def get_next_id() -> int: """ Retrieves ID generator function from the path, specified in project's conf. :return: newly generated ID """ # TODO: cache this id_generator = resolve_dotted_path(settings.mongodb_id_generator) return id_generator()
[docs]def setup_mongodb(app: FastAPI) -> None: """ Helper function to setup MongoDB connection & `motor` client during setup. Use during app startup as follows: .. code-block:: python app = FastAPI() @app.on_event('startup') async def startup(): setup_mongodb(app) :param app: app object, instance of FastAPI :return: None """ client = motor.motor_asyncio.AsyncIOMotorClient( settings.mongodb_dsn, minPoolSize=settings.mongodb_min_pool_size, maxPoolSize=settings.mongodb_max_pool_size, ) app.mongodb = client[settings.mongodb_dbname]
[docs]def get_db_client(): """ Gets instance of MongoDB client for you to make DB queries. :return: MongoDBClient """ from fastapi_contrib.db.client import MongoDBClient client = MongoDBClient() return client
[docs]def get_models() -> list: """ Scans `settings.apps_folder_name`. Find `models` modules in each of them and get all attributes there. Last step is to filter attributes to return only those, subclassed from MongoDBModel (or timestamped version). Used internally only by `create_indexes` function. :return: list of user-defined models (subclassed from MongoDBModel) in apps """ from fastapi_contrib.db.models import MongoDBModel apps_folder_name = settings.apps_folder_name models = [] for app in settings.apps: app_path = f"{apps_folder_name}/{app}" modules = [ f for f in pkgutil.walk_packages(path=[app_path]) if f.name == 'models' ] if not modules: continue for module in modules: path_to_models = f"{apps_folder_name}.{app}.models" mudule = importlib.import_module(path_to_models) if module.ispkg: module_models = [ x[0] for x in inspect.getmembers(mudule, inspect.isclass) ] else: try: module_models = pyclbr.readmodule(path_to_models).keys() except (AttributeError, ImportError): logger.warning( f"Unable to read module attributes in {path_to_models}" ) continue models.extend([getattr(mudule, model) for model in module_models]) return list(filter(lambda x: issubclass(x, MongoDBModel), models))
[docs]async def create_indexes() -> List[str]: """ Gets all models in project and then creates indexes for each one of them. :return: list of indexes that has been invoked to create (could've been created earlier, it doesn't raise in this case) """ models = get_models() indexes = [] for model in models: indexes.append(await model.create_indexes()) return list(filter(None, indexes))