Example #1
0
    def init_dest(self):
        if self.coursedir.course_id == '':
            self.fail("No course id specified. Re-run with --course flag.")
        if not self.authenticator.has_access(self.coursedir.student_id, self.coursedir.course_id):
            self.fail("You do not have access to this course.")

        self.inbound_path = os.path.join(self.root, self.coursedir.course_id, 'inbound')
        if not os.path.isdir(self.inbound_path):
            self.fail("Inbound directory doesn't exist: {}".format(self.inbound_path))
        if not check_mode(self.inbound_path, write=True, execute=True):
            self.fail("You don't have write permissions to the directory: {}".format(self.inbound_path))

        self.cache_path = os.path.join(self.cache, self.coursedir.course_id)
        if self.coursedir.student_id != '*':
            # An explicit student id has been specified on the command line; we use it as student_id
            if '*' in self.coursedir.student_id or '+' in self.coursedir.student_id:
                self.fail("The student ID should contain no '*' nor '+'; got {}".format(self.coursedir.student_id))
            student_id = self.coursedir.student_id
        else:
            student_id = get_username()
        if self.add_random_string:
            random_str = base64.urlsafe_b64encode(os.urandom(9)).decode('ascii')
            self.assignment_filename = '{}+{}+{}+{}'.format(
                student_id, self.coursedir.assignment_id, self.timestamp, random_str)
        else:
            self.assignment_filename = '{}+{}+{}'.format(
                student_id, self.coursedir.assignment_id, self.timestamp)
Example #2
0
 def init_dest(self):
     self.course_path = os.path.join(self.exchange_directory, self.course_id)
     self.inbound_path = os.path.join(self.course_path, 'inbound')
     self.assignment_filename = get_username() + '+' + self.assignment_id + '+' + self.timestamp
     self.dest_path = os.path.join(self.inbound_path, self.assignment_filename)
     if not os.path.isdir(self.inbound_path):
         self.fail("Inbound directory doesn't exist: {}".format(self.inbound_path))
     if not check_mode(self.inbound_path, write=True, execute=True):
         self.fail("You don't have write permissions to the directory: {}".format(self.inbound_path))
Example #3
0
 def init_dest(self):
     self.course_path = os.path.join(self.exchange_directory, self.course_id)
     self.inbound_path = os.path.join(self.course_path, 'inbound')
     self.assignment_filename = get_username() + '+' + self.assignment_id + '+' + self.timestamp
     self.dest_path = os.path.join(self.inbound_path, self.assignment_filename)
     if not os.path.isdir(self.inbound_path):
         self.fail("Inbound directory doesn't exist: {}".format(self.inbound_path))
     if not check_mode(self.inbound_path, write=True, execute=True):
         self.fail("You don't have write permissions to the directory: {}".format(self.inbound_path))
Example #4
0
    def init_dest(self):
        if self.course_id == '':
            self.fail("No course id specified. Re-run with --course flag.")

        self.inbound_path = os.path.join(self.exchange_directory, self.course_id, 'inbound')
        if not os.path.isdir(self.inbound_path):
            self.fail("Inbound directory doesn't exist: {}".format(self.inbound_path))
        if not check_mode(self.inbound_path, write=True, execute=True):
            self.fail("You don't have write permissions to the directory: {}".format(self.inbound_path))

        self.cache_path = os.path.join(self.cache_directory, self.course_id)
        self.assignment_filename = '{}+{}+{}'.format(get_username(), self.assignment_id, self.timestamp)
