Exemplo n.º 1
0
 def find_existing(self,
                   registry,
                   title: str,
                   check_front_matter=False,
                   top_directories=None):
     # Get the path to the file
     safe_filename = self.make_markdown_filename(title)
     if not os.path.exists(safe_filename):
         if top_directories is None:
             top_directories = [registry.search_up_for_waltz_registry('./')]
         potential_files = []
         for top_directory in top_directories:
             for root, dirs, files in os.walk(top_directory):
                 for file in files:
                     potential_file = os.path.join(root, file)
                     if file == safe_filename:
                         potential_files.append(potential_file)
                     elif check_front_matter and file.endswith(".md"):
                         _, waltz, _ = extract_front_matter(
                             self.read(potential_file))
                         if waltz.get('title') == title:
                             potential_files.append(potential_file)
         if len(potential_files) > 1:
             raise WaltzAmbiguousResource(
                 "Ambiguous resource named {}:\n\t{}".format(
                     safe_filename,
                     "\n\t".join(potential
                                 for potential in potential_files)),
                 potential_files)
         elif not potential_files:
             raise FileNotFoundError(
                 "No resource named {} found.".format(safe_filename))
         safe_filename, = potential_files
     return safe_filename
Exemplo n.º 2
0
 def list(self, registry, args):
     if args.category:
         category_names = registry.get_resource_category(
             args.category).category_names
     else:
         category_names = None
     rows = []
     for root, dirs, files in os.walk(self.path):
         for name in natsorted(files):
             if name.endswith(".md"):
                 path = os.path.join(root, name)
                 decoded_markdown = self.read(path)
                 try:
                     regular, waltz, body = extract_front_matter(
                         decoded_markdown)
                 except:
                     if category_names is None:
                         rows.append(
                             ("[invalid]", "", os.path.relpath(path)))
                     continue
                 resource = "[{}]".format(waltz.get('resource', 'unknown'))
                 if category_names is None or waltz.get(
                         'resource') in category_names:
                     rows.append(
                         (resource, waltz.get("title",
                                              ""), os.path.relpath(path)))
     print(tabulate(rows, ("Resource", "Title", "Path")))
Exemplo n.º 3
0
 def encode_json(cls, registry: Registry, data: str, args):
     regular, waltz, body = extract_front_matter(data)
     settings = waltz.get('settings', {})
     submission = settings.get('submission', {})
     timing = settings.get('timing', {})
     secrecy = settings.get('secrecy', {})
     body = hide_data_in_html(regular, m2h(body))
     return json.dumps({
         'name': waltz['title'],
         'description': body,
         'html_url': waltz['url'],
         'published': waltz['published'],
         # General settings
         'points_possible': settings['points_possible'],
         'grading_type': settings['grading_type'],
         # Submissions
         'allowed_extensions': submission.get('allowed_extensions'),
         'submission_types': submission['submission_types'],
         # Timing
         'due_at': from_friendly_date(timing['due_at']),
         'unlock_at': from_friendly_date(timing['unlock_at']),
         'lock_at': from_friendly_date(timing['lock_at']),
         # Secrecy
         'anonymize_students': secrecy['anonymize_students'],
         'anonymous_grading': secrecy['anonymous_grading']
     })
Exemplo n.º 4
0
 def encode_json(cls, registry: Registry, data: str, args):
     regular, waltz, body = extract_front_matter(data)
     body = hide_data_in_html(regular, m2h(body))
     return json.dumps({
         'title': waltz['title'],
         'published': waltz['published'],
         'body': body
         # TODO: Other fields
     })
Exemplo n.º 5
0
 def encode_question_by_title(cls, registry: Registry, title: str, args):
     local = registry.get_service(args.local_service, 'local')
     # TODO: By default limit search to "<Quiz> Questions/" folder?
     source_path = local.find_existing(registry, title,
                                       check_front_matter=True, top_directories=args.banks)
     decoded_markdown = local.read(source_path)
     regular, waltz, body = extract_front_matter(decoded_markdown)
     body = hide_data_in_html(regular, m2h(body))
     waltz['question_text'] = body
     return cls.encode_question(registry, waltz, args)
