def _alter_column_type_if_needed( table: Type[Model], field_instance: Field, new_type: Field, ) -> bool: field_type_name = new_type.__class__.__name__ current_type = field_instance.__class__.__name__ column_name = field_instance.name.lower() table_name = table.__name__.lower() if field_type_name.lower() == current_type.lower(): log.info(f'Column {column_name} is already {field_type_name}') return False log.info( f'Changing {column_name} from {current_type} ' f'to {field_type_name} in {table}', ) migrator = db_config.get_migrator_instance() with db_config.database.transaction(): migrate( migrator.alter_column_type(table_name, column_name, new_type), ) db_config.database.commit() return True
def _execute_sql_if_possible(sql: str) -> bool: with db_config.database.transaction(): log.info(f'Running {sql}') try: db_config.database.execute_sql(sql) db_config.database.commit() except (OperationalError, ProgrammingError) as e: log.info(f"Can't run SQL '{sql}' because: {e}") return True
def _get_or_create_user_in_model(user: UserToCreate) -> None: log.info('Create user with email: %s', user.email) models.User.get_or_create(**{ models.User.mail_address.name: user.email, models.User.username.name: user.email, }, defaults={ models.User.fullname.name: f'{user.name}', models.User.role.name: models.Role.get_student_role(), models.User.password.name: user.password, })
def _add_course_and_numbers_to_exercises_table( table: Model, course: models.Course, ) -> None: log.info( 'Adding Course, Numbers for exercises, might take some extra time...', ) with db_config.database.transaction(): for exercise in table: exercise.number = exercise.id exercise.course = course exercise.save()
def _add_user_course_constaint() -> bool: migrator = db_config.get_migrator_instance() with db_config.database.transaction(): try: migrate( migrator.add_index( 'usercourse', ('user_id', 'course_id'), True, ), ) except (OperationalError, ProgrammingError) as e: log.info(f'Index usercourse user and course already exists: {e}') db_config.database.commit()
def _add_exercise_course_id_and_number_columns_constraint() -> bool: Exercise = models.Exercise migrator = db_config.get_migrator_instance() with db_config.database.transaction(): _add_not_null_column(Exercise, Exercise.course) _add_not_null_column(Exercise, Exercise.number) try: migrate( migrator.add_index('exercise', ('course_id', 'number'), True), ) except (OperationalError, ProgrammingError) as e: log.info(f'Index exercise course and number already exists: {e}') db_config.database.commit()
def _drop_constraint_if_needed(table: Type[Model], column_name: str) -> bool: table_name = table.__name__.lower() cols = {col.name for col in db_config.database.get_columns(table_name)} if column_name not in cols: log.info(f'Column {column_name} not exists in {table}') return False log.info(f'Drop foreign key on {table}.{column_name}') migrator = db_config.get_migrator_instance() with db_config.database.transaction(): migrate(migrator.drop_constraint(table_name, column_name)) db_config.database.commit() return True
def _add_not_null_column( table: Model, column: Field, run_before_adding_not_null: Callable[[Model, Field], None] = None, ) -> bool: already_exists, table_name, column_name = get_details(table, column) log.info(f'Adding {table_name}.{column_name}, if needed.') if already_exists: log.info(f'Column {column_name} already exists in {table_name}.') return False migrator = db_config.get_migrator_instance() with db_config.database.transaction(): column.null = True migrate(migrator.add_column(table_name, column_name, field=column)) if callable(run_before_adding_not_null): run_before_adding_not_null(table, column) migrate(migrator.drop_not_null(table_name, column_name)) db_config.database.commit() return True
def __enter__(self): args = ( 'docker', 'run', '-d', '--memory', self.memory_limit, '--cpus', self.cpu_limit, '--network', 'none', '--rm', '--name', self._container_name, self.base_image, 'sleep', str(self.timeout_seconds), ) log.info('Start executing safe container context with %s', args) subprocess.check_call(args) # NOQA: S603 return self
def _migrate_column_in_table_if_needed( table: Type[Model], field_instance: Field, *, field_name: Optional[str] = None, **kwargs: Any, ) -> bool: column_name = field_name or field_instance.name table_name = table.__name__.lower() cols = {col.name for col in db_config.database.get_columns(table_name)} if column_name in cols: log.info(f'Column {column_name} already exists in {table}') return False log.info(f'Create {column_name} field in {table}') migrator = db_config.get_migrator_instance() with db_config.database.transaction(): try: migrate( migrator.add_column( table=table_name, column_name=column_name, field=field_instance, **kwargs, )) except (OperationalError, ProgrammingError) as e: if 'does not exist' in str(e): log.info(f'Column {field_name} already exists: {e}') else: raise db_config.database.commit() return True
def _rename_column_in_table_if_needed( table: Type[Model], old_column_name: str, new_column_name: str, ) -> bool: column_name = old_column_name.lower() table_name = table.__name__.lower() cols = {col.name for col in db_config.database.get_columns(table_name)} if new_column_name in cols: log.info(f'Column {new_column_name} already exists in {table}') return False if old_column_name not in cols: log.info(f'Column {old_column_name} not exists in {table}') return False log.info(f'Changing {column_name} -> {new_column_name} in {table}') migrator = db_config.get_migrator_instance() with db_config.database.transaction(): migrate( migrator.rename_column( table_name, old_column_name, new_column_name, ), ) db_config.database.commit() return True
def register_test_class(file_path: str, test_class: typing.ClassVar): subject = test_class.__doc__ exercise = models.Exercise.get_or_none(models.Exercise.subject == subject) if not exercise: log.info(f'Failed to find exercise subject {subject}') raise SystemError with open(file_path, 'r') as file_reader: code = file_reader.read() exercise_test = models.ExerciseTest.get_or_create_exercise_test( exercise=exercise, code=code, ) for test_func_name in inspect.getmembers(test_class): test_func_name = test_func_name[0] if test_func_name.startswith('test_'): test_func = getattr(test_class, test_func_name) models.ExerciseTestName.create_exercise_test_name( exercise_test=exercise_test, test_name=test_func_name, pretty_test_name=test_func.__doc__, )
def ratelimit_handler(e): log.info(f'IP Address: {get_remote_address()}: {e}') return make_response( jsonify(error='ratelimit exceeded %s' % e.description), 429, )
def _add_uuid_to_users_table(table: Model, _column: Field) -> None: log.info('Adding UUIDs for all users, might take some extra time...') with db_config.database.transaction(): for user in table: user.uuid = uuid4() user.save()
def _create_usercourses_objects(table: Model, course: models.Course) -> None: log.info('Adding UserCourse for all users, might take some extra time...') UserCourse = models.UserCourse with db_config.database.transaction(): for user in table: UserCourse.create(user=user, course=course)
def _add_api_keys_to_users_table(table: Model, _column: Field) -> None: log.info('Adding API Keys for all users, might take some extra time...') with db_config.database.transaction(): for user in table: user.api_key = table.random_password(stronger=True) user.save()