Пример #1
0
    def _clone_solution_comments(
        from_solution: models.Solution,
        to_solution: models.Solution,
    ) -> None:
        user_comments = models.Comment.by_solution(
            from_solution.id, ).filter(~models.Comment.is_auto)
        for comment in user_comments:
            models.Comment.create_comment(
                commenter=models.User.get_system_user(),
                line_number=comment.line_number,
                comment_text=comment.comment,
                file=to_solution.solution_files.get(),
                is_auto=True,
            )

        to_solution.checker = from_solution.checker
        to_solution.state = from_solution.state
        to_solution.save()
        notifications.send(
            kind=notifications.NotificationKind.CHECKED,
            user=to_solution.solver,
            related_id=to_solution,
            message=_(
                'הפתרון שלך לתרגיל %(subject)s נבדק.',
                subject=to_solution.exercise.subject,
            ),
            action_url=f'{routes.SOLUTIONS}/{to_solution.id}',
        )
Пример #2
0
    def _populate_junit_results(self, raw_results: str) -> None:
        assert self._solution is not None  # noqa: S101
        suites = ()
        if raw_results:
            suites = junitparser.TestSuite.fromstring(raw_results).testsuites()

        tests_ran = False
        number_of_failures = 0
        for test_suite in suites:
            failures, ran = self._handle_test_suite(test_suite)
            number_of_failures += failures
            if ran and not tests_ran:
                tests_ran = ran

        if not tests_ran:
            self._handle_failed_to_execute_tests(raw_results)
            return

        if not number_of_failures:
            return

        fail_message = _(
            'הבודק האוטומטי נכשל ב־ %(number)d דוגמאות בתרגיל "%(subject)s".',
            number=number_of_failures,
            subject=self._solution.exercise.subject,
        )
        notifications.send(
            kind=notifications.NotificationKind.UNITTEST_ERROR,
            user=self._solution.solver,
            related_id=self._solution.id,
            message=fail_message,
            action_url=f'{routes.SOLUTIONS}/{self._solution_id}',
        )
Пример #3
0
    def _populate_junit_results(self, junit_results: str):
        assert self._solution is not None  # noqa: S101
        results = None
        if junit_results:
            results = junitparser.TestSuite.fromstring(junit_results)
        if not results:
            self._logger.info('junit invalid results (%s) on solution %s',
                              junit_results, self._solution_id)
            fail_user_message = 'הבודק האוטומטי לא הצליח להריץ את הקוד שלך.'
            models.SolutionExerciseTestExecution.create_execution_result(
                solution=self._solution,
                test_name=models.ExerciseTestName.FATAL_TEST_NAME,
                user_message=fail_user_message,
                staff_message='אחי, בדקת את הקוד שלך?',
            )
            notifications.send(
                kind=notifications.NotificationKind.UNITTEST_ERROR,
                user=self._solution.solver,
                related_id=self._solution.id,
                message=fail_user_message,
                action_url=f'{routes.SOLUTIONS}/{self._solution_id}',
            )
            return

        number_of_failures = 0
        for case in results:
            result = case.result
            if result is None:
                self._logger.info(
                    'Case %s passed for solution %s.',
                    case.name, self._solution,
                )
                continue
            # invalid case
            message = '\n'.join([elem[1] for elem in result._elem.items()])
            self._logger.info('Create comment on test %s solution %s.',
                              case.name, self._solution_id)
            number_of_failures += 1
            models.SolutionExerciseTestExecution.create_execution_result(
                solution=self._solution,
                test_name=case.name,
                user_message=message,
                staff_message=result._elem.text,
            )

        if not number_of_failures:
            return

        fail_message = (
            f'הבודק האוטומטי נכשל ב־{number_of_failures} '
            f'דוגמאות בתרגיל "{self._solution.exercise.subject}".'
        )
        notifications.send(
            kind=notifications.NotificationKind.UNITTEST_ERROR,
            user=self._solution.solver,
            related_id=self._solution.id,
            message=fail_message,
            action_url=f'{routes.SOLUTIONS}/{self._solution_id}',
        )
Пример #4
0
def notify_comment_after_check(user: User, solution: Solution) -> bool:
    is_checked = solution.is_checked
    if is_checked:
        msg, addressee = get_message_and_addressee(user, solution)
        if is_last_to_reply(user, solution):
            notifications.send(
                kind=notifications.NotificationKind.USER_RESPONSE,
                user=addressee,
                related_id=solution.id,
                message=msg,
                action_url=f'{routes.SOLUTIONS}/{solution.id}',
            )
            return True
    return False
Пример #5
0
def mark_as_checked(solution_id: int, checker_id: int) -> bool:
    checked_solution: Solution = Solution.get_by_id(solution_id)
    is_updated = checked_solution.mark_as_checked(by=checker_id)
    msg = f'הפתרון שלך לתרגיל "{checked_solution.exercise.subject}" נבדק.'
    if is_updated:
        notifications.send(
            kind=notifications.NotificationKind.CHECKED,
            user=checked_solution.solver,
            related_id=solution_id,
            message=msg,
            action_url=f'{routes.SOLUTIONS}/{solution_id}',
        )
    if config.FEATURE_FLAG_CHECK_IDENTICAL_CODE_ON:
        (identical_tests_tasks.check_if_other_solutions_can_be_solved.
         apply_async(args=(solution_id, )))
    return is_updated