Exemplo n.º 6
0
 def find_existing(self,
                   registry,
                   title: str,
                   check_front_matter=False,
                   top_directories=None,
                   folder_file=None,
                   extension='.md',
                   args=None):
     # Get the path to the file
     if hasattr(args, 'filename') and args.filename and os.path.exists(
             args.filename):
         safe_filename = args.filename
         args.title = self.get_title(args.filename)
     else:
         safe_filename = self.make_markdown_filename(
             title, extension=extension, folder_file=folder_file)
     # Is the exact filepath here?
     if os.path.exists(safe_filename):
         return safe_filename
     # Ah, are we in the containing directory for the path?
     if os.path.exists(make_end_path(safe_filename)):
         return make_end_path(safe_filename)
     # Okay, search recursively from the .waltz file
     else:
         if top_directories is None:
             top_directories = [registry.search_up_for_waltz_registry('./')]
         potential_files = []
         for top_directory in top_directories:
             for root, dirs, files in os.walk(top_directory):
                 for file in files:
                     potential_file = os.path.join(root, file)
                     if all_path_parts_match(potential_file, safe_filename):
                         potential_files.append(potential_file)
                     elif check_front_matter and file.endswith(".md"):
                         _, waltz, _ = extract_front_matter(
                             self.read(potential_file))
                         if waltz.get('title') == title:
                             potential_files.append(potential_file)
         if len(potential_files) > 1:
             raise WaltzAmbiguousResource(
                 "Ambiguous resource named {}:\n\t{}".format(
                     safe_filename,
                     "\n\t".join(potential
                                 for potential in potential_files)),
                 potential_files)
         elif not potential_files:
             raise FileNotFoundError(
                 "No resource named {} found.".format(safe_filename))
         safe_filename, = potential_files
     return safe_filename
Exemplo n.º 7
0
def Push(args):
    registry = Registry.load(args.waltz_directory)
    resource_category = None
    if len(args.resource) == 1:
        local = registry.get_service('local', args.local_service)
        existing_file = local.find_existing(registry, args.resource[0], False, None)
        _, waltz, _ = extract_front_matter(local.read(existing_file))
        if 'resource' in waltz: # TODO: validate resource category
            resource_category = registry.get_resource_category(waltz['resource'])
            args.category = waltz['resource']
            args.title = args.resource[0]
            args.service = registry.get_service(resource_category.default_service).name
    if resource_category is None:
        resource_category = registry.guess_resource_category(args)
    resource_category.encode(registry, args)
    resource_category.upload(registry, args)
Exemplo n.º 8
0
 def diff_extra_files(cls, registry: Registry, data, args):
     local = registry.get_service(args.local_service, 'local')
     regular, waltz, body = extract_front_matter(data)
     for question in waltz['questions']:
         if isinstance(question, str):
             destination_path = local.find_existing(
                 registry,
                 args.title,
                 folder_file=question,
                 check_front_matter=True,
                 top_directories=args.banks)
             yield destination_path, local.read(destination_path)
         elif 'group' in question:
             for inner_question in question['questions']:
                 if isinstance(inner_question, str):
                     destination_path = local.find_existing(
                         registry, args.title, folder_file=inner_question)
                     yield destination_path, local.read(destination_path)
Exemplo n.º 9
0
 def get_title(self, filename):
     data = self.read(filename)
     regular, waltz, body = extract_front_matter(data)
     filename_as_title = os.path.splitext(os.path.basename(filename))[0]
     return waltz.get('title', filename_as_title)
