"""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.crud.users import hash_password 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 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() password = fk.password(length=randint(6, 16)) email = fk.profile(fields=['mail'])['mail'] first_name = fk.first_name() last_name = fk.last_name() return UserCreate( email=email, first_name=first_name, last_name=last_name, password=password, password_confirmation=password, ) 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') db_user = UserModel( email=user.email, first_name=user.first_name, last_name=user.last_name, password=hash_password(user.password), created=created, updated=updated, ) 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)