Example #5
0
    def init_dest(self):
        if self.coursedir.course_id == "":
            self.fail("No course id specified. Re-run with --course flag.")
        if not self.authenticator.has_access(
            self.coursedir.student_id, self.coursedir.course_id
        ):
            self.fail("You do not have access to this course.")

        self.inbound_path = os.path.join(
            self.root, self.coursedir.course_id, self.inbound_directory
        )

        if self.personalized_inbound:
            self.inbound_path = os.path.join(
                self.inbound_path, os.getenv("JUPYTERHUB_USER")
            )

            if not os.path.isdir(self.inbound_path):
                self.log.warning(
                    "Inbound directory doesn't exist, creating {}".format(
                        self.inbound_path
                    )
                )
                # 0777 with set GID so student instructors can read students' submissions
                self.ensure_directory(
                    self.inbound_path,
                    S_ISGID
                    | S_IRUSR
                    | S_IWUSR
                    | S_IXUSR
                    | S_IRGRP
                    | S_IWGRP
                    | S_IXGRP
                    | S_IROTH
                    | S_IWOTH
                    | S_IXOTH
                    | (S_IRGRP if self.coursedir.groupshared else 0),
                )

        if not os.path.isdir(self.inbound_path):
            self.fail("Inbound directory doesn't exist: {}".format(self.inbound_path))
        if not check_mode(self.inbound_path, write=True, execute=True):
            self.fail(
                "You don't have write permissions to the directory: {}".format(
                    self.inbound_path
                )
            )

        self.cache_path = os.path.join(self.cache, self.coursedir.course_id)
        if self.coursedir.student_id != "*":
            # An explicit student id has been specified on the command line; we use it as student_id
            if "*" in self.coursedir.student_id or "+" in self.coursedir.student_id:
                self.fail(
                    "The student ID should contain no '*' nor '+'; got {}".format(
                        self.coursedir.student_id
                    )
                )
            student_id = self.coursedir.student_id
        else:
            student_id = get_username()
        if self.add_random_string:
            random_str = base64.urlsafe_b64encode(os.urandom(9)).decode("ascii")
            self.assignment_filename = "{}+{}+{}+{}".format(
                student_id, self.coursedir.assignment_id, self.timestamp, random_str
            )
        else:
            self.assignment_filename = "{}+{}+{}".format(
                student_id, self.coursedir.assignment_id, self.timestamp
            )
Example #6
0
    def copy_files(self):
        self.init_release()

        hashcode = "No hashcode present"

        # Original notebook file
        student_notebook_file = os.path.join(
            self.src_path, f"{self.coursedir.assignment_id}.ipynb"
        )

        if os.path.isfile(student_notebook_file):
            nb = nbformat.read(student_notebook_file, as_version=4)
            nb = append_timestamp(nb, self.timestamp)
            nbformat.write(nb, student_notebook_file)
            hashcode = truncate_hashcode(
                compute_hashcode(student_notebook_file, method="sha1")
            )

            username = get_username()
            generate_student_info(
                os.path.join(self.src_path, f"{username}_info.txt"),
                username,
                hashcode,
                self.timestamp,
            )
            nb = append_hashcode(nb, hashcode)
            generate_html(
                nb,
                os.path.join(
                    self.src_path, f"{self.coursedir.assignment_id}_hashcode.html"
                ),
            )
        else:
            self.log.warning(
                "Can not generate hashcode, notebook and assignment name does not match."
            )

        dest_path = os.path.join(self.inbound_path, self.assignment_filename)
        if self.add_random_string:
            cache_path = os.path.join(
                self.cache_path, self.assignment_filename.rsplit("+", 1)[0]
            )
        else:
            cache_path = os.path.join(self.cache_path, self.assignment_filename)

        self.log.info("Source: {}".format(self.src_path))
        self.log.info("Destination: {}".format(dest_path))

        # copy to the real location
        self.check_filename_diff()
        self.do_copy(self.src_path, dest_path)
        with open(os.path.join(dest_path, "timestamp.txt"), "w") as fh:
            fh.write(self.timestamp)
        self.set_perms(
            dest_path,
            fileperms=(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH),
            dirperms=(
                S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
            ),
        )

        # Make this 0777=ugo=rwx so the instructor can delete later. Hidden from other users by the timestamp.
        os.chmod(
            dest_path,
            S_IRUSR
            | S_IWUSR
            | S_IXUSR
            | S_IRGRP
            | S_IWGRP
            | S_IXGRP
            | S_IROTH
            | S_IWOTH
            | S_IXOTH,
        )

        # also copy to the cache
        if not os.path.isdir(self.cache_path):
            os.makedirs(self.cache_path)
        self.do_copy(self.src_path, cache_path)
        with open(os.path.join(cache_path, "timestamp.txt"), "w") as fh:
            fh.write(self.timestamp)

        self.log.info(
            "Submitted as: {} {} {}".format(
                self.coursedir.course_id,
                self.coursedir.assignment_id,
                str(self.timestamp),
            )
        )

        return hashcode, self.timestamp