Exemplo n.º 10
0
    def encode_json(cls, registry: Registry, data: str, args):
        regular, waltz, body = extract_front_matter(data)
        # Grab out convenient groups
        visibility = waltz.get('visibility', {})
        forked = waltz.get('forked', {})
        identity = waltz.get('identity', {})
        files = waltz.get('files', {})
        # Grab any extra files
        extra_files = {}
        local = registry.get_service(args.local_service, 'local')
        for py_filename in ['on_run', 'starting_code', 'on_change', 'on_eval']:
            try:
                source_path = local.find_existing(registry,
                                                  args.title,
                                                  folder_file=py_filename,
                                                  extension='.py')
            except FileNotFoundError:
                extra_files[py_filename] = ""
                continue
            extra_files[py_filename] = local.read(source_path)
        collected = {}
        for special, prepend in cls.SPECIAL_INSTRUCTOR_FILES_R.items():
            for file in files.get(special, []):
                source_path = local.find_existing(registry,
                                                  args.title,
                                                  folder_file=file,
                                                  extension="")
                collected[prepend + file] = local.read(source_path)
        if collected:
            extra_files['extra_instructor_files'] = json.dumps(collected)
        else:
            extra_files['extra_instructor_files'] = ""

        # And generate the rest of the JSON
        return json.dumps({
            "_schema_version":
            2,
            'url':
            waltz['title'],
            'name':
            waltz['display title'],
            'type':
            waltz['type'],
            'reviewed':
            waltz.get('human reviewed', False),
            'hidden':
            visibility.get('hide status'),
            'public':
            visibility.get('publicly indexed'),
            'ip_ranges':
            visibility.get('ip ranges', ""),
            'settings':
            json.dumps(waltz['additional settings'])
            if waltz['additional settings'] else None,
            'forked_id':
            forked.get('id', None),
            'forked_version':
            forked.get('version', None),
            'owner_id':
            identity['owner id'],
            'owner_id__email':
            identity['owner email'],
            'course_id':
            identity['course id'],
            'version':
            identity['version downloaded'],
            'date_created':
            from_friendly_date(identity.get('created')),
            'date_modified':
            from_friendly_date(identity.get('modified')),
            'instructions':
            body,
            'extra_starting_files':
            "",
            # TODO: Store sample submissions in BlockPy
            'sample_submissions': [],
            # TODO: Store tags in BlockPy
            'tags': [],
            **extra_files
            # TODO: Other fields
        })
Exemplo n.º 11
0
 def encode_json(cls, registry: Registry, data, args):
     regular, waltz, body = extract_front_matter(data)
     settings = waltz.get('settings', {})
     timing = settings.get('timing', {})
     secrecy = settings.get('secrecy', {})
     body = hide_data_in_html(regular, m2h(body))
     questions = []
     groups = {}
     for question in waltz.get('questions', []):
         if isinstance(question, str):
             # Look up quiz question name
             questions.append(
                 QuizQuestion.encode_question_by_title(
                     registry, question, args))
         elif 'group' in question:
             # This is a question group
             group = QuizGroup.encode_group(registry, question, args)
             groups[group['name']] = group
             questions.extend(
                 QuizGroup.encode_questions(registry, question, args))
         else:
             # This is an embedded question
             questions.append(
                 QuizQuestion.encode_question(registry, question, args))
     # TODO: total_estimated_points from the questions
     return json.dumps({
         'title':
         waltz['title'],
         'published':
         waltz.get('published', False),
         'description':
         body,
         # Settings
         'quiz_type':
         settings.get('quiz_type', 'assignment'),
         'points_possible':
         settings.get('points_possible'),
         'allowed_attempts':
         settings.get('allowed_attempts'),
         'scoring_policy':
         settings.get('scoring_policy'),
         # Timing
         'due_at':
         from_friendly_date(timing.get('due_at')),
         'unlock_at':
         from_friendly_date(timing.get('unlock_at')),
         'lock_at':
         from_friendly_date(timing.get('lock_at')),
         # Secrecy
         'one_question_at_a_time':
         int(secrecy.get('one_question_at_a_time', 0)),
         'shuffle_answers':
         int(secrecy.get('shuffle_answers', 0)),
         'time_limit':
         secrecy.get('time_limit'),
         'cant_go_back':
         int(secrecy.get('cant_go_back', 0)),
         'show_correct_answers':
         int(secrecy.get('show_correct_answers', 1)),
         'show_correct_answers_last_attempt':
         secrecy.get('show_correct_answers_last_attempt'),
         'show_correct_answers_at':
         secrecy.get('show_correct_answers_at'),
         'hide_correct_answers_at':
         secrecy.get('hide_correct_answers_at'),
         'hide_results':
         secrecy.get('hide_results'),
         'one_time_results':
         int(secrecy.get('one_time_results', 0)),
         'access_code':
         secrecy.get('access_code'),
         'ip_filter':
         secrecy.get('ip_filter'),
         # Questions and Groups
         'questions':
         questions,
         'groups':
         groups
     })