示例#1
0
def setup(conf_file):
    global api, sess

    with open(conf_file, "r") as f:
       CONF.update(json.load(f))

    api = AplusTokenClient(CONF['api_token'])
    api.set_base_url_from(CONF['base_url'])

    sess = requests.Session()
    logging.basicConfig()
示例#2
0
    def handle(self, *args, **options):
        token = options['token']
        wait = options['wait'] / 1000
        courses = get_courses(self,
                              site_domain=options['site'],
                              course_code=options['course'])

        client = AplusTokenClient(token, debug_enabled=True)

        if not options['no_students']:
            if courses:
                students = Student.objects.get_students_on_courses(courses)
            else:
                students = Student.objects.all()
            for student in students:
                self.stdout.write(
                    self.style.NOTICE("Working on {}, {}".format(
                        student, student.url)))
                student.update_using(client)
                student.save()

        if not options['no_taggings']:
            for course in courses:
                self.stdout.write(
                    self.style.NOTICE("Updating tags for course {}, {}".format(
                        course, course.url)))
                tag_summary = StudentTag.update_from_api(client, course)
                self.stdout.write(
                    self.style.SUCCESS(
                        "  Tags updated. {} new, {} updated, {} deleted.".
                        format(
                            len(tag_summary['new']),
                            len(tag_summary['updated']),
                            len(tag_summary['deleted']),
                        )))
示例#3
0
    def handle(self, *args, **options):
        token = options['token']
        wait = options['wait'] / 1000
        courses = get_courses(self,
                              site_domain=options['site'],
                              course_code=options['course'])

        if courses:
            students = Student.objects.get_students_on_courses(courses)
        else:
            students = Student.objects.all()

        client = AplusTokenClient(token, debug_enabled=True)

        for student in students:
            self.stdout.write(
                self.style.NOTICE("Working on {}, {}".format(
                    student, student.url)))
            student.update_using(client)
            student.save()

        for course in courses:
            self.stdout.write(
                self.style.NOTICE("Updating tags for course {}, {}".format(
                    course, course.url)))
            StudentTag.update_from_api(client, course)
示例#4
0
 def get_api_client(self, site):
     try:
         token = self.tokens.get(site=site)
     except Token.DoesNotExist:
         return None
     return AplusTokenClient(token.token)
示例#5
0
        'englanti': 'en',
    },
}

p = ArgumentParser()
p.add_argument('-v',
               '--verbose',
               action='store_true',
               help="Print logging messages")
p.add_argument('-t', '--token', help='Token for A+ API')
args = p.parse_args()

if args.verbose:
    logging.basicConfig(level=logging.DEBUG)

api = AplusTokenClient(args.token)
api.set_base_url_from(CONFIG['base_url'])


def get_submission(submission_id):
    return api.load_data('{submissions_url}{submission_id}/'.format(
        **CONFIG, submission_id=submission_id))


def add_tagging(exercise_id, submission_id):
    if exercise_id not in CONFIG['exercise_ids']:
        return

    submission = get_submission(submission_id)
    submitters = submission['submitters']
    submission_data = submission['submission_data']
