Пример #1
0
    def update_task_descriptor_content(self,
                                       courseid,
                                       taskid,
                                       content,
                                       force_extension=None):
        """
        Update the task descriptor with the dict in content
        :param course: the course id of the course
        :param taskid: the task id of the task
        :param content: the content to put in the task file
        :param force_extension: If None, save it the same format. Else, save with the given extension
        :raise InvalidNameException, TaskNotFoundException, TaskUnreadableException
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        if force_extension is None:
            path_to_descriptor, _, descriptor_manager = self._get_task_descriptor_info(
                courseid, taskid)
        elif force_extension in self.get_available_task_file_extensions():
            path_to_descriptor = os.path.join(self._tasks_directory, courseid,
                                              taskid,
                                              "task." + force_extension)
            descriptor_manager = self._task_file_managers[force_extension]
        else:
            raise TaskReaderNotFoundException()

        try:
            with codecs.open(path_to_descriptor, 'w', 'utf-8') as fd:
                fd.write(descriptor_manager.dump(content))
        except:
            raise TaskNotFoundException()
Пример #2
0
 def delete_all_possible_task_files(self, courseid, taskid):
     """ Deletes all possibles task files in directory, to allow to change the format """
     if not id_checker(courseid):
         raise InvalidNameException("Course with invalid name: " + courseid)
     if not id_checker(taskid):
         raise InvalidNameException("Task with invalid name: " + taskid)
     task_fs = self.get_task_fs(courseid, taskid)
     for ext in self.get_available_task_file_extensions():
         try:
             task_fs.delete("task." + ext)
         except:
             pass
Пример #3
0
 def get_task_fs(self, courseid, taskid):
     """
     :param courseid: the course id of the course
     :param taskid: the task id of the task
     :raise InvalidNameException
     :return: A FileSystemProvider to the folder containing the task files
     """
     if not id_checker(courseid):
         raise InvalidNameException("Course with invalid name: " + courseid)
     if not id_checker(taskid):
         raise InvalidNameException("Task with invalid name: " + taskid)
     return self._filesystem.from_subfolder(courseid).from_subfolder(taskid)
Пример #4
0
 def get_directory_path(self, courseid, taskid):
     """
     :param courseid: the course id of the course
     :param taskid: the task id of the task
     :raise InvalidNameException
     :return: The path to the directory that contains the files related to the task
     """
     if not id_checker(courseid):
         raise InvalidNameException("Course with invalid name: " + courseid)
     if not id_checker(taskid):
         raise InvalidNameException("Task with invalid name: " + taskid)
     return os.path.join(self._tasks_directory, courseid, taskid)
Пример #5
0
 def get_task_descriptor_extension(self, courseid, taskid):
     """
         :param courseid: the course id of the course
         :param taskid: the task id of the task
         :raise InvalidNameException, TaskNotFoundException
         :return: the current extension of the task descriptor
         """
     if not id_checker(courseid):
         raise InvalidNameException("Course with invalid name: " + courseid)
     if not id_checker(taskid):
         raise InvalidNameException("Task with invalid name: " + taskid)
     descriptor_path = self._get_task_descriptor_info(courseid, taskid)[0]
     return splitext(descriptor_path)[1]
Пример #6
0
    def _update_cache(self, course, taskid):
        """
        Updates the cache
        :param course: a Course object
        :param taskid: a (valid) task id
        :raise InvalidNameException, TaskNotFoundException, TaskUnreadableException
        """
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_fs = self.get_task_fs(course.get_id(), taskid)
        descriptor_name, descriptor_reader = self._get_task_descriptor_info(course.get_id(), taskid)
        try:
            task_content = descriptor_reader.load(task_fs.get(descriptor_name))
        except Exception as e:
            raise TaskUnreadableException(str(e))

        last_modif = {descriptor_name: task_fs.get_last_modification_time(descriptor_name)}
        translations_fs = task_fs.from_subfolder("$i18n")
        if translations_fs.exists():
            for f in translations_fs.list(folders=False, files=True, recursive=False):
                lang = f[0:len(f) - 3]
                if translations_fs.exists(lang + ".mo"):
                    last_modif["$i18n/" + lang + ".mo"] = translations_fs.get_last_modification_time(lang + ".mo")

        self._cache[(course.get_id(), taskid)] = (
            self._task_class(course, taskid, task_content, task_fs, self._hook_manager, self._task_problem_types),
            last_modif
        )
Пример #7
0
    def _cache_update_needed(self, course, taskid):
        """
        :param course: a Course object
        :param taskid: a (valid) task id
        :raise InvalidNameException, TaskNotFoundException
        :return: True if an update of the cache is needed, False else
        """
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_fs = self.get_task_fs(course.get_id(), taskid)

        if (course.get_id(), taskid) not in self._cache:
            return True

        try:
            descriptor_name = self._get_task_descriptor_info(course.get_id(), taskid)[0]
            last_update = {descriptor_name: task_fs.get_last_modification_time(descriptor_name)}
            translations_fs = task_fs.from_subfolder("$i18n")
            if translations_fs.exists():
                for f in translations_fs.list(folders=False, files=True, recursive=False):
                    lang = f[0:len(f) - 3]
                    if translations_fs.exists(lang + ".mo"):
                        last_update["$i18n/" + lang + ".mo"] = translations_fs.get_last_modification_time(lang + ".mo")
        except:
            raise TaskNotFoundException()

        last_modif = self._cache[(course.get_id(), taskid)][1]
        for filename, mftime in last_update.items():
            if filename not in last_modif or last_modif[filename] < mftime:
                return True

        return False
Пример #8
0
    def create_course(self, courseid, init_content):
        """
        :param courseid: the course id of the course
        :param init_content: initial descriptor content
        :raise InvalidNameException or CourseAlreadyExistsException
        Create a new course folder and set initial descriptor content, folder can already exist
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)

        course_fs = self.get_course_fs(courseid)
        course_fs.ensure_exists()

        if course_fs.exists("course.yaml") or course_fs.exists("course.json"):
            raise CourseAlreadyExistsException("Course with id " + courseid +
                                               " already exists.")
        else:
            course_fs.put("course.yaml",
                          get_json_or_yaml("course.yaml", init_content))

        get_course_logger(courseid).info("Course %s created in the factory.",
                                         courseid)
        self._hook_manager.call_hook('course_created',
                                     courseid=courseid,
                                     new_content=init_content)
