def init_assignment(self, assignment_id, student_id): super(AutogradeApp, self).init_assignment(assignment_id, student_id) # try to get the student from the database, and throw an error if it # doesn't exist gb = Gradebook(self.db_url) try: gb.find_student(student_id) except MissingEntry: if self.create_student: self.log.warning("Creating student with ID '%s'", student_id) gb.add_student(student_id) else: self.fail("No student with ID '%s' exists in the database", student_id) # try to read in a timestamp from file src_path = self._format_source(assignment_id, student_id) timestamp = self._get_existing_timestamp(src_path) if timestamp: submission = gb.update_or_create_submission( assignment_id, student_id, timestamp=timestamp) self.log.info("%s submitted at %s", submission, timestamp) # if the submission is late, print out how many seconds late it is if timestamp and submission.total_seconds_late > 0: self.log.warning("%s is %s seconds late", submission, submission.total_seconds_late) else: submission = gb.update_or_create_submission(assignment_id, student_id) # copy files over from the source directory self.log.info("Overwriting files with master versions from the source directory") dest_path = self._format_dest(assignment_id, student_id) source_path = self.directory_structure.format( nbgrader_step=self.source_directory, student_id='.', assignment_id=assignment_id) source_files = utils.find_all_files(source_path, self.ignore + ["*.ipynb"]) # copy them to the build directory for filename in source_files: dest = os.path.join(dest_path, os.path.relpath(filename, source_path)) ensure_dir_exists(os.path.dirname(dest)) if not os.path.normpath(dest) == os.path.normpath(filename): self.log.info("Linking %s -> %s", filename, dest) link_or_copy(filename, dest) # ignore notebooks that aren't in the database notebooks = [] for notebook in self.notebooks: notebook_id = os.path.splitext(os.path.basename(notebook))[0] try: gb.find_notebook(notebook_id, assignment_id) except MissingEntry: self.log.warning("Skipping unknown notebook: %s", notebook) continue else: notebooks.append(notebook) self.notebooks = notebooks
def test_link_twice(self): # Linking the same file twice shouldn't leave duplicates around. # See https://github.com/ipython/ipython/issues/6450 dst = self.dst('target') path.link_or_copy(self.src, dst) path.link_or_copy(self.src, dst) self.assert_inode_equal(self.src, dst) nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target'])
def test_no_link(self): real_link = os.link try: del os.link dst = self.dst("target") path.link_or_copy(self.src, dst) self.assert_content_equal(self.src, dst) self.assert_inode_not_equal(self.src, dst) finally: os.link = real_link
def write(self, output, resources, notebook_name=None, **kw): """ Consume and write Jinja output to the file system. Output directory is set via the 'build_directory' variable of this instance (a configurable). See base for more... """ # Pull the extension and subdir from the resources dict. output_extension = resources['output_extension'] # Write all of the extracted resources to the destination directory. # NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG # TRANSFORMER SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS... for filename, data in resources.get('outputs', {}).items(): # Determine where to write the file to dest = os.path.join(self.build_directory, filename) path = os.path.dirname(dest) self._makedir(path) # Write file self.log.debug("Writing %i bytes to support file %s", len(data), dest) with io.open(dest, 'wb') as f: f.write(data) # Copy referenced files to output directory if self.build_directory: for filename in self.files: # Copy files that match search pattern for matching_filename in glob.glob(filename): # Make sure folder exists. dest = os.path.join(self.build_directory, filename) path = os.path.dirname(dest) self._makedir(path) # Copy if destination is different. if not os.path.normpath(dest) == os.path.normpath(matching_filename): self.log.info("Linking %s -> %s", matching_filename, dest) link_or_copy(matching_filename, dest) # Determine where to write conversion results. dest = notebook_name + '.' + output_extension if self.build_directory: dest = os.path.join(self.build_directory, dest) # Write conversion results. self.log.info("Writing %i bytes to %s", len(output), dest) with io.open(dest, 'w') as f: f.write(output) return dest
def init_assignment(self, assignment_id, student_id): """Initializes resources/dependencies/etc. that are common to all notebooks in an assignment. """ source = self._format_source(assignment_id, student_id) dest = self._format_dest(assignment_id, student_id) # detect other files in the source directory for filename in find_all_files(source, self.ignore + ["*.ipynb"]): # Make sure folder exists. path = os.path.join(dest, os.path.relpath(filename, source)) ensure_dir_exists(os.path.dirname(path)) # Copy if destination is different. if not os.path.normpath(path) == os.path.normpath(filename): self.log.info("Linking %s -> %s", filename, path) link_or_copy(filename, path)
def test_link_successful(self): dst = self.dst("target") path.link_or_copy(self.src, dst) self.assert_inode_equal(self.src, dst)
def test_target_exists(self): dst = self.dst("target") open(dst, "w").close() path.link_or_copy(self.src, dst) self.assert_inode_equal(self.src, dst)
def test_link_into_dir(self): dst = self.dst("some_dir") os.mkdir(dst) path.link_or_copy(self.src, dst) expected_dst = self.dst("some_dir", os.path.basename(self.src)) self.assert_inode_equal(self.src, expected_dst)
def test_windows(self): dst = self.dst("target") path.link_or_copy(self.src, dst) self.assert_content_equal(self.src, dst)
def write(self, output, resources, notebook_name=None, **kw): """ Consume and write Jinja output to the file system. Output directory is set via the 'build_directory' variable of this instance (a configurable). See base for more... """ # Verify that a notebook name is provided. if notebook_name is None: raise TypeError('notebook_name') # Pull the extension and subdir from the resources dict. output_extension = resources.get('output_extension', None) # Write all of the extracted resources to the destination directory. # NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG # PREPROCESSOR SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS... for filename, data in resources.get('outputs', {}).items(): # Determine where to write the file to dest = os.path.join(self.build_directory, filename) path = os.path.dirname(dest) self._makedir(path) # Write file self.log.debug("Writing %i bytes to support file %s", len(data), dest) with io.open(dest, 'wb') as f: f.write(data) # Copy referenced files to output directory if self.build_directory: for filename in self.files: # Copy files that match search pattern for matching_filename in glob.glob(filename): # Make sure folder exists. dest = os.path.join(self.build_directory, matching_filename) path = os.path.dirname(dest) self._makedir(path) # Copy if destination is different. if not os.path.normpath(dest) == os.path.normpath(matching_filename): self.log.info("Linking %s -> %s", matching_filename, dest) link_or_copy(matching_filename, dest) # Determine where to write conversion results. if output_extension is not None: dest = notebook_name + '.' + output_extension else: dest = notebook_name if self.build_directory: dest = os.path.join(self.build_directory, dest) # Write conversion results. self.log.info("Writing %i bytes to %s", len(output), dest) if isinstance(output, unicode_type): with io.open(dest, 'w', encoding='utf-8') as f: f.write(output) else: with io.open(dest, 'wb') as f: f.write(output) return dest
def write(self, output, resources, notebook_name=None, **kw): """ Consume and write Jinja output to the file system. Output directory is set via the 'build_directory' variable of this instance (a configurable). See base for more... """ # Verify that a notebook name is provided. if notebook_name is None: raise TypeError('notebook_name') # Pull the extension and subdir from the resources dict. output_extension = resources.get('output_extension', None) # Get the relative path for copying files if self.relpath == '': relpath = resources.get('metadata', {}).get('path', '') else: relpath = self.relpath # Write all of the extracted resources to the destination directory. # NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG # PREPROCESSOR SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS... items = resources.get('outputs', {}).items() if items: self.log.info("Support files will be in %s", os.path.join(resources.get('output_files_dir',''), '')) for filename, data in items: # Determine where to write the file to dest = os.path.join(self.build_directory, filename) path = os.path.dirname(dest) self._makedir(path) # Write file self.log.debug("Writing %i bytes to support file %s", len(data), dest) with io.open(dest, 'wb') as f: f.write(data) # Copy referenced files to output directory if self.build_directory: for filename in self.files: # Copy files that match search pattern for matching_filename in glob.glob(filename): # compute the relative path for the filename if relpath != '': dest_filename = os.path.relpath(matching_filename, relpath) else: dest_filename = matching_filename # Make sure folder exists. dest = os.path.join(self.build_directory, dest_filename) path = os.path.dirname(dest) self._makedir(path) # Copy if destination is different. if not os.path.normpath(dest) == os.path.normpath(matching_filename): self.log.info("Linking %s -> %s", matching_filename, dest) link_or_copy(matching_filename, dest) # Determine where to write conversion results. if output_extension is not None: dest = notebook_name + output_extension else: dest = notebook_name if self.build_directory: dest = os.path.join(self.build_directory, dest) # Write conversion results. self.log.info("Writing %i bytes to %s", len(output), dest) if isinstance(output, unicode_type): with io.open(dest, 'w', encoding='utf-8') as f: f.write(output) else: with io.open(dest, 'wb') as f: f.write(output) return dest
def init_assignment(self, assignment_id, student_id): super(AutogradeApp, self).init_assignment(assignment_id, student_id) # try to get the student from the database, and throw an error if it # doesn't exist gb = Gradebook(self.db_url) try: gb.find_student(student_id) except MissingEntry: if self.create_student: self.log.warning("Creating student with ID '%s'", student_id) gb.add_student(student_id) else: self.fail("No student with ID '%s' exists in the database", student_id) # try to read in a timestamp from file src_path = self._format_source(assignment_id, student_id) timestamp = self._get_existing_timestamp(src_path) if timestamp: submission = gb.update_or_create_submission(assignment_id, student_id, timestamp=timestamp) self.log.info("%s submitted at %s", submission, timestamp) # if the submission is late, print out how many seconds late it is if timestamp and submission.total_seconds_late > 0: self.log.warning("%s is %s seconds late", submission, submission.total_seconds_late) else: submission = gb.update_or_create_submission( assignment_id, student_id) # copy files over from the source directory self.log.info( "Overwriting files with master versions from the source directory") dest_path = self._format_dest(assignment_id, student_id) source_path = self.directory_structure.format( nbgrader_step=self.source_directory, student_id='.', assignment_id=assignment_id) source_files = utils.find_all_files(source_path, self.ignore + ["*.ipynb"]) # copy them to the build directory for filename in source_files: dest = os.path.join(dest_path, os.path.relpath(filename, source_path)) ensure_dir_exists(os.path.dirname(dest)) if not os.path.normpath(dest) == os.path.normpath(filename): self.log.info("Linking %s -> %s", filename, dest) link_or_copy(filename, dest) # ignore notebooks that aren't in the database notebooks = [] for notebook in self.notebooks: notebook_id = os.path.splitext(os.path.basename(notebook))[0] try: gb.find_notebook(notebook_id, assignment_id) except MissingEntry: self.log.warning("Skipping unknown notebook: %s", notebook) continue else: notebooks.append(notebook) self.notebooks = notebooks