def test_no_modification_on_event_has_no_effect_on_disk(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)
        before_modification_dt = os.path.getmtime(quiz.path)

        quiz.write()
        self.assertTrue(before_modification_dt == os.path.getmtime(quiz.path))
Ejemplo n.º 2
0
    def test_sort_activity_type(self):
        course = MoodleCourse(self.tmp_path)
        activities = course._load_activites()[MoodleQuiz]
        activities = course._sort_activity_type(activities)

        for i, x in enumerate([146935, 146936, 146939]):
            self.assertEqual(x, activities[i]['moduleid'])
    def test_sort_activity_type(self):
        course = MoodleCourse(self.tmp_path)
        activities = course._load_activites()[MoodleQuiz]
        activities = course._sort_activity_type(activities)

        for i, x in enumerate([146935, 146936, 146939]):
            self.assertEqual(x, activities[i]['moduleid'])
Ejemplo n.º 4
0
    def test_no_modification_on_event_has_no_effect_on_disk(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)
        before_modification_dt = os.path.getmtime(quiz.path)

        quiz.write()
        self.assertTrue(before_modification_dt == os.path.getmtime(quiz.path))
    def test_get_data_from_event(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

        self.assertEqual('test de remise', quiz['name'])
        self.assertEqual('1451709900', quiz['timeopen'])
        self.assertEqual('1454301900', quiz['timeclose'])
Ejemplo n.º 6
0
    def test_get_data_from_event(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

        self.assertEqual('test de remise', quiz['name'])
        self.assertEqual('1451709900', quiz['timeopen'])
        self.assertEqual('1454301900', quiz['timeclose'])
def download_planning(uuid):
    try:
        planning = _get_planning(uuid, g.user_id)
    except CAPException as e:
        return e.res

    moodle_archive_path = planning.mbz_fullpath
    planning_txt = planning.planning_txt

    if not planning_txt:
        return _bad_request()

    # Make tmp directory for MBZ extraction and ics download
    with tempfile.TemporaryDirectory() as tmp_path:
        # Download calendar to tmp folder
        calendar = CalendarReader(planning.ics_fullpath)
        calendar_meetings = calendar.get_all_meetings()

        # Extract Moodle course to tmp folder
        with tarfile.open(moodle_archive_path) as tar_file:
            tar_file.extractall(tmp_path)
            course = MoodleCourse(tmp_path)

        interpreter = Interpreter(calendar_meetings, course)
        for line in planning_txt.split('\n'):
            event = interpreter.get_new_event_from_string(line)
            course.replace_event(event)

        folder = os.path.join(app.config['UPLOAD_FOLDER'], uuid)
        latest_mbz_path = os.path.join(folder, 'latest.mbz')

        course.write(latest_mbz_path)
        return send_from_directory(
            folder, 'latest.mbz', as_attachment=True)
def download_planning(uuid):
    planning = _get_planning(uuid)
    if not planning:
        return jsonify({"message": 'Planning with uuid "%s" not found' % uuid}), 404

    moodle_archive_path = planning.mbz_fullpath
    planning_txt = planning.planning_txt

    if not planning_txt:
        return _bad_request()

    # Make tmp directory for MBZ extraction and ics download
    with tempfile.TemporaryDirectory() as tmp_path:
        # Download calendar to tmp folder
        calendar_path = _dl_and_save_ics_file(planning.ics_url, tmp_path)
        calendar = CalendarReader(calendar_path)
        calendar_meetings = calendar.get_all_meetings()

        # Extract Moodle course to tmp folder
        with tarfile.open(moodle_archive_path) as tar_file:
            tar_file.extractall(tmp_path)
            course = MoodleCourse(tmp_path)

        interpreter = Interpreter(calendar_meetings, course)
        for line in planning_txt.split("\n"):
            event = interpreter.get_new_event_from_string(line)
            course.replace_event(event)
        folder = os.path.join(app.config["UPLOAD_FOLDER"], uuid)
        latest_mbz_path = os.path.join(folder, "latest.mbz")

        course.write(latest_mbz_path)
        return send_from_directory(folder, "latest.mbz", as_attachment=True)
    def test_archive_is_repacked(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)
        quiz.set_start_datetime(arrow.get(
            2001, 1, 1, 1, 1, 1, tzinfo=tz.gettz('America/Montreal')).datetime)

        course.write(self.tmp_output_archive)
        self.assertTrue(os.path.isfile(self.tmp_output_archive))
Ejemplo n.º 10
0
    def test_archive_is_repacked(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)
        quiz.set_start_datetime(
            arrow.get(2001, 1, 1, 1, 1, 1,
                      tzinfo=tz.gettz('America/Montreal')).datetime)

        course.write(self.tmp_output_archive)
        self.assertTrue(os.path.isfile(self.tmp_output_archive))
Ejemplo n.º 11
0
    def test_get_event_end_date(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

        quiz['timeclose'] = 1389027600
        dt = arrow.get(2014, 1, 6, 12,
                       tzinfo=tz.gettz('America/Montreal')).datetime

        self.assertEqual(dt, quiz.get_end_datetime())
Ejemplo n.º 12
0
    def test_set_event_start_date(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

        dt = arrow.get(2014, 1, 6, 12,
                       tzinfo=tz.gettz('America/Montreal')).datetime
        quiz.set_start_datetime(dt)

        self.assertEqual('1389027600', quiz['timeopen'])
    def test_get_event_end_date(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

        quiz['timeclose'] = 1389027600
        dt = arrow.get(
            2014, 1, 6, 12, tzinfo=tz.gettz('America/Montreal')).datetime

        self.assertEqual(dt, quiz.get_end_datetime())
    def test_set_event_start_date(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

        dt = arrow.get(
            2014, 1, 6, 12, tzinfo=tz.gettz('America/Montreal')).datetime
        quiz.set_start_datetime(dt)

        self.assertEqual('1389027600', quiz['timeopen'])
Ejemplo n.º 15
0
    def test_set_invalid_key_raises_exception(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

        with self.assertRaises(Exception):
            quiz['invalid_key'] = 'some data'

        with self.assertRaises(Exception):
            quiz['id'] = 'some data'

        with self.assertRaises(Exception):
            quiz['moduleid'] = 'some data'
    def test_set_invalid_key_raises_exception(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

        with self.assertRaises(Exception):
            quiz['invalid_key'] = 'some data'

        with self.assertRaises(Exception):
            quiz['id'] = 'some data'

        with self.assertRaises(Exception):
            quiz['moduleid'] = 'some data'
    def test_get_activity_by_relative_num(self):
        course = MoodleCourse(self.tmp_path)

        actual = course.get_activity_by_type_and_num(MoodleQuiz, 1)['id']
        self.assertEqual('4271', actual)

        actual = course.get_activity_by_type_and_num(MoodleQuiz, 2)['id']
        self.assertEqual('4272', actual)

        actual = course.get_activity_by_type_and_num(MoodleQuiz, 3)['id']
        self.assertEqual('4273', actual)

        actual = course.get_activity_by_type_and_num(MoodleHomework, 1)['id']
        self.assertEqual('5588', actual)
Ejemplo n.º 18
0
    def test_new_mbz_archive(self):
        course_activity_planner._generate_planning_uuid = \
            MagicMock(return_value='uuid')
        # Ignore mbz in request and link to local mbz file
        course_activity_planner._save_mbz_file = \
            MagicMock(return_value=self.local_mbz_path)

        res = self.client.post(
            '/api/planning',
            data=dict(
                mbz_file=(io.BytesIO(b'this is a test'), 'test.mbz'),
                ics_url=self.cal_url),
            headers=[('Authorization', "Bearer %s" % self.token)])

        res = self.client.put(
            '/api/planning/uuid',
            data=json.dumps({'planning': 'MQ1 S1F S2\nE1 S1F S2'}),
            headers=[('Content-Type', 'application/json'),
                     ('Authorization', "Bearer %s" % self.token)])

        res = self.client.get(
            '/api/planning/uuid/mbz',
            headers=[('Authorization', "Bearer %s" % self.token)])
        self.assertEqual(200, res._status_code)

        new_mbz_path = os.path.join(self.app.config['UPLOAD_FOLDER'],
                                    'downloaded.mbz')

        encoded = json.loads(res.data.decode('utf8'))['mbz_64']
        with open(new_mbz_path, 'wb') as f:
            f.write(base64.b64decode(encoded))

        print(os.path.exists(new_mbz_path))
        tmp_archive = os.path.join(self.app.config['UPLOAD_FOLDER'],
                                   'extracted')

        with tarfile.open(new_mbz_path) as tar_file:
            tar_file.extractall(tmp_archive)
            course = MoodleCourse(tmp_archive)
            quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

            expected_s = 1389013200
            expected_e = 1389614400

            actual_s = quiz.get_start_timestamp()
            actual_e = quiz.get_end_timestamp()

            self.assertEqual(expected_s, actual_s)
            self.assertEqual(expected_e, actual_e)
def get_interpreter_and_planning_from(uuid):
    planning = _get_planning(uuid, g.user_id)
    moodle_archive_path = planning.mbz_fullpath

    try:
        calendar = CalendarReader(planning.ics_fullpath)
        calendar_meetings = calendar.get_all_meetings()
    except CAPException as e:
        raise e
    except Exception as e:
        raise CAPException({'type': 'danger', 'msg': str(e)}, 400)

    if not moodle_archive_path:
        return Interpreter(calendar_meetings, None), planning

    # Make tmp directory for MBZ extraction
    with tempfile.TemporaryDirectory() as tmp_path:
        # Extract Moodle course to tmp folder
        try:
            with tarfile.open(moodle_archive_path) as tar_file:
                tar_file.extractall(tmp_path)
                course = MoodleCourse(tmp_path)
        except Exception:
            _bad_mbz()
    return Interpreter(calendar_meetings, course), planning
Ejemplo n.º 20
0
    def test_new_mbz_archive(self):
        course_activity_planner._generate_planning_uuid = \
            MagicMock(return_value='uuid')
        # Ignore mbz in request and link to local mbz file
        course_activity_planner._save_mbz_file = \
            MagicMock(return_value=self.local_mbz_path)

        res = self.client.post(
            '/api/planning',
            data=dict(
                mbz_file=(io.BytesIO(b'this is a test'), 'test.mbz'),
                ics_url=self.cal_url),
            headers=[('Authorization', "Bearer %s" % self.token)])

        res = self.client.put(
            '/api/planning/uuid',
            data=json.dumps({'planning': 'Q1 S1F S2'}),
            headers=[('Content-Type', 'application/json'),
                     ('Authorization', "Bearer %s" % self.token)])

        res = self.client.get(
            '/api/planning/uuid/mbz',
            headers=[('Authorization', "Bearer %s" % self.token)])
        self.assertEqual(200, res._status_code)

        new_mbz_path = os.path.join(self.app.config['UPLOAD_FOLDER'],
                                    'downloaded.mbz')
        with open(new_mbz_path, 'wb') as f:
            f.write(res.data)

        tmp_archive = os.path.join(self.app.config['UPLOAD_FOLDER'],
                                   'extracted')

        with tarfile.open(new_mbz_path) as tar_file:
            tar_file.extractall(tmp_archive)
            course = MoodleCourse(tmp_archive)
            quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)

            expected_s = 1389013200
            expected_e = 1389614400

            actual_s = quiz.get_start_timestamp()
            actual_e = quiz.get_end_timestamp()

            self.assertEqual(expected_s, actual_s)
            self.assertEqual(expected_e, actual_e)
Ejemplo n.º 21
0
    def test_modification_of_event_has_effect_on_disk(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)
        quiz.set_start_datetime(arrow.get(
            2001, 1, 1, 1, 1, 1, tzinfo=tz.gettz('America/Montreal')).datetime)
        before_modification_dt = os.path.getmtime(quiz.path)

        quiz.write()
        self.assertFalse(before_modification_dt == os.path.getmtime(quiz.path))

        # Check data is updated on disk
        course_after = MoodleCourse(self.tmp_path)
        quiz_after = course_after.get_activity_by_type_and_num(MoodleQuiz, 1)
        self.assertEqual(arrow.get(
            2001, 1, 1, 1, 1, 1, tzinfo=tz.gettz('America/Montreal')).datetime,
            quiz_after.get_start_datetime()
            )
Ejemplo n.º 22
0
    def test_write_activities_to_disk_saves_io(self):
        course = MoodleCourse(self.tmp_path)

        # quiz 1 is not modified
        q1 = course.get_activity_by_type_and_num(MoodleQuiz, 1)
        q1_before_modification_dt = os.path.getmtime(q1.path)

        # quiz 2 is modified
        q2 = course.get_activity_by_type_and_num(MoodleQuiz, 2)
        q2.set_start_datetime(
            arrow.get(2001, 1, 1, 1, 1, 1,
                      tzinfo=tz.gettz('America/Montreal')).datetime)
        q2_before_modification_dt = os.path.getmtime(q2.path)

        # Homework 1 is modified
        h1 = course.get_activity_by_type_and_num(MoodleHomework, 1)
        h1.set_start_datetime(
            arrow.get(2001, 1, 1, 1, 1, 1,
                      tzinfo=tz.gettz('America/Montreal')).datetime)
        h1_before_modification_dt = os.path.getmtime(h1.path)

        course._write_activities_to_disk()
        # Only quiz 2 was written on disk
        self.assertTrue(q1_before_modification_dt == os.path.getmtime(q1.path))
        self.assertFalse(
            q2_before_modification_dt == os.path.getmtime(q2.path))
        self.assertFalse(
            h1_before_modification_dt == os.path.getmtime(h1.path))
Ejemplo n.º 23
0
def download_planning(uuid):
    try:
        planning = _get_planning(uuid, g.user_id)
    except CAPException as e:
        return e.res

    moodle_archive_path = planning.mbz_fullpath
    planning_txt = planning.planning_txt

    if not planning_txt:
        return _bad_request()

    # Make tmp directory for MBZ extraction and ics download
    with tempfile.TemporaryDirectory() as tmp_path:
        # Download calendar to tmp folder
        calendar = CalendarReader(planning.ics_fullpath)
        calendar_meetings = calendar.get_all_meetings()

        # Extract Moodle course to tmp folder
        with tarfile.open(moodle_archive_path) as tar_file:
            tar_file.extractall(tmp_path)
            course = MoodleCourse(tmp_path)

        interpreter = Interpreter(calendar_meetings, course)
        for line in planning_txt.split('\n'):
            event = interpreter.get_new_event_from_string(line)
            course.replace_event(event)

        folder = os.path.join(app.config['UPLOAD_FOLDER'], uuid)
        latest_mbz_path = os.path.join(folder, 'latest.mbz')

        course.write(latest_mbz_path)
        return send_from_directory(folder, 'latest.mbz', as_attachment=True)
    def setUp(self):
        # Setup calendar
        calendar = CalendarReader(self.calendar_path)

        self.calendar_meetings = calendar.get_all_meetings()

        # Setup Moodle course
        self.tmp_path = tempfile.mkdtemp()
        with tarfile.open(self.moodle_archive_path) as tar_file:
            tar_file.extractall(self.tmp_path)

        self.course = MoodleCourse(self.tmp_path)
        self.interpreter = Interpreter(self.calendar_meetings, self.course)
Ejemplo n.º 25
0
def preview_planning(uuid):
    try:
        planning = _get_planning(uuid, g.user_id)
    except CAPException as e:
        return e.res
    moodle_archive_path = planning.mbz_fullpath
    planning_txt = planning.planning_txt

    # Make tmp directory for MBZ extraction
    with tempfile.TemporaryDirectory() as tmp_path:
        try:
            calendar = CalendarReader(planning.ics_fullpath)
            calendar_meetings = calendar.get_all_meetings()
        except Exception as e:
            _bad_cal()

        # Extract Moodle course to tmp folder
        course = None
        if moodle_archive_path:
            try:
                with tarfile.open(moodle_archive_path) as tar_file:
                    tar_file.extractall(tmp_path)
                    course = MoodleCourse(tmp_path)
            except Exception as e:
                return jsonify(alerts=[{
                    'type': 'danger',
                    'msg': 'MBZ file could not be read.'
                }]), 400

    alerts = []
    preview = None
    inventory = None
    try:
        interpreter = Interpreter(calendar_meetings, course)
        inventory = _build_inventory(interpreter, planning_txt)
        preview = _build_preview(interpreter, planning_txt)
        alerts = _build_alerts_for_preview(interpreter)
    except InvalidSyntaxException as e:
        alerts.append({'type': 'danger', 'msg': e.message})
    return jsonify({
        'preview': preview,
        'inventory': inventory,
        'alerts': alerts
    }), 200
Ejemplo n.º 26
0
    def test_load_activities(self):
        course = MoodleCourse(self.tmp_path)

        actual = course._load_activites()[MoodleQuiz]
        self.assertEqual(3, len(actual))

        actual = course._load_activites()[MoodleHomework]
        self.assertEqual(1, len(actual))

        actual = course._load_activites()[MoodleLesson]
        self.assertEqual(1, len(actual))

        actual = course._load_activites()[MoodleFeedback]
        self.assertEqual(1, len(actual))

        actual = course._load_activites()[MoodleChoice]
        self.assertEqual(1, len(actual))
Ejemplo n.º 27
0
    def test_get_activity_by_relative_num(self):
        course = MoodleCourse(self.tmp_path)

        actual = course.get_activity_by_type_and_num(MoodleQuiz, 1)['id']
        self.assertEqual('4271', actual)

        actual = course.get_activity_by_type_and_num(MoodleQuiz, 2)['id']
        self.assertEqual('4272', actual)

        actual = course.get_activity_by_type_and_num(MoodleQuiz, 3)['id']
        self.assertEqual('4273', actual)

        actual = course.get_activity_by_type_and_num(MoodleHomework, 1)['id']
        self.assertEqual('5588', actual)
    def test_load_activities(self):
        course = MoodleCourse(self.tmp_path)

        actual = course._load_activites()[MoodleQuiz]
        self.assertEqual(3, len(actual))

        actual = course._load_activites()[MoodleHomework]
        self.assertEqual(1, len(actual))

        actual = course._load_activites()[MoodleLesson]
        self.assertEqual(1, len(actual))

        actual = course._load_activites()[MoodleFeedback]
        self.assertEqual(1, len(actual))

        actual = course._load_activites()[MoodleChoice]
        self.assertEqual(1, len(actual))
Ejemplo n.º 29
0
    def test_modification_of_event_has_effect_on_disk(self):
        course = MoodleCourse(self.tmp_path)
        quiz = course.get_activity_by_type_and_num(MoodleQuiz, 1)
        quiz.set_start_datetime(
            arrow.get(2001, 1, 1, 1, 1, 1,
                      tzinfo=tz.gettz('America/Montreal')).datetime)
        before_modification_dt = os.path.getmtime(quiz.path)

        quiz.write()
        self.assertFalse(before_modification_dt == os.path.getmtime(quiz.path))
        self.assertFalse(
            before_modification_dt == os.path.getmtime(quiz.global_path +
                                                       '/calendar.xml'))

        # Check data is updated on disk
        course_after = MoodleCourse(self.tmp_path)
        quiz_after = course_after.get_activity_by_type_and_num(MoodleQuiz, 1)
        self.assertEqual(
            arrow.get(2001, 1, 1, 1, 1, 1,
                      tzinfo=tz.gettz('America/Montreal')).datetime,
            quiz_after.get_start_datetime())
    def test_write_activities_to_disk_saves_io(self):
        course = MoodleCourse(self.tmp_path)

        # quiz 1 is not modified
        q1 = course.get_activity_by_type_and_num(MoodleQuiz, 1)
        q1_before_modification_dt = os.path.getmtime(q1.path)

        # quiz 2 is modified
        q2 = course.get_activity_by_type_and_num(MoodleQuiz, 2)
        q2.set_start_datetime(arrow.get(
            2001, 1, 1, 1, 1, 1, tzinfo=tz.gettz('America/Montreal')).datetime)
        q2_before_modification_dt = os.path.getmtime(q2.path)

        # Homework 1 is modified
        h1 = course.get_activity_by_type_and_num(MoodleHomework, 1)
        h1.set_start_datetime(arrow.get(
            2001, 1, 1, 1, 1, 1, tzinfo=tz.gettz('America/Montreal')).datetime)
        h1_before_modification_dt = os.path.getmtime(h1.path)

        course._write_activities_to_disk()
        # Only quiz 2 was written on disk
        self.assertTrue(q1_before_modification_dt == os.path.getmtime(q1.path))
        self.assertFalse(q2_before_modification_dt == os.path.getmtime(q2.path))
        self.assertFalse(h1_before_modification_dt == os.path.getmtime(h1.path))
Ejemplo n.º 31
0
    def test_load_activity_sequence(self):
        course = MoodleCourse(self.tmp_path)
        actual = course._load_activity_sequence()

        self.assertEqual([175721, 175723, 175724, 175720, 175722, 176000],
                         actual)
Ejemplo n.º 32
0
 def test_load_activities(self):
     course = MoodleCourse(self.tmp_path)
     actual = course._load_activites()[MoodleQuiz]
     self.assertEqual(4, len(actual))
     actual = course._load_activites()[MoodleHomework]
     self.assertEqual(1, len(actual))
    def test_load_activity_sequence(self):
        course = MoodleCourse(self.tmp_path)
        actual = course._load_activity_sequence()

        self.assertEqual([146934, 146935, 146936, 146937, 146939], actual)
 def test_invisible_activities_are_not_loaded(self):
     course = MoodleCourse(self.tmp_path)
     actual = course._load_activites()[MoodleQuiz]
     self.assertEqual(2, len(actual))
Ejemplo n.º 35
0
    def test_load_activity_sequence(self):
        course = MoodleCourse(self.tmp_path)
        actual = course._load_activity_sequence()

        self.assertEqual([146934, 146935, 146936, 146937, 146939], actual)
Ejemplo n.º 36
0
 def test_invisible_activities_are_not_loaded(self):
     course = MoodleCourse(self.tmp_path)
     actual = course._load_activites()[MoodleQuiz]
     self.assertEqual(2, len(actual))
Ejemplo n.º 37
0
    def test_activities_are_sorted(self):
        course = MoodleCourse(self.tmp_path)

        for i, x in enumerate([146935, 146936, 146939]):
            self.assertEqual(x, course.activities[MoodleQuiz][i]['moduleid'])
    def test_load_activity_sequence(self):
        course = MoodleCourse(self.tmp_path)
        actual = course._load_activity_sequence()

        self.assertEqual([175721, 175723, 175724, 175720, 175722, 176000],
                         actual)
 def test_load_activities(self):
     course = MoodleCourse(self.tmp_path)
     actual = course._load_activites()[MoodleQuiz]
     self.assertEqual(4, len(actual))
     actual = course._load_activites()[MoodleHomework]
     self.assertEqual(1, len(actual))