Example #1
0
def add_new_rubric_row(
    assig: models.Assignment, header: str, description: str,
    items: t.Sequence[JSONType]
) -> int:
    """Add new rubric row to the assignment.

    :param assig: The assignment to add the rubric row to
    :param header: The name of the new rubric row.
    :param description: The description of the new rubric row.
    :param items: The items (:py:class:`.models.RubricItem`) that should be
        added to the new rubric row, the JSONType should be a dictionary with
        the keys ``description`` (:py:class:`str`), ``header``
        (:py:class:`str`) and ``points`` (:py:class:`float`).
    :returns: The amount of items in this row.

    :raises APIException: If `description` or `points` fields are not in
        `item`. (INVALID_PARAM)
    """
    rubric_row = models.RubricRow(
        assignment_id=assig.id, header=header, description=description
    )
    for item in items:
        item = ensure_json_dict(item)
        ensure_keys_in_dict(
            item,
            [('description', str),
             ('header', str),
             ('points', numbers.Real)]
        )
        description = t.cast(str, item['description'])
        header = t.cast(str, item['header'])
        points = t.cast(numbers.Real, item['points'])
        rubric_item = models.RubricItem(
            rubricrow_id=rubric_row.id,
            header=header,
            description=description,
            points=points
        )
        db.session.add(rubric_item)
        rubric_row.items.append(rubric_item)
    db.session.add(rubric_row)

    return len(items)
Example #2
0
def test_data(db=None):
    db = db or psef.models.db

    if not app.config['DEBUG']:
        print('You can not add test data in production mode', file=sys.stderr)
        return 1

    seed()
    db.session.commit()
    with open(
        f'{os.path.dirname(os.path.abspath(__file__))}/test_data/courses.json',
        'r'
    ) as c:
        cs = json.load(c)
        for c in cs:
            if m.Course.query.filter_by(name=c['name']).first() is None:
                db.session.add(m.Course(name=c['name']))
    db.session.commit()
    with open(
        f'{os.path.dirname(os.path.abspath(__file__))}/test_data/assignments.json',
        'r'
    ) as c:
        cs = json.load(c)
        for c in cs:
            assig = m.Assignment.query.filter_by(name=c['name']).first()
            if assig is None:
                db.session.add(
                    m.Assignment(
                        name=c['name'],
                        deadline=datetime.datetime.utcnow() +
                        datetime.timedelta(days=c['deadline']),
                        state=c['state'],
                        description=c['description'],
                        course=m.Course.query.filter_by(name=c['course']
                                                        ).first()
                    )
                )
            else:
                assig.description = c['description']
                assig.state = c['state']
                assig.course = m.Course.query.filter_by(name=c['course']
                                                        ).first()
    db.session.commit()
    with open(
        f'{os.path.dirname(os.path.abspath(__file__))}/test_data/users.json',
        'r'
    ) as c:
        cs = json.load(c)
        for c in cs:
            u = m.User.query.filter_by(name=c['name']).first()
            courses = {
                m.Course.query.filter_by(name=name).first(): role
                for name, role in c['courses'].items()
            }
            perms = {
                course.id:
                m.CourseRole.query.filter_by(name=name,
                                             course_id=course.id).first()
                for course, name in courses.items()
            }
            username = c['name'].split(' ')[0].lower()
            if u is not None:
                u.name = c['name']
                u.courses = perms
                u.email = c['name'].replace(' ', '_').lower() + '@example.com'
                u.password = c['name']
                u.username = username
                u.role = m.Role.query.filter_by(name=c['role']).first()
            else:
                u = m.User(
                    name=c['name'],
                    courses=perms,
                    email=c['name'].replace(' ', '_').lower() + '@example.com',
                    password=c['name'],
                    username=username,
                    role=m.Role.query.filter_by(name=c['role']).first()
                )
                db.session.add(u)
                for course, role in courses.items():
                    if role == 'Student':
                        for assig in course.assignments:
                            work = m.Work(assignment=assig, user=u)
                            db.session.add(
                                m.File(
                                    work=work,
                                    name='Top stub dir',
                                    is_directory=True
                                )
                            )
                            db.session.add(work)
    db.session.commit()
    with open(
        f'{os.path.dirname(os.path.abspath(__file__))}/test_data/rubrics.json',
        'r'
    ) as c:
        cs = json.load(c)
        for c in cs:
            for row in c['rows']:
                assignment = m.Assignment.query.filter_by(
                    name=c['assignment']
                ).first()
                if assignment is not None:
                    rubric_row = m.RubricRow.query.filter_by(
                        header=row['header'],
                        description=row['description'],
                        assignment_id=assignment.id
                    ).first()
                    if rubric_row is None:
                        rubric_row = m.RubricRow(
                            header=row['header'],
                            description=row['description'],
                            assignment=assignment
                        )
                        db.session.add(rubric_row)
                    for item in row['items']:
                        if not db.session.query(
                            m.RubricItem.query.filter_by(
                                rubricrow_id=rubric_row.id,
                                **item,
                            ).exists()
                        ).scalar():
                            rubric_item = m.RubricItem(
                                description=item['description'] * 5,
                                header=item['header'],
                                points=item['points'],
                                rubricrow=rubric_row
                            )
                            db.session.add(rubric_item)
    db.session.commit()