Пример #9
0
    def create_course(self, courseid, init_content):
        """
        :param courseid: the course id of the course
        :param init_content: initial descriptor content
        :raise InvalidNameException or CourseAlreadyExistsException
        Create a new course folder and set initial descriptor content, folder can already exist
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)

        course_directory = os.path.join(self._tasks_directory, courseid)
        if not os.path.exists(course_directory):
            os.mkdir(course_directory)

        base_file = os.path.join(course_directory, "course")
        if not os.path.isfile(base_file +
                              ".yaml") and not os.path.isfile(base_file +
                                                              ".json"):
            write_yaml(os.path.join(course_directory, "course.yaml"),
                       init_content)
        else:
            raise CourseAlreadyExistsException("Course with id " + courseid +
                                               " already exists.")

        get_course_logger(courseid).info("Course %s created in the factory.",
                                         courseid)
Пример #10
0
    def delete_task(self, courseid, taskid):
        """ Erase the content of the task folder
        :param courseid: the course id of the course
        :param taskid: the task id of the task
        :raise: InvalidNameException or CourseNotFoundException
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_fs = self.get_task_fs(courseid, taskid)

        if task_fs.exists():
            task_fs.delete()
            get_course_logger(courseid).info("Task %s erased from the factory.", taskid)
Пример #11
0
    def update_temporal_task_file(self, course, taskid, data):
        """
        :param course: a Course object
        :param taskid: the task id of the task
        :param data: a Dict with the temporary data of the task to be stored
        :raise InvalidNameException, TaskReaderNotFoundException, TaskNotFoundException
      
        Create or Update a temporary task file that is used to store the task data that is required for some plugins
        """
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_fs = self.get_task_fs(course.get_id(), taskid)

        task_file_manager = None

        try:
            for file_extension, file_manager in self._task_file_managers.items(
            ):
                if file_extension is "yaml":
                    task_file_manager = file_manager

        except:
            raise TaskReaderNotFoundException()

        if task_file_manager:
            temporal_task_file_content = task_file_manager.dump(data)

        try:
            task_fs.put("task_temp.yaml", temporal_task_file_content)
        except:
            raise TaskNotFoundException()