Пример #6
0
    def test_auto_deletion(self, student_user: User):
        extra = 3
        start = Notification.MAX_PER_USER
        for _ in range(Notification.MAX_PER_USER + extra - 1):
            notifications.send(
                user=student_user,
                kind=notifications.NotificationKind.CHECKED,
                message='',
                related_id=1,
                action_url='/view/1',
            )

        assert Notification.select().count() == start
        expected = start + extra - 1
        actual = Notification.select().order_by(
            Notification.created.desc()).get().id
        assert expected == actual
Пример #7
0
    def test_send(self, student_user: User):
        another_user = conftest.create_student_user(index=1)
        params = self.generate_params()
        n1 = notifications.send(student_user, **params)
        n2 = notifications.send(another_user, self.kind_checked, 'yoyo2')
        n3 = notifications.send(student_user, self.kind_flake8, 'yoyo3')

        assert n1.user == student_user
        assert n1.kind == params['kind'].value
        assert n1.message == params['message']
        assert n1.related_id == params['related_id']
        assert n1.action_url == params['action_url']
        assert n2.kind != n3.kind
        assert n2.message == 'yoyo2'
        assert n2.user == another_user
        assert len(list(notifications.get(student_user))) == 2
        assert len(list(notifications.get(another_user))) == 1
Пример #8
0
 def _handle_failed_to_execute_tests(self, raw_results: str) -> None:
     self._logger.info('junit invalid results (%s) on solution %s',
                       raw_results, self._solution_id)
     fail_user_message = _('הבודק האוטומטי לא הצליח להריץ את הקוד שלך.', )
     models.SolutionExerciseTestExecution.create_execution_result(
         solution=self._solution,
         test_name=models.ExerciseTestName.FATAL_TEST_NAME,
         user_message=fail_user_message,
         staff_message=_('אחי, בדקת את הקוד שלך?'),
     )
     notifications.send(
         kind=notifications.NotificationKind.UNITTEST_ERROR,
         user=self._solution.solver,
         related_id=self._solution.id,
         message=fail_user_message,
         action_url=f'{routes.SOLUTIONS}/{self._solution_id}',
     )
Пример #9
0
 def _handle_failed_to_execute_tests(self, raw_results: bytes) -> None:
     self._logger.info(b'junit invalid results (%s) on solution %s',
                       raw_results, self._solution_id)
     fail_user_message = CANT_EXECUTE_CODE_MESSAGE
     models.SolutionExerciseTestExecution.create_execution_result(
         solution=self._solution,
         test_name=models.ExerciseTestName.FATAL_TEST_NAME,
         user_message=fail_user_message,
         staff_message=_('Bro, did you check your code?'),
     )
     notifications.send(
         kind=notifications.NotificationKind.UNITTEST_ERROR,
         user=self._solution.solver,
         related_id=self._solution.id,
         message=fail_user_message,
         action_url=f'{routes.SOLUTIONS}/{self._solution_id}',
     )
Пример #10
0
    def _populate_junit_results(self, raw_results: bytes) -> None:
        assert self._solution is not None  # noqa: S101
        if not raw_results:
            return None

        suites = self._get_parsed_suites(raw_results)
        if not suites:
            return None

        tests_ran = False
        number_of_failures = 0
        for test_suite in suites:
            failures, ran = self._handle_test_suite(test_suite)
            number_of_failures += failures
            if ran and not tests_ran:
                tests_ran = ran

        if not tests_ran:
            self._handle_failed_to_execute_tests(raw_results)
            return None

        if not number_of_failures:
            return None

        fail_message = _(
            'The automatic checker failed in %(number)d examples in your '
            '"%(subject)s" solution.',
            number=number_of_failures,
            subject=self._solution.exercise.subject,
        )
        notifications.send(
            kind=notifications.NotificationKind.UNITTEST_ERROR,
            user=self._solution.solver,
            related_id=self._solution.id,
            message=fail_message,
            action_url=f'{routes.SOLUTIONS}/{self._solution_id}',
        )
Пример #11
0
    def _fire_notification_if_needed(self):
        if not self._errors:
            return

        errors_len = len(self._errors)
        exercise_name = self.solution.exercise.subject
        msg = (
            f'הבודק האוטומטי נתן {errors_len} '
            f'הערות על תרגילך "{exercise_name}".'
        )
        return notifications.send(
            kind=notifications.NotificationKind.FLAKE8_ERROR,
            user=self.solution.solver,
            related_id=self.solution,
            message=msg,
            action_url=f'{routes.SOLUTIONS}/{self.solution.id}',
        )
Пример #12
0
    def _fire_notification_if_needed(self):
        if not self._errors:
            return

        errors_len = len(self._errors)
        exercise_name = self.solution.exercise.subject
        msg = _(
            'The automatic checker gave you %(errors_num)d for your '
            '%(name)s solution.',
            errors_num=errors_len,
            name=exercise_name,
        )
        return notifications.send(
            kind=notifications.NotificationKind.FLAKE8_ERROR,
            user=self.solution.solver,
            related_id=self.solution,
            message=msg,
            action_url=f'{routes.SOLUTIONS}/{self.solution.id}',
        )