Example #3
0
def test_data(db=None):
    db = psef.models.db if db is None else db

    if not app.config['DEBUG']:
        print('You can not add test data in production mode', file=sys.stderr)
        return 1
    if not os.path.isdir(app.config['UPLOAD_DIR']):
        os.mkdir(app.config['UPLOAD_DIR'])

    seed()
    db.session.commit()
    with open(
            f'{os.path.dirname(os.path.abspath(__file__))}/test_data/courses.json',
            'r') as c:
        cs = json.load(c)
        for c in cs:
            if m.Course.query.filter_by(name=c['name']).first() is None:
                db.session.add(m.Course.create_and_add(name=c['name']))
    db.session.commit()
    with open(
            f'{os.path.dirname(os.path.abspath(__file__))}/test_data/assignments.json',
            'r') as c:
        cs = json.load(c)
        for c in cs:
            assig = m.Assignment.query.filter_by(name=c['name']).first()
            if assig is None:
                db.session.add(
                    m.Assignment(
                        name=c['name'],
                        deadline=cg_dt_utils.now() +
                        datetime.timedelta(days=c['deadline']),
                        state=c['state'],
                        description=c['description'],
                        course=m.Course.query.filter_by(
                            name=c['course']).first(),
                        is_lti=False,
                    ))
            else:
                assig.description = c['description']
                assig.state = c['state']
                assig.course = m.Course.query.filter_by(
                    name=c['course']).first()
    db.session.commit()
    with open(
            f'{os.path.dirname(os.path.abspath(__file__))}/test_data/users.json',
            'r') as c:
        cs = json.load(c)
        for c in cs:
            u = m.User.query.filter_by(name=c['name']).first()
            courses = {
                m.Course.query.filter_by(name=name).first(): role
                for name, role in c['courses'].items()
            }
            perms = {
                course.id:
                m.CourseRole.query.filter_by(name=name,
                                             course_id=course.id).first()
                for course, name in courses.items()
            }
            username = c['name'].split(' ')[0].lower()
            if u is not None:
                u.name = c['name']
                u.courses = perms
                u.email = c['name'].replace(' ', '_').lower() + '@example.com'
                u.password = c['name']
                u.username = username
                u.role = m.Role.query.filter_by(name=c['role']).first()
            else:
                u = m.User(name=c['name'],
                           courses=perms,
                           email=c['name'].replace(' ', '_').lower() +
                           '@example.com',
                           password=c['name'],
                           username=username,
                           role=m.Role.query.filter_by(name=c['role']).first())
                db.session.add(u)
                for course, role in courses.items():
                    if role == 'Student':
                        for assig in course.assignments:
                            work = m.Work(assignment=assig, user=u)
                            f = m.File(work=work,
                                       name='Top stub dir ({})'.format(u.name),
                                       is_directory=True)
                            filename = str(uuid.uuid4())
                            shutil.copyfile(
                                __file__,
                                os.path.join(app.config['UPLOAD_DIR'],
                                             filename))
                            f.children = [
                                m.File(work=work,
                                       name='manage.py',
                                       is_directory=False,
                                       filename=filename)
                            ]
                            db.session.add(f)
                            db.session.add(work)
    db.session.commit()
    with open(
            f'{os.path.dirname(os.path.abspath(__file__))}/test_data/rubrics.json',
            'r') as c:
        cs = json.load(c)
        for c in cs:
            for row in c['rows']:
                assignment = m.Assignment.query.filter_by(
                    name=c['assignment']).first()
                if assignment is not None:
                    rubric_row = m.RubricRow.query.filter_by(
                        header=row['header'],
                        description=row['description'],
                        assignment_id=assignment.id,
                    ).first()
                    if rubric_row is None:
                        rubric_row = m.RubricRow(
                            header=row['header'],
                            description=row['description'],
                            assignment=assignment,
                            rubric_row_type='normal',
                        )
                        db.session.add(rubric_row)
                    for item in row['items']:
                        if not db.session.query(
                                m.RubricItem.query.filter_by(
                                    rubricrow_id=rubric_row.id,
                                    **item,
                                ).exists()).scalar():
                            rubric_item = m.RubricItem(
                                description=item['description'] * 5,
                                header=item['header'],
                                points=item['points'],
                                rubricrow=rubric_row)
                            db.session.add(rubric_item)
    db.session.commit()
Example #4
0
def patch_rubric_row(
    header: str,
    description: str,
    rubric_row_id: int,
    items: t.Sequence[JSONType],
) -> int:
    """Update a rubric row of the assignment.

    .. note::

      All items not present in the given ``items`` array will be deleted from
      the rubric row.

    :param rubric_row_id: The id of the rubric row that should be updated.
    :param items: The items (:py:class:`models.RubricItem`) that should be
        added or updated. The format should be the same as in
        :py:func:`add_new_rubric_row` with the addition that if ``id`` is in
        the item the item will be updated instead of added.
    :returns: The amount of items in the resulting row.

    :raises APIException: If `description` or `points` fields are not in
        `item`. (INVALID_PARAM)
    :raises APIException: If no rubric item with given id exists.
        (OBJECT_ID_NOT_FOUND)
    """
    rubric_row = helpers.get_or_404(models.RubricRow, rubric_row_id)

    rubric_row.header = header
    rubric_row.description = description

    seen = set()

    for item in items:
        item = ensure_json_dict(item)
        ensure_keys_in_dict(
            item,
            [('description', str),
             ('points', numbers.Real),
             ('header', str)]
        )
        description = t.cast(str, item['description'])
        header = t.cast(str, item['header'])
        points = t.cast(numbers.Real, item['points'])

        if 'id' in item:
            seen.add(item['id'])
            rubric_item = helpers.get_or_404(models.RubricItem, item['id'])

            rubric_item.header = header
            rubric_item.description = description
            rubric_item.points = float(points)
        else:
            rubric_item = models.RubricItem(
                rubricrow_id=rubric_row.id,
                description=description,
                header=header,
                points=points
            )
            db.session.add(rubric_item)
            rubric_row.items.append(rubric_item)

    rubric_row.items = [
        item for item in rubric_row.items if item.id is None or item.id in seen
    ]

    return len(rubric_row.items)