Пример #12
0
    def _cache_update_needed(self, course, taskid):
        """
        :param course: a Course object
        :param taskid: a (valid) task id
        :raise InvalidNameException, TaskNotFoundException
        :return: True if an update of the cache is needed, False else
        """
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_fs = self.get_task_fs(course.get_id(), taskid)

        if (course.get_id(), taskid) not in self._cache:
            return True

        try:
            last_update, __, __ = self._get_last_updates(
                course, taskid, task_fs, False)
        except:
            raise TaskNotFoundException()

        last_modif = self._cache[(course.get_id(), taskid)][1]
        for filename, mftime in last_update.items():
            if filename not in last_modif or last_modif[filename] < mftime:
                return True

        return False
Пример #13
0
    def get_temporal_task_file_content(self, course, taskid):
        """
        :param course: a Course object
        :param taskid: the task id of the task
        :raise InvalidNameException, TaskUnreadableException
        :return: the content of the temporary task file
        """

        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_file_manager = None

        task_fs = self.get_task_fs(course.get_id(), taskid)
        for file_extension, file_manager in self._task_file_managers.items():
            if task_fs.get("task_temp." + file_extension):
                task_file_manager = file_manager

        temporal_task_file_content = {}
        try:
            temporal_task_file_content["data"] = task_file_manager.load(
                task_fs.get("task_temp.yaml"))
        except Exception as e:
            raise TaskUnreadableException(str(e))

        return temporal_task_file_content
Пример #14
0
 def get_course_fs(self, courseid):
     """
     :param courseid: 
     :return: a FileSystemProvider pointing to the directory of the course 
     """
     if not id_checker(courseid):
         raise InvalidNameException("Course with invalid name: " + courseid)
     return self._filesystem.from_subfolder(courseid)
Пример #15
0
    def get_task_descriptor_content(self, courseid, taskid):
        """
        :param courseid: the course id of the course
        :param taskid: the task id of the task
        :raise InvalidNameException, TaskNotFoundException, TaskUnreadableException
        :return: the content of the task descriptor, as a dict
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        descriptor_path, descriptor_manager = self._get_task_descriptor_info(courseid, taskid)
        try:
            task_content = descriptor_manager.load(self.get_task_fs(courseid, taskid).get(descriptor_path))
        except Exception as e:
            raise TaskUnreadableException(str(e))
        return task_content
Пример #16
0
 def get_task_descriptor_content(self, courseid, taskid):
     """
     :param courseid: the course id of the course
     :param taskid: the task id of the task
     :raise InvalidNameException, TaskNotFoundException, TaskUnreadableException
     :return: the content of the task descriptor, as a dict
     """
     if not id_checker(courseid):
         raise InvalidNameException("Course with invalid name: " + courseid)
     if not id_checker(taskid):
         raise InvalidNameException("Task with invalid name: " + taskid)
     path_to_descriptor, _, descriptor_manager = self._get_task_descriptor_info(courseid, taskid)
     try:
         with codecs.open(path_to_descriptor, 'r', 'utf-8') as fd:
             task_content = descriptor_manager.load(fd.read())
     except Exception as e:
         raise TaskUnreadableException(str(e))
     return task_content
Пример #17
0
    def _get_task_descriptor_info(self, courseid, taskid):
        """
        :param courseid: the course id of the course
        :param taskid: the task id of the task
        :raise InvalidNameException, TaskNotFoundException
        :return: a tuple, containing:
            (descriptor filename,
             task file manager for the descriptor)
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_fs = self.get_task_fs(courseid, taskid)
        for ext, task_file_manager in self._task_file_managers.items():
            if task_fs.exists("task." + ext):
                return "task." + ext, task_file_manager

        raise TaskNotFoundException()
