Пример #1
0
def add_students_to_sections_random(section_names):
    course = canvas.Course()
    can = canvas.Canvas()

    section_ids = {
        section_name: find_section_id(section_name)
        for section_name in section_names
    }

    users_all = can.list_students(course.id)

    random.shuffle(users_all)
    users_slice_start = 0
    for section_name, n_sections_remaining in zip(
            section_names, range(len(section_ids), 0, -1)):
        n_users_remaining = len(users_all) - users_slice_start
        section_size = n_users_remaining // n_sections_remaining
        section_id = section_ids[section_name]
        section_users = users_all[users_slice_start:users_slice_start +
                                  section_size]
        print('Section {} (id: {}) gets {} students: {}'.format(
            repr(section_name), section_id, section_size,
            ', '.join(u['name'] for u in section_users)))
        for user in section_users:
            can.add_section_member(section_id, user['id'])
        users_slice_start += section_size
Пример #2
0
def find_user(user_name):
    course = canvas.Course()
    can = canvas.Canvas()
    users = can.list_students(course.id)

    # Hack to remove duplicates.
    users_found = list(filter(lambda user: user_name == user['name'] or user_name == user['login_id'][:6], users))
    users_found = list(set(tuple(x.items()) for x in users_found))
    users_found = [{k: v for k, v in x} for x in users_found]
    if len(users_found) == 1:
        print('Found; id: {}, sis_user_id: {}, sis_login_id: {}, name: {}'.format(
            users_found[0]['id'], users_found[0]['sis_user_id'],
            users_found[0]['sis_login_id'], users_found[0]['name']))
    elif len(users_found) > 1:
        print('{} users found:'.format(len(users_found)))
        for user in users_found:
            print(user)
        sys.exit(1)
    else:
        print('No users found.  Guesses:')
        users.sort(key=lambda user: levenshtein.ratio(user_name, user['name']),
                   reverse=True)
        for user in users[:10]:
            print('{:.2%} match; id: {}, sis_user_id: {}, sis_login_id: {}, name: {}'.format(
                levenshtein.ratio(user_name, user['name']),
                user['id'], user['sis_user_id'],
                user['sis_login_id'], user['name']))

        sys.exit(1)
Пример #3
0
def set_group_members(group_name, user_names):
    course = canvas.Course()

    can = canvas.Canvas()
    groups_all = can.groups_in_course(course.id)
    groups = list(filter(lambda x: x['name'] == group_name,
                         groups_all))
    if len(groups) < 1:
        raise Exception('no group of that name')
    else:
        group_id = groups[0]['id']

    users_all = can.list_students(course.id)
    user_ids = []
    for user_name in user_names:
        users = list(filter(lambda x: x['name'] == user_name,
                            users_all))
        if len(users) < 1:
            raise Exception('no user of that name')
        else:
            user_id = users[0]['id']
        user_ids.append(user_id)
    can.add_group_members(group_id, user_ids)

    fetch_groups(course) # a bit silly, and very slow