Example #7
0
    def init_src(self):
        if self.coursedir.course_id == "":
            self.fail("No course id specified. Re-run with --course flag.")

        self.course_path = os.path.join(self.root, self.coursedir.course_id)
        self.outbound_path = os.path.join(self.course_path,
                                          self.feedback_directory)
        self.src_path = os.path.join(self.outbound_path)
        self.cache_path = os.path.join(self.cache, self.coursedir.course_id)

        if self.coursedir.student_id != "*":
            # An explicit student id has been specified on the command line; we use it as student_id
            if "*" in self.coursedir.student_id or "+" in self.coursedir.student_id:
                self.fail(
                    "The student ID should contain no '*' nor '+'; got {}".
                    format(self.coursedir.student_id))
            student_id = self.coursedir.student_id
        else:
            student_id = get_username()

        if not os.path.isdir(self.src_path):
            self._assignment_not_found(self.src_path,
                                       os.path.join(self.outbound_path, "*"))
        if not check_mode(self.src_path, execute=True):
            self.fail(
                "You don't have execute permissions for the directory: {}".
                format(self.src_path))

        assignment_id = (self.coursedir.assignment_id
                         if self.coursedir.assignment_id else "*")
        pattern = os.path.join(self.cache_path, "*+{}+*".format(assignment_id))
        self.log.debug(
            "Looking for submissions with pattern: {}".format(pattern))

        self.feedback_files = []
        submissions = [os.path.split(x)[-1] for x in glob.glob(pattern)]
        for submission in submissions:
            _, assignment_id, timestamp = submission.split("/")[-1].split("+")

            self.log.debug(
                "Looking for feedback for '{}/{}' submitted at {}".format(
                    self.coursedir.course_id, assignment_id, timestamp))

            pattern = os.path.join(self.cache_path, submission, "*.ipynb")
            notebooks = glob.glob(pattern)
            for notebook in notebooks:
                notebook_id = os.path.splitext(os.path.split(notebook)[-1])[0]

                # Check if personalized_feedback is used
                if self.personalized_feedback:
                    feedbackpath = os.path.join(
                        self.outbound_path,
                        student_id,
                        assignment_id,
                        "{}.html".format(notebook_id),
                    )
                    self.log.debug("Feedback file: ", feedbackpath)
                    if os.path.exists(feedbackpath):
                        self.feedback_files.append(
                            (notebook_id, timestamp, feedbackpath))
                        self.log.info(
                            "Found feedback for '{}/{}/{}' submitted at {}".
                            format(
                                self.coursedir.course_id,
                                assignment_id,
                                notebook_id,
                                timestamp,
                            ))
                        continue

                    # If we reached here, then there's no feedback available
                    self.log.warning(
                        "Could not find feedback for '{}/{}/{}' submitted at {}"
                        .format(
                            self.coursedir.course_id,
                            assignment_id,
                            notebook_id,
                            timestamp,
                        ))
                else:
                    unique_key = make_unique_key(
                        self.coursedir.course_id,
                        assignment_id,
                        notebook_id,
                        student_id,
                        timestamp,
                    )

                    # Look for the feedback using new-style of feedback
                    self.log.debug("Unique key is: {}".format(unique_key))
                    nb_hash = notebook_hash(notebook, unique_key)
                    feedbackpath = os.path.join(self.outbound_path,
                                                "{0}.html".format(nb_hash))
                    if os.path.exists(feedbackpath):
                        self.feedback_files.append(
                            (notebook_id, timestamp, feedbackpath))
                        self.log.info(
                            "Found feedback for '{}/{}/{}' submitted at {}".
                            format(
                                self.coursedir.course_id,
                                assignment_id,
                                notebook_id,
                                timestamp,
                            ))
                        continue

                    # If it doesn't exist, try the legacy hashing
                    nb_hash = notebook_hash(notebook)
                    feedbackpath = os.path.join(self.outbound_path,
                                                "{0}.html".format(nb_hash))
                    if os.path.exists(feedbackpath):
                        self.feedback_files.append(
                            (notebook_id, timestamp, feedbackpath))
                        self.log.warning(
                            "Found legacy feedback for '{}/{}/{}' submitted at {}"
                            .format(
                                self.coursedir.course_id,
                                assignment_id,
                                notebook_id,
                                timestamp,
                            ))
                        continue

                    # If we reached here, then there's no feedback available
                    self.log.warning(
                        "Could not find feedback for '{}/{}/{}' submitted at {}"
                        .format(
                            self.coursedir.course_id,
                            assignment_id,
                            notebook_id,
                            timestamp,
                        ))
Example #8
0
from nbgrader.utils import get_username

c = get_config()

c.NbGrader.course_id = "demo"
c.NbGrader.db_assignments = [dict(name="ps1")]
c.NbGrader.db_students = [dict(id=get_username())]