Пример #18
0
    def delete_task(self, courseid, taskid):
        """
        :param courseid: the course id of the course
        :param taskid: the task id of the task
        :raise InvalidNameException or CourseNotFoundException
        Erase the content of the task folder
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_directory = os.path.join(self._tasks_directory, courseid, taskid)

        if not os.path.exists(task_directory):
            raise TaskNotFoundException()

        shutil.rmtree(task_directory)

        get_course_logger(courseid).info("Task %s erased from the factory.", taskid)
Пример #19
0
 def get_course(self, courseid):
     """
     :param courseid: the course id of the course
     :raise InvalidNameException, CourseNotFoundException, CourseUnreadableException
     :return: an object representing the course, of the type given in the constructor
     """
     if not id_checker(courseid):
         raise InvalidNameException("Course with invalid name: " + courseid)
     if self._cache_update_needed(courseid):
         self._update_cache(courseid)
     return self._cache[courseid][0]
Пример #20
0
    def _get_task_descriptor_info(self, courseid, taskid):
        """
        :param courseid: the course id of the course
        :param taskid: the task id of the task
        :raise InvalidNameException, TaskNotFoundException
        :return: a tuple, containing:
            (the path to the descriptor of the task,
             extension of the descriptor,
             task file manager for the descriptor)
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)
        base_file = os.path.join(self._tasks_directory, courseid, taskid, "task")

        for ext, task_file_manager in self._task_file_managers.items():
            if os.path.isfile(base_file + "." + ext):
                return base_file + "." + ext, ext, task_file_manager

        raise TaskNotFoundException()
Пример #21
0
 def get_task(self, course, taskid):
     """
     :param course: a Course object
     :param taskid: the task id of the task
     :raise InvalidNameException, TaskNotFoundException, TaskUnreadableException
     :return: an object representing the task, of the type given in the constructor
     """
     if not id_checker(taskid):
         raise InvalidNameException("Task with invalid name: " + taskid)
     if self._cache_update_needed(course, taskid):
         self._update_cache(course, taskid)
     return self._cache[(course.get_id(), taskid)][0]
Пример #22
0
    def update_task_descriptor_content(self,
                                       courseid,
                                       taskid,
                                       content,
                                       force_extension=None):
        """
        Update the task descriptor with the dict in content
        :param courseid: the course id of the course
        :param taskid: the task id of the task
        :param content: the content to put in the task file
        :param force_extension: If None, save it the same format. Else, save with the given extension
        :raise InvalidNameException, TaskNotFoundException, TaskUnreadableException
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        if force_extension is None:
            path_to_descriptor, descriptor_manager = self._get_task_descriptor_info(
                courseid, taskid)
        elif force_extension in self.get_available_task_file_extensions():
            path_to_descriptor = "task." + force_extension
            descriptor_manager = self._task_file_managers[force_extension]
        else:
            raise TaskReaderNotFoundException()

        try:
            self.get_task_fs(courseid,
                             taskid).put(path_to_descriptor,
                                         descriptor_manager.dump(content))
        except:
            raise TaskNotFoundException()

        self._hook_manager.call_hook('task_updated',
                                     courseid=courseid,
                                     taskid=taskid,
                                     new_content=content)
Пример #23
0
 def _get_course_descriptor_path(self, courseid):
     """
     :param courseid: the course id of the course
     :raise InvalidNameException, CourseNotFoundException
     :return: the path to the descriptor of the course
     """
     if not id_checker(courseid):
         raise InvalidNameException("Course with invalid name: " + courseid)
     course_fs = self.get_course_fs(courseid)
     if course_fs.exists("course.yaml"):
         return courseid + "/course.yaml"
     if course_fs.exists("course.json"):
         return courseid + "/course.json"
     raise CourseNotFoundException()
Пример #24
0
 def _get_template_descriptor_path(self, courseid):
     """
     [Source code integration]: generalise with get_course_descriptor_path
     :param courseid: the course id of the course
     :raise InvalidNameException, CourseNotFoundException
     :return: the path to the description of the template
     """
     if not id_checker(courseid):
         raise InvalidNameException("Template with invalid name: " +
                                    courseid)
     course_fs = self.get_course_fs(courseid)
     if course_fs.exists("template.yaml"):
         return courseid + "/template.yaml"
     raise CourseNotFoundException()
Пример #25
0
    def delete_task(self, courseid, taskid):
        """
        :param courseid: the course id of the course
        :param taskid: the task id of the task
        :raise InvalidNameException or CourseNotFoundException
        Erase the content of the task folder
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_fs = self.get_task_fs(courseid, taskid)

        if not task_fs.exists():
            raise TaskNotFoundException()

        task_fs.delete()

        get_course_logger(courseid).info("Task %s erased from the factory.",
                                         taskid)
        self._hook_manager.call_hook('task_deleted',
                                     courseid=courseid,
                                     taskid=taskid)
