From b1d3c26b077f7742434d8f929b11e3b378bb45be Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 2 Nov 2023 19:38:09 +0100 Subject: [PATCH] Apply SIM --- advlabdb/adminModelViews.py | 5 +- advlabdb/forms.py | 6 +- advlabdb/models.py | 10 +- advlabdb/routes.py | 15 +- cli/maintain/reset_admin_password/main.py | 49 ++-- cli/setup/init_db/main.py | 91 +++--- cli/test/generate_test_db/main.py | 340 +++++++++++----------- pyproject.toml | 2 +- 8 files changed, 245 insertions(+), 273 deletions(-) diff --git a/advlabdb/adminModelViews.py b/advlabdb/adminModelViews.py index dbcbfa8..43617ac 100644 --- a/advlabdb/adminModelViews.py +++ b/advlabdb/adminModelViews.py @@ -1084,9 +1084,8 @@ class GroupExperimentView(SecureAdminModelView): self.session.add(appointment) def after_model_change(self, form, model, is_created): - if is_created: - if model.appointments: - flash(f"Appointments {model.appointments} added.", "success") + if is_created and model.appointments: + flash(f"Appointments {model.appointments} added.", "success") def groupExperimentQueryFactory(): diff --git a/advlabdb/forms.py b/advlabdb/forms.py index 148741c..0bad35c 100644 --- a/advlabdb/forms.py +++ b/advlabdb/forms.py @@ -20,11 +20,7 @@ def assistant_group_experiment_form_factory(current_user, group_experiment): appointments = group_experiment.appointments appointment_num = 1 for appointment in appointments: - description = None - if appointment.special: - description = "Yes" - else: - description = "No" + description = "Yes" if appointment.special else "No" setattr( AssistantGroupExperimentForm, diff --git a/advlabdb/models.py b/advlabdb/models.py index ee8ca59..fd200e7 100644 --- a/advlabdb/models.py +++ b/advlabdb/models.py @@ -231,10 +231,7 @@ class Group(db.Model): .order_by(Group.number.desc()) ) - if highestGroupNumber is not None: - number = highestGroupNumber + 1 - else: - number = 1 + number = highestGroupNumber + 1 if highestGroupNumber is not None else 1 return Group( program=program, @@ -529,9 +526,8 @@ class Semester(db.Model): def __init__(self, label, year, **kwargs): last_semester = Semester.lastSemester() - if last_semester is not None: - if year < last_semester.year or (year == last_semester.year and label == "SS"): - raise DatabaseException(f"You can only create semesters later than the last semester {last_semester}!") + if last_semester is not None and (year < last_semester.year or (year == last_semester.year and label == "SS")): + raise DatabaseException(f"You can only create semesters later than the last semester {last_semester}!") super().__init__(label=label, year=year, **kwargs) diff --git a/advlabdb/routes.py b/advlabdb/routes.py index c50ddb0..bda4c86 100644 --- a/advlabdb/routes.py +++ b/advlabdb/routes.py @@ -44,15 +44,9 @@ def post_login(): if current_active_semester.done: current_user.set_last_semester_as_active() - if current_user.has_role("admin"): - endpoint_base = "admin" - else: - endpoint_base = "assistant" + endpoint_base = "admin" if current_user.has_role("admin") else "assistant" - if current_user.login_count == 1: - url = url_for(endpoint_base + "_docs.index") - else: - url = url_for(endpoint_base + ".index") + url = url_for(endpoint_base + "_docs.index") if current_user.login_count == 1 else url_for(endpoint_base + ".index") return redirect(url) @@ -60,10 +54,7 @@ def post_login(): @bp.route("/user-settings") @auth_required() def user_settings(): - if current_user.has_role("admin"): - role = "admin" - else: - role = "assistant" + role = "admin" if current_user.has_role("admin") else "assistant" url = url_for("main.index") + role + "/user/edit/?id=" + str(current_user.id) diff --git a/cli/maintain/reset_admin_password/main.py b/cli/maintain/reset_admin_password/main.py index 8e71703..62d26a9 100644 --- a/cli/maintain/reset_admin_password/main.py +++ b/cli/maintain/reset_admin_password/main.py @@ -12,39 +12,38 @@ def _reset_admin_password(manage): app = create_app(create_for_server=False) - with app.app_context(): - with db.session.begin(): - admins = db.session.scalars(select(Admin).join(User).where(User.active is True)).all() - activate_user = False + with app.app_context(), db.session.begin(): + admins = db.session.scalars(select(Admin).join(User).where(User.active is True)).all() + activate_user = False - if len(admins) == 0: - click.echo("There is no admin with an active user. The user of the chosen admin will be activated.") - admins = db.session.scalars(select(Admin)).all() - activate_user = True + if len(admins) == 0: + click.echo("There is no admin with an active user. The user of the chosen admin will be activated.") + admins = db.session.scalars(select(Admin)).all() + activate_user = True - num_admins = len(admins) + num_admins = len(admins) - prompt = "Admins:\n" - for ind, admin in enumerate(admins): - user = admin.user - prompt += f"[{ind}] {user.first_name} {user.last_name}: {user.email}\n" - prompt += f"Enter number [0-{num_admins - 1}]" + prompt = "Admins:\n" + for ind, admin in enumerate(admins): + user = admin.user + prompt += f"[{ind}] {user.first_name} {user.last_name}: {user.email}\n" + prompt += f"Enter number [0-{num_admins - 1}]" - admin_index = click.prompt( - prompt, - type=click.IntRange(0, num_admins - 1), - ) + admin_index = click.prompt( + prompt, + type=click.IntRange(0, num_admins - 1), + ) - chosen_admin_user = admins[admin_index].user + chosen_admin_user = admins[admin_index].user - new_password = randomPassword() + new_password = randomPassword() - admin_change_password( - chosen_admin_user, new_password, notify=False - ) # Password is automatically hashed with this function + admin_change_password( + chosen_admin_user, new_password, notify=False + ) # Password is automatically hashed with this function - if activate_user: - chosen_admin_user.active = True + if activate_user: + chosen_admin_user.active = True manage.box(f"New password: {new_password}") diff --git a/cli/setup/init_db/main.py b/cli/setup/init_db/main.py index f8fcd48..707d09a 100644 --- a/cli/setup/init_db/main.py +++ b/cli/setup/init_db/main.py @@ -24,64 +24,61 @@ def _init_db(manage): app = create_app(create_for_server=False) - with app.app_context(): - with db.session.begin(): - # Create new database - db.create_all() + with app.app_context(), db.session.begin(): + # Create new database + db.create_all() - semester_label = click.prompt( - "Enter the label of the current semester", - type=click.Choice(("SS", "WS")), - ) - semester_year = click.prompt( - f"Enter the year of the current semester (between {MIN_YEAR} and {MAX_YEAR})", - type=click.IntRange(MIN_YEAR, MAX_YEAR), - ) + semester_label = click.prompt( + "Enter the label of the current semester", + type=click.Choice(("SS", "WS")), + ) + semester_year = click.prompt( + f"Enter the year of the current semester (between {MIN_YEAR} and {MAX_YEAR})", + type=click.IntRange(MIN_YEAR, MAX_YEAR), + ) - semester = Semester(label=semester_label, year=semester_year) + semester = Semester(label=semester_label, year=semester_year) - db.session.add(semester) + db.session.add(semester) - adminRole = user_datastore.create_role(name="admin") - user_datastore.create_role(name="assistant") + adminRole = user_datastore.create_role(name="admin") + user_datastore.create_role(name="assistant") - manage.box("The first admin account will be created now.") + manage.box("The first admin account will be created now.") - admin_email = click.prompt( - "Enter the admin's email address", - type=EmailParamType(), - ) + admin_email = click.prompt( + "Enter the admin's email address", + type=EmailParamType(), + ) - admin_first_name = click.prompt("Enter the admin's first name") - admin_last_name = click.prompt("Enter the admin's last name") - admin_phone_number = click.prompt( - "Enter the admin's phone number (optional)", default="", show_default=False - ) - admin_mobile_phone_number = click.prompt( - "Enter the admin's mobile phone number (optional)", default="", show_default=False - ) - admin_building = click.prompt("Enter the admin's building (optional)", default="", show_default=False) - admin_room = click.prompt("Enter the admin's room (optional)", default="", show_default=False) + admin_first_name = click.prompt("Enter the admin's first name") + admin_last_name = click.prompt("Enter the admin's last name") + admin_phone_number = click.prompt("Enter the admin's phone number (optional)", default="", show_default=False) + admin_mobile_phone_number = click.prompt( + "Enter the admin's mobile phone number (optional)", default="", show_default=False + ) + admin_building = click.prompt("Enter the admin's building (optional)", default="", show_default=False) + admin_room = click.prompt("Enter the admin's room (optional)", default="", show_default=False) - admin_password = randomPassword() - admin_hashed_password = hash_password(admin_password) + admin_password = randomPassword() + admin_hashed_password = hash_password(admin_password) - admin_user = user_datastore.create_user( - email=admin_email, - password=admin_hashed_password, - roles=[adminRole], - first_name=admin_first_name.strip(), - last_name=admin_last_name.strip(), - phone_number=admin_phone_number.strip() or None, - mobile_phone_number=admin_mobile_phone_number.strip() or None, - building=admin_building.strip() or None, - room=admin_room.strip() or None, - active_semester=semester, - ) + admin_user = user_datastore.create_user( + email=admin_email, + password=admin_hashed_password, + roles=[adminRole], + first_name=admin_first_name.strip(), + last_name=admin_last_name.strip(), + phone_number=admin_phone_number.strip() or None, + mobile_phone_number=admin_mobile_phone_number.strip() or None, + building=admin_building.strip() or None, + room=admin_room.strip() or None, + active_semester=semester, + ) - admin = Admin(user=admin_user) + admin = Admin(user=admin_user) - db.session.add(admin) + db.session.add(admin) manage.box(f"Admin password: {admin_password}") diff --git a/cli/test/generate_test_db/main.py b/cli/test/generate_test_db/main.py index a041589..8f2e781 100644 --- a/cli/test/generate_test_db/main.py +++ b/cli/test/generate_test_db/main.py @@ -45,202 +45,196 @@ def _generate_test_db(): app = create_app(create_for_server=False) - with app.app_context(): - with db.session.begin(): - db.create_all() + with app.app_context(), db.session.begin(): + db.create_all() - bs_prog = db_add(Program(label="BS")) - ms_prog = db_add(Program(label="MS")) - be_prog = db_add(Program(label="BE")) - programs = (bs_prog, ms_prog, be_prog) + bs_prog = db_add(Program(label="BS")) + ms_prog = db_add(Program(label="MS")) + be_prog = db_add(Program(label="BE")) + programs = (bs_prog, ms_prog, be_prog) - ss = db_add(Semester(label="SS", year=23)) - ws = db_add(Semester(label="WS", year=23)) - semesters = (ss, ws) + ss = db_add(Semester(label="SS", year=23)) + ws = db_add(Semester(label="WS", year=23)) + semesters = (ss, ws) - bs_1_ss_part = db_add(Part(semester=ss, program=bs_prog, number=1)) - bs_2_ss_part = db_add(Part(semester=ss, program=bs_prog, number=2)) - ms_1_ss_part = db_add(Part(semester=ss, program=ms_prog, number=1)) - ms_2_ss_part = db_add(Part(semester=ss, program=ms_prog, number=2)) - be_1_ss_part = db_add(Part(semester=ss, program=be_prog, number=1)) - be_2_ss_part = db_add(Part(semester=ss, program=be_prog, number=2)) - ss_parts = (bs_1_ss_part, bs_2_ss_part, ms_1_ss_part, ms_2_ss_part, be_1_ss_part, be_2_ss_part) + bs_1_ss_part = db_add(Part(semester=ss, program=bs_prog, number=1)) + bs_2_ss_part = db_add(Part(semester=ss, program=bs_prog, number=2)) + ms_1_ss_part = db_add(Part(semester=ss, program=ms_prog, number=1)) + ms_2_ss_part = db_add(Part(semester=ss, program=ms_prog, number=2)) + be_1_ss_part = db_add(Part(semester=ss, program=be_prog, number=1)) + be_2_ss_part = db_add(Part(semester=ss, program=be_prog, number=2)) + ss_parts = (bs_1_ss_part, bs_2_ss_part, ms_1_ss_part, ms_2_ss_part, be_1_ss_part, be_2_ss_part) - db_add(Part(semester=ws, program=bs_prog, number=1)) - bs_2_ws_part = db_add(Part(semester=ws, program=bs_prog, number=2)) - ms_1_ws_part = db_add(Part(semester=ws, program=ms_prog, number=1)) - ms_2_ws_part = db_add(Part(semester=ws, program=ms_prog, number=2)) - db_add(Part(semester=ws, program=be_prog, number=1)) - be_2_ws_part = db_add(Part(semester=ws, program=be_prog, number=2)) + db_add(Part(semester=ws, program=bs_prog, number=1)) + bs_2_ws_part = db_add(Part(semester=ws, program=bs_prog, number=2)) + ms_1_ws_part = db_add(Part(semester=ws, program=ms_prog, number=1)) + ms_2_ws_part = db_add(Part(semester=ws, program=ms_prog, number=2)) + db_add(Part(semester=ws, program=be_prog, number=1)) + be_2_ws_part = db_add(Part(semester=ws, program=be_prog, number=2)) - semester_program_part_students = { - ss: {program: [] for program in programs}, - ws: {program: [] for program in programs}, - } + semester_program_part_students = { + ss: {program: [] for program in programs}, + ws: {program: [] for program in programs}, + } - def add_part_student(student, part): - part_student = db_add(PartStudent(student=student, part=part)) - semester_program_part_students[part.semester][part.program].append(part_student) + def add_part_student(student, part): + part_student = db_add(PartStudent(student=student, part=part)) + semester_program_part_students[part.semester][part.program].append(part_student) - for ind, name in enumerate(student_names): - if randint(0, 1) == 0: # nosec: B311 - contact_email = f"{name[0]}-{name[1]}@private.de".lower() - else: - contact_email = None + for ind, name in enumerate(student_names): + contact_email = f"{name[0]}-{name[1]}@private.de".lower() if ind % 2 == 0 else None - student = db_add( - Student( - student_number=ind, - first_name=name[0], - last_name=name[1], - uni_email=f"{name[0]}-{name[1]}@uni.de".lower(), - contact_email=contact_email, - ) + student = db_add( + Student( + student_number=ind, + first_name=name[0], + last_name=name[1], + uni_email=f"{name[0]}-{name[1]}@uni.de".lower(), + contact_email=contact_email, ) + ) - part = ss_parts[ind % len(ss_parts)] - add_part_student(student, part) + part = ss_parts[ind % len(ss_parts)] + add_part_student(student, part) - if random() < 0.9: # nosec: B311 - # Transfer to the next part in the second semester - if part == bs_1_ss_part: - add_part_student(student, bs_2_ws_part) - elif part == bs_2_ss_part: - add_part_student(student, ms_1_ws_part) - elif part == ms_1_ss_part: - add_part_student(student, ms_2_ws_part) - elif part == be_1_ss_part: - add_part_student(student, be_2_ws_part) + if random() < 0.9: # nosec: B311 + # Transfer to the next part in the second semester + if part == bs_1_ss_part: + add_part_student(student, bs_2_ws_part) + elif part == bs_2_ss_part: + add_part_student(student, ms_1_ws_part) + elif part == ms_1_ss_part: + add_part_student(student, ms_2_ws_part) + elif part == be_1_ss_part: + add_part_student(student, be_2_ws_part) - program_groups = {program: [] for program in programs} - for _semester, program_part_students in semester_program_part_students.items(): - for program, part_students in program_part_students.items(): - if len(part_students) % 2 == 1: - # Add the first 3 students into a special group for an uneven number of students - group_part_students = [] - for _ in range(3): - if len(part_students) == 0: - break - - group_part_students.append(part_students.pop(0)) - - group = db_add(Group.customInit(group_part_students)) - program_groups[program].append(group) - - while len(part_students) >= 2: - # Add the rest of the students into groups of 2 - group = db_add(Group.customInit([part_students.pop(0) for i in range(2)])) - program_groups[program].append(group) - - program_semester_experiments = {program: [] for program in programs} - all_semester_experiments = [] - for ind, title in enumerate(experiment_titles): - program = programs[ind % len(programs)] - - experiment = db_add( - Experiment( - number=ind + 1, - program=program, - title=title, - building="Not assigned", - room="Not assigned", - duration_in_days=2, - ) - ) - - for semester in semesters: - semester_experiment = db_add(SemesterExperiment(experiment=experiment, semester=semester)) - program_semester_experiments[program].append(semester_experiment) - all_semester_experiments.append(semester_experiment) - - all_group_experiments = [] - for program in programs: - semester_experiments = program_semester_experiments[program] - num_semester_experiments = len(semester_experiments) - - for ind, group in enumerate(program_groups[program]): - num_tries = 0 - while True: - try: - semester_experiment = semester_experiments[ind % num_semester_experiments] - group_experiment = db_add( - GroupExperiment(semester_experiment=semester_experiment, group=group) - ) - except DatabaseException as ex: - # Catch an error when a student becomes the same experiment for the second time. - # Try the next experiment! - ind += 1 - num_tries += 1 - if num_tries == num_semester_experiments: - raise ex - else: + program_groups = {program: [] for program in programs} + for _semester, program_part_students in semester_program_part_students.items(): + for program, part_students in program_part_students.items(): + if len(part_students) % 2 == 1: + # Add the first 3 students into a special group for an uneven number of students + group_part_students = [] + for _ in range(3): + if len(part_students) == 0: break - all_group_experiments.append(group_experiment) + group_part_students.append(part_students.pop(0)) - adminRole = user_datastore.create_role(name="admin") - assistantRole = user_datastore.create_role(name="assistant") + group = db_add(Group.customInit(group_part_students)) + program_groups[program].append(group) - admin_names = ( - ("Aileen", "Grant"), - ("Ben", "Huber"), + while len(part_students) >= 2: + # Add the rest of the students into groups of 2 + group = db_add(Group.customInit([part_students.pop(0) for i in range(2)])) + program_groups[program].append(group) + + program_semester_experiments = {program: [] for program in programs} + all_semester_experiments = [] + for ind, title in enumerate(experiment_titles): + program = programs[ind % len(programs)] + + experiment = db_add( + Experiment( + number=ind + 1, + program=program, + title=title, + building="Not assigned", + room="Not assigned", + duration_in_days=2, + ) ) - for name in admin_names: - user = user_datastore.create_user( - email=f"{name[0]}-{name[1]}@uni.de".lower(), - password=hash_password("admin"), - roles=[adminRole], - first_name=name[0], - last_name=name[1], - active_semester=ws, - ) - db_add(Admin(user=user)) + for semester in semesters: + semester_experiment = db_add(SemesterExperiment(experiment=experiment, semester=semester)) + program_semester_experiments[program].append(semester_experiment) + all_semester_experiments.append(semester_experiment) - num_assistants = len(assistant_names) - num_assistant_experiments = ceil(len(all_semester_experiments) / num_assistants) + all_group_experiments = [] + for program in programs: + semester_experiments = program_semester_experiments[program] + num_semester_experiments = len(semester_experiments) - for name in assistant_names: - user = user_datastore.create_user( - email=f"{name[0]}-{name[1]}@uni.de".lower(), - password=hash_password("assistant"), - roles=[assistantRole], - first_name=name[0], - last_name=name[1], - mobile_phone_number="01" + "".join(str(randint(0, 9)) for i in range(10)), # nosec: B311 - active_semester=ws, - ) - - semester_experiments = [] - for _ in range(num_assistant_experiments): - if len(all_semester_experiments) == 0: + for ind, group in enumerate(program_groups[program]): + num_tries = 0 + while True: + try: + semester_experiment = semester_experiments[ind % num_semester_experiments] + group_experiment = db_add(GroupExperiment(semester_experiment=semester_experiment, group=group)) + except DatabaseException as ex: + # Catch an error when a student becomes the same experiment for the second time. + # Try the next experiment! + ind += 1 + num_tries += 1 + if num_tries == num_semester_experiments: + raise ex + else: break - semester_experiments.append(all_semester_experiments.pop(0)) + all_group_experiments.append(group_experiment) - db_add(Assistant(user=user, semester_experiments=semester_experiments)) + adminRole = user_datastore.create_role(name="admin") + assistantRole = user_datastore.create_role(name="assistant") - for group_experiment in all_group_experiments: - semester_experiment = group_experiment.semester_experiment - special = False - semester = semester_experiment.semester - if semester.label == "SS": - month = randint(3, 8) # nosec: B311 - if month <= 4: - special = True - else: - month = randint(9, 12) # nosec: B311 - if month <= 10: - special = True + admin_names = ( + ("Aileen", "Grant"), + ("Ben", "Huber"), + ) + for name in admin_names: + user = user_datastore.create_user( + email=f"{name[0]}-{name[1]}@uni.de".lower(), + password=hash_password("admin"), + roles=[adminRole], + first_name=name[0], + last_name=name[1], + active_semester=ws, + ) - year = 2000 + semester.year - day = randint(1, 28) # nosec: B311 - for appointment_date in (date(year, month, day), date(year, month, day + 1)): - db_add( - Appointment( - date=appointment_date, - special=special, - group_experiment=group_experiment, - assistant=semester_experiment.assistants[0], - ) + db_add(Admin(user=user)) + + num_assistants = len(assistant_names) + num_assistant_experiments = ceil(len(all_semester_experiments) / num_assistants) + + for name in assistant_names: + user = user_datastore.create_user( + email=f"{name[0]}-{name[1]}@uni.de".lower(), + password=hash_password("assistant"), + roles=[assistantRole], + first_name=name[0], + last_name=name[1], + mobile_phone_number="01" + "".join(str(randint(0, 9)) for i in range(10)), # nosec: B311 + active_semester=ws, + ) + + semester_experiments = [] + for _ in range(num_assistant_experiments): + if len(all_semester_experiments) == 0: + break + + semester_experiments.append(all_semester_experiments.pop(0)) + + db_add(Assistant(user=user, semester_experiments=semester_experiments)) + + for group_experiment in all_group_experiments: + semester_experiment = group_experiment.semester_experiment + special = False + semester = semester_experiment.semester + if semester.label == "SS": + month = randint(3, 8) # nosec: B311 + if month <= 4: + special = True + else: + month = randint(9, 12) # nosec: B311 + if month <= 10: + special = True + + year = 2000 + semester.year + day = randint(1, 28) # nosec: B311 + for appointment_date in (date(year, month, day), date(year, month, day + 1)): + db_add( + Appointment( + date=appointment_date, + special=special, + group_experiment=group_experiment, + assistant=semester_experiment.assistants[0], ) + ) diff --git a/pyproject.toml b/pyproject.toml index 2b9e371..d334ec0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.ruff] -select = ["E", "W", "F", "I", "UP", "YTT", "S", "B", "C4", "ICN", "PIE", "Q", "RET"] +select = ["E", "W", "F", "I", "UP", "YTT", "S", "B", "C4", "ICN", "PIE", "Q", "RET", "SIM"] ignore = ["E5", "S3", "S6", "RET504"] line-length = 120