Пример #4
0
def create(subs_path, category_name, groups_file):
    canvas = canvaslib.Canvas()
    course = canvaslib.Course()

    # Get mapping from abc123 to Canvas User ID.
    user_ids = get_user_id_mapping(canvas, course)

    # Extract groups.
    with open(groups_file) as f:
        contents = f.read().strip()
    groups = [line.split(' ') for line in contents.split('\n')]

    # Update Canvas.
    create_groups_on_canvas(canvas, course, category_name, user_ids, groups)

    # Update locally.
    groupsubs_path = subs_path.replace('subs/', 'groupsubs/')
    os.makedirs(groupsubs_path, exist_ok=True)
    for group_members, group_number in zip(groups, range(len(groups))):
        groupsub_path = os.path.join(groupsubs_path,
                                     '{:03d}'.format(group_number))
        group_members_submitted = []
        total_count = 0
        for abc123 in group_members:
            pattern = os.path.join(subs_path, abc123) + '_*'
            subpaths = glob.glob(pattern)

            # There should be 0 or 1 directories that match.
            # 0 if, for some reason, a KU ID specified in a group.txt doesn't
            #   have a submission. (This can be for other reasons than that it
            #   is an invalid KU ID, or that that KU ID isn't subscribed to the
            #   course. Example: cbh239 is on Advanced Programming 2017 and was
            #   mentioned in a group.txt, they didn't submit anything
            #   themselves for assignment 1, but they don't have an empty
            #   directory like other students.
            if len(subpaths) > 1:
                raise Exception('Wait! Two submissions match {}: {}'.format(
                    abc123, ", ".join(subpaths)))

            elif len(subpaths) == 1:
                subpath = subpaths[0]
                ignore_files = [".staffeli.yml", "group.txt"]
                files = [
                    f for f in os.listdir(subpath) if f not in ignore_files
                ]
                if len(files) > 0:
                    group_members_submitted.append(subpath)

        if len(group_members_submitted) != 1:
            raise Exception('Wait! Multiple submissions from {}: {}'.format(
                ", ".join(group_members), ", ".join(group_members_submitted)))

        submitter_path = group_members_submitted[0]
        os.symlink(os.path.join('..', '..', submitter_path), groupsub_path)

    return 0
Пример #5
0
def clone(args):
    dirname = " ".join(args)

    course = canvas.Canvas().course(name=dirname)
    mknewdir(dirname)
    course.cache(dirname)

    os.chdir(dirname)
    fetch_students(course)
    fetch_groups(course)
Пример #6
0
def find_section_id(section_name):
    course = canvas.Course()
    can = canvas.Canvas()

    sections_all = can.course_sections(course.id)
    sections = list(filter(lambda x: x['name'] == section_name, sections_all))
    if len(sections) < 1:
        raise Exception('no section of that name')
    else:
        section_id = sections[0]['id']
    return section_id
Пример #7
0
def delete_all_groups(group_category_name):
    course = canvas.Course()
    can = canvas.Canvas()

    categories_all = can.group_categories(course.id)
    categories = list(
        filter(lambda x: x['name'] == group_category_name, categories_all))
    if len(categories) < 1:
        raise Exception('no category of that name')
    else:
        group_category_id = categories[0]['id']

    can.delete_all_groups(group_category_id)

    fetch_groups(course)  # a bit silly, and very slow
Пример #8
0
def add_member_to_section(section_name, user_name):
    course = canvas.Course()
    can = canvas.Canvas()

    section_id = find_section_id(section_name)

    users_all = can.list_students(course.id)
    users = list(filter(lambda x: (x['name'] == user_name or
                                   x['login_id'][:6] == user_name),
                        users_all))
    if len(users) < 1:
        raise Exception('no user of that name')
    else:
        user_id = users[0]['id']
    can.add_section_member(section_id, user_id)
Пример #9
0
def clone(remargs):
    if len(remargs) == 1:
        course_name = remargs[0]
        dirname = course_name
    elif len(remargs) == 2:
        course_name = remargs[0]
        dirname = remargs[1]
    else:
        print("Usage: staffeli clone 'COURSE NAME' [DIRECTORY], or see: staffeli help")
        sys.exit(1)

    course = canvas.Canvas().course(name = course_name)
    mknewdir(dirname)
    course.cache(dirname)

    print("Cloning '{}' into '{}'...".format(course.displayname, dirname))

    os.chdir(dirname)
    fetch_students(course)
    fetch_groups(course)
Пример #10
0
#!/usr/bin/env python3
#
# Split into sections.

import sys
import re
import os

import staffeli.canvas as canvas


course = canvas.Course()
can = canvas.Canvas()

def create(groupsubs_path, groups_file, *section_names):
    sections_path = groupsubs_path.replace('groupsubs/', 'sections/')

    with open(groups_file) as f:
        contents = f.read().strip()
    groups = [line.split(' ') for line in contents.split('\n')]

    groups_distributed = []

    all_sections = can.list_sections(course.id)
    for name in section_names:
        section = next(filter(lambda sec: sec['name'] == name,
                              all_sections))

        m = re.match(r'Class (.+)', name)
        if m is not None:
            name = m.group(1).lower()