"""This module contains utilities for creating fake database entries.""" from random import randint from faker import Faker from sqlalchemy.orm import Session from todo.schemas.users import UserCreate, User from todo.auth.auth import AuthHandler from todo.models.users import User as UserModel from todo.schemas.todos import TodoItemCreate, TodoItem from todo.models.todos import TodoItem as TodoItemModel from todo.database.engine import get_db auth_handler = AuthHandler() def _get_faker() -> Faker: """Creates and returns a Faker object.""" return Faker() def get_fake_user_details() -> UserCreate: """Returns a set of fake details for creating a new user.""" fk = _get_faker() email = fk.profile(fields=['mail'])['mail'] first_name = fk.first_name() last_name = fk.last_name() password = email return UserCreate( email=email, first_name=first_name, last_name=last_name, password=password, password_confirmation=password, is_admin=False, ) def get_fake_todo_details() -> TodoItemCreate: """Returns a set of fake details for creating a new todo-item.""" fk = _get_faker() title = fk.sentence(nb_words=randint(4, 6)) # Generate some sentences and concatenate them with a randomized delimiter description_sentences = [fk.sentence(nb_words=randint(4, 6)) for i in range(randint(1, 5))] if randint(0, 1): delimiter = '\n- ' description_sentences[0] = "- " + description_sentences[0] elif randint(0, 1): delimiter = '\n' else: delimiter = ' ' description = delimiter.join(description_sentences) return TodoItemCreate( title=title, description=description, ) def create_fake_user(db: Session = next(get_db())) -> User: """Creates a fake user and saves them to the database.""" user = get_fake_user_details() fk = _get_faker() created = fk.date_time_between('-2y', 'now') updated = fk.date_time_between(created, 'now') is_admin = randint(0, 10) == 0 db_user = UserModel( email=user.email, first_name=user.first_name, last_name=user.last_name, password=auth_handler.hash_password(user.password), created=created, updated=updated, is_admin=is_admin, ) db.add(db_user) db.commit() db.refresh(db_user) return User.from_orm(db_user) def create_fake_todo(user_id: int, db: Session = next(get_db())) -> TodoItem: """Creates a fake todo-item for the specified user and saves it to the database.""" todo = get_fake_todo_details() db_user = db.query(UserModel).filter(UserModel.id == user_id).first() if not db_user: raise RuntimeError('User not found.') fk = _get_faker() created = fk.date_time_between(db_user.created, 'now') if randint(1, 4) == 1: updated = fk.date_time_between(created, 'now') else: updated = created if randint(1, 4) == 1: finished = fk.date_time_between(created, 'now') updated = finished done = True else: finished = None done = False db_todo = TodoItemModel( user_id=user_id, title=todo.title, description=todo.description, done=done, created=created, updated=updated, finished=finished ) db.add(db_todo) db.commit() db.refresh(db_todo) return TodoItem.from_orm(db_todo) def populate_database(num_users: int = randint(50, 150), max_todos_per_user: int = randint(50, 150)) -> None: """Creates the specified number of users, each with between 0 and max_todos_per_user todo-items.""" db = next(get_db()) for i in range(num_users): user = create_fake_user(db) for j in range(randint(0, max_todos_per_user)): create_fake_todo(user.id, db)