Пример #26
0
def update_toc_content(course_factory, courseid, content):
    """
    Updates the content of the structure that describes the course
    :param course_factory: the course factory
    :param courseid: the course id of the course
    :param content: the new structure that replaces the old content
    :raise InvalidNameException, CourseNotFoundException
    """
    if not id_checker(courseid):
        raise InvalidNameException("Course with invalid name: " + courseid)

    get_sections_ids_and_make_unique(content)

    course_factory.get_course_fs(courseid).put(
        "toc.yaml", get_json_or_yaml("toc.yaml", content))
Пример #27
0
 def _get_course_descriptor_path(self, courseid):
     """
     :param courseid: the course id of the course
     :raise InvalidNameException, CourseNotFoundException
     :return: the path to the descriptor of the course
     """
     if not id_checker(courseid):
         raise InvalidNameException("Course with invalid name: " + courseid)
     base_file = os.path.join(self._tasks_directory, courseid, "course")
     if os.path.isfile(base_file + ".yaml"):
         return base_file + ".yaml"
     elif os.path.isfile(base_file + ".json"):
         return base_file + ".json"
     else:
         raise CourseNotFoundException()
Пример #28
0
    def get_temporal_task_file(self, course, taskid):
        """
        :param course: a Course object
        :param taskid: the task id of the task
        :raise InvalidNameException
        :return: the temporary task file in the task folder
        """
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_fs = self.get_task_fs(course.get_id(), taskid)
        try:
            temporal_task_file = task_fs.get("task_temp.yaml")
        except:
            temporal_task_file = None

        return temporal_task_file
Пример #29
0
    def _update_cache(self, course, taskid):
        """
        Updates the cache
        :param course: a Course object
        :param taskid: a (valid) task id
        :raise InvalidNameException, TaskNotFoundException, TaskUnreadableException
        """
        if not id_checker(taskid):
            raise InvalidNameException("Task with invalid name: " + taskid)

        task_fs = self.get_task_fs(course.get_id(), taskid)
        last_modif, translation_fs, task_content = self._get_last_updates(
            course, taskid, task_fs, True)

        self._cache[(course.get_id(), taskid)] = (self._task_class(
            course, taskid, task_content, task_fs, translation_fs,
            self._hook_manager, self._task_problem_types), last_modif)
Пример #30
0
    def delete_course(self, courseid):
        """
        :param courseid: the course id of the course
        :raise InvalidNameException or CourseNotFoundException
        Erase the content of the course folder
        """
        if not id_checker(courseid):
            raise InvalidNameException("Course with invalid name: " + courseid)

        course_fs = self.get_course_fs(courseid)

        if not course_fs.exists():
            raise CourseNotFoundException()

        course_fs.delete()

        get_course_logger(courseid).info("Course %s erased from the factory.",
                                         courseid)