示例#6
0
def download(destination, courses, users):
    # domain and token
    domain = config.get('main', 'domain')
    if not domain:
        raise RuntimeError("no domain, run `set-fomain` first")
    token = config.get(domain, 'api-token')
    if not token:
        raise RuntimeError("no api token, run `set-domain` first")

    # api client
    api = AplusTokenClient(token,
                           cache=FilesystemCache(
                               os.path.join(CACHE_DIR, domain)))
    base_url = config.get(domain,
                          'api-url',
                          fallback='https://%s/api/v2' % (domain, ))
    api.set_base_url_from(base_url)
    me = api.load_data('/me/', skip_cache=True)

    # courses
    if not courses:
        courses = me['enrolled_courses']
    else:
        course_ids = set()
        course_urls = set()
        for filter_ in courses:
            key, value = filter_.split('=', 1)
            if key == 'id':
                course_ids.add(int(value))
            elif key == 'url':
                course_urls.add(value.strip('/'))
            else:
                raise ValueError(
                    "Unsupported course filter %r. id= and url= are supported"
                    % (key, ))
        courses = [api.load_data('/courses/%d/' % i) for i in course_ids]
        course_urls -= set(get_course_url(c) for c in courses)
        if course_urls:
            for course in api.load_data('/courses/'):
                url = get_course_url(course)
                if url in course_urls:
                    courses.append(course)
                    course_urls.remove(url)
                    if not course_urls:
                        break
        if course_urls:
            raise ValueError("Course urls %s were not found" % (course_urls, ))
    if not courses:
        raise ValueError("No courses selected")

    print("Selected courses:")
    for course in courses:
        print(
            "  {c.code} - {c.name} ({c.instance_name}) <{c.html_url}>".format(
                c=course))

    # users
    if not users:
        users = [me]
    else:
        user_ids = set()
        user_sids = set()
        for filter_ in users:
            key, value = filter_.split('=', 1)
            if key == 'id':
                user_ids.add(int(value))
            elif key == 'sid':
                user_sids.add(value.strip().lower())
            else:
                raise ValueError(
                    "Unsupported course filter %r. id and sid are supported" %
                    (key, ))
        users = [api.load_data('/users/%d/' % i) for i in user_ids]
        user_sids -= set(u.student_id.lower() for u in users)
        if user_sids:
            for course in courses:
                for student in course.students:
                    if student.student_id and student.student_id.lower(
                    ) in user_sids:
                        users.append(student)
                        user_sids.remove(student.student_id.lower())
                        if not user_sids:
                            break
                if not user_sids:
                    break
        if user_sids:
            raise ValueError("Student ids %s were not found on any courses" %
                             (user_sids, ))
    if not users:
        raise ValueError("No users selected")

    print("Selected users:")
    for user in users:
        print("  {u.student_id}: {u.full_name} <{u.email}> (id={u.id})".format(
            u=user))

    # crawl submissions using points cache
    submission_count = 0
    for course in courses:
        course_dir = "{c.code} - {c.name} ({c.instance_name}) (id={c.id})".format(
            c=course)
        for user in users:
            points = api.load_data('/courses/%d/points/%d/' %
                                   (course.id, user.id))
            name = ("{u.last_name}, {u.first_name} ({u.student_id})"
                    if user.get('student_id') else
                    "{u.last_name}, {u.first_name} (id={u.id})").format(u=user)
            if not points:
                raise ValueError("User %s is not enrolled on the course %s" %
                                 (name, course_dir))
            user_dir = os.path.join(destination, course_dir, name)
            user_data = dict_from_api(points, 'student_id', 'full_name',
                                      'first_name', 'last_name', 'email',
                                      ('api_url', 'url'))
            user_data['tags'] = [(t.name, t.description)
                                 for t in points['tags']]
            user_data.update(
                dict_from_api(points, 'submission_count', 'points',
                              'points_by_difficulty'))
            write_yaml(user_dir, 'user.yaml', user_data)

            for module in points['modules']:
                exercises = module['exercises']
                if not exercises:
                    continue

                module_name = "{} (id={})".format(module.name[:40], module.id)
                module_dir = os.path.join(user_dir, module_name)
                module_data = dict_from_api(module, 'id', 'name',
                                            'submission_count', 'passed',
                                            'max_points', 'points_to_pass',
                                            'points', 'points_by_difficulty')
                write_yaml(module_dir, 'module.yaml', module_data)

                for exercise in exercises:
                    exercise_name = "{} (id={})".format(
                        exercise.name[:40], exercise.id)
                    exercise_dir = os.path.join(module_dir, exercise_name)
                    exercise_data = dict_from_api(exercise, 'id',
                                                  ('api_url', 'url'), 'name',
                                                  'difficulty',
                                                  'submission_count', 'passed',
                                                  'max_points',
                                                  'points_to_pass', 'points')

                    submissions = exercise['submissions']
                    if not submissions:
                        write_yaml(module_dir, exercise_name + '.yaml',
                                   exercise_data)
                    else:
                        write_yaml(exercise_dir, 'exercise.yaml',
                                   exercise_data)
                        best_url = exercise['best_submission']
                        for submission_url in submissions:
                            best = submission_url == best_url
                            submission = api.load_data(submission_url)
                            download_submission(api,
                                                submission,
                                                exercise_dir,
                                                best=best)
                            submission_count += 1

    print("DONE. Downloaded %d submissions" % submission_count)
    return

    # OLD METHOD

    # find all submission API points
    data = {}
    for course in courses:
        info = "{c.code} - {c.name} ({c.instance_name}) (id={c.id})".format(
            c=course)
        subs = []
        data[info] = subs

        for module in course['exercises']:
            for exercise in module['exercises']:
                if 'submissions' not in exercise:
                    continue
                url = exercise.get_item('submissions')
                if not url.endswith('/'):
                    url += '/'
                subs.append(url)

    from pprint import pprint
    pprint(data)

    # download all submissions for all users in all endpoints
    for info, submission_urls in data.items():
        for user in users:
            name = user['student_id'] or ('aplus_%d' % user.id)
            user_data = dict_from_api(user, 'student_id', 'email',
                                      'first_name', 'last_name', 'full_name')
            for url in submission_urls:
                for submission in api.load_data('%s%d/' %
                                                (url, user.id)) or []:
                    ename = get_exercise_fn(submission.exercise, dirs=1)
                    path = os.path.join(destination, info, name, ename)
                    if not os.path.exists(path):
                        os.makedirs(path)
                    download_submission(api, submission, path)
示例#7
0
from aplus_client.client import AplusTokenClient
from flask import current_app as app

api = AplusTokenClient(None)