def save_notebook(self, model, name, path=''):
        """Save the notebook model and return the model with no content."""

        self.log.debug("save_notebook(%s, '%s', '%s')",
                       model, str(name), str(path))
        assert name.endswith(self.filename_ext)
        path = path.strip('/')

        if 'content' not in model:
            raise web.HTTPError(400, u'No notebook JSON data provided')
        
        # One checkpoint should always exist
        if self.notebook_exists(name, path) \
           and not self.list_checkpoints(name, path):
            self.create_checkpoint(name, path)

        new_path = model.get('path', path)
        new_name = model.get('name', name)

        if path != new_path or name != new_name:
            self._rename_notebook(name, path, new_name, new_path)

        # Create the path and notebook entries if necessary
        if new_path not in self.tree:
            self.tree[new_path] = {}
        if new_name not in self.tree[new_path]:
            self.tree[new_path][new_name] = \
                   dict(created = tz.utcnow(), checkpoints=[])
        notebook = self.tree[new_path][new_name]

        # Save the notebook file
        nb = current.to_notebook_json(model['content'])
        self.check_and_sign(nb, new_path, new_name)
        if 'name' in nb['metadata']:
            nb['metadata']['name'] = u''
        ipynb_stream = StringIO()
        current.write(nb, ipynb_stream, u'json')
        notebook['ipynb'] = ipynb_stream.getvalue()
        notebook['ipynb_last_modified'] = tz.utcnow()
        ipynb_stream.close()

        # Save .py script as well
        py_stream = StringIO()
        current.write(nb, py_stream, u'json')
        notebook['py'] = py_stream.getvalue()
        notebook['py_last_modified'] = tz.utcnow()
        py_stream.close()

        # Return model
        model = self.get_notebook(new_name, new_path, content=False)
        self.log.debug("save_notebook -> %s", model)
        return model
Exemplo n.º 2
0
 def _base_model(self, path):
     """Build the common base of a contents model"""
     last_modified = tz.utcnow()
     created = tz.utcnow()
     # Create the base model.
     model = {}
     model['name'] = path.rsplit('/', 1)[-1]
     model['path'] = path
     model['last_modified'] = last_modified
     model['created'] = created
     model['content'] = None
     model['format'] = None
     model['mimetype'] = None
     model['writable'] = True
     return model
Exemplo n.º 3
0
 def _base_model(self, path):
     """Build the common base of a contents model"""
     last_modified = tz.utcnow()
     created = tz.utcnow()
     # Create the base model.
     model = {}
     model['name'] = path.rsplit('/', 1)[-1]
     model['path'] = path
     model['last_modified'] = last_modified
     model['created'] = created
     model['content'] = None
     model['format'] = None
     model['mimetype'] = None
     model['writable'] = True
     return model
Exemplo n.º 4
0
def test_date_default():
    data = dict(today=datetime.datetime.now(), utcnow=tz.utcnow())
    jsondata = json.dumps(data, default=jsonutil.date_default)
    nt.assert_in("+00", jsondata)
    nt.assert_equal(jsondata.count("+00"), 1)
    extracted = jsonutil.extract_dates(json.loads(jsondata))
    for dt in list(extracted.values()):
        nt.assert_true(isinstance(dt, datetime.datetime))
Exemplo n.º 5
0
def test_date_default():
    data = dict(today=datetime.datetime.now(), utcnow=tz.utcnow())
    jsondata = json.dumps(data, default=jsonutil.date_default)
    nt.assert_in("+00", jsondata)
    nt.assert_equal(jsondata.count("+00"), 1)
    extracted = jsonutil.extract_dates(json.loads(jsondata))
    for dt in extracted.values():
        nt.assert_true(isinstance(dt, datetime.datetime))
Exemplo n.º 6
0
 def _base_model(self, path):
     """Build the common base of a contents model"""
     # http://jupyter-notebook.readthedocs.io/en/stable/extending/contents.html
     path = path.strip('/')
     last_modified = tz.utcnow()
     created = tz.utcnow()
     # Create the base model.
     model = {}
     model['name'] = path.rsplit('/', 1)[-1]
     model['path'] = path
     model['last_modified'] = last_modified
     model['created'] = created
     model['content'] = None
     model['format'] = None
     model['mimetype'] = None
     model['writable'] = True
     return model
Exemplo n.º 7
0
 def _base_model(self, path, kind=None):
     """Build the common base of a contents model"""
     # http://jupyter-notebook.readthedocs.io/en/stable/extending/contents.html
     from IPython.utils import tz
     path = unquote(path).strip('/')
     last_modified = tz.utcnow()
     created = tz.utcnow()
     # Create the base model.
     model = {}
     model['name'] = os.path.basename(path)
     model['path'] = path
     model['last_modified'] = last_modified
     model['created'] = created
     model['content'] = None
     model['format'] = None
     model['mimetype'] = None
     model['writable'] = True
     if kind:
         model['type'] = kind
         model['content'] = [] if kind == 'directory' else None
     return model
 def get_dir_model(self, name, path=''):
     """Get the directory model given a directory name and its API style path.
     
     The keys in the model should be:
     * name
     * path
     * last_modified
     * created
     * type='directory'
     """
     if not self.path_exists(path):
         raise IOError('directory does not exist: %r' % path)
     # Create the directory model.
     model ={}
     model['name'] = name
     model['path'] = path.strip('/')
     model['last_modified'] = tz.utcnow()
     model['created'] = tz.utcnow()
     model['type'] = 'directory'
     self.log.debug("get_dir_model('%s', '%s') -> %s",
                    name, path, str(model))
     return model
Exemplo n.º 9
0
 def _rename_notebook(self, old_name, new_name):
     if old_name not in self.nb_list:
         raise web.HTTPError(400, u"Unavailable Notebook: %s" % (old_name))
     # update attributes
     attr = self.nb_list[old_name]['attributes']
     attr['name'] = self._strip_ext(new_name)
     attr['last_modified'] = tz.utcnow().isoformat()
     attr_str = json.dumps(attr)
     # update in shock
     try:
         node = self._update_shock_node(self.nb_list[old_name]['id'], attr_str)
     except Exception as e:
         raise web.HTTPError(400, u'Unexpected error while renaming notebook: %s' %e)
     # update listing
     del self.nb_list[old_name]
     self.nb_list[new_name] = node
Exemplo n.º 10
0
 def _delete_notebook(self, os_path, name):
     if name not in self.nb_list:
         raise web.HTTPError(400, u"Unavailable Notebook: %s" % (name))
     # set as deleted in shock
     attr = self.nb_list[name]['attributes']
     attr['deleted'] = 1
     attr['last_modified'] = tz.utcnow().isoformat()
     attr_str = json.dumps(attr)
     try:
         self.log.debug("Deleting %s from Shock", name)
         node = self._update_shock_node(self.nb_list[name]['id'], attr_str)
     except Exception as e:
         raise web.HTTPError(400, u'Unexpected error while deleting notebook: %s' %e)
     # delete from listing
     del self.nb_list[name]
     os.unlink(os_path)
Exemplo n.º 11
0
 def read_notebook_object(self, notebook_id):
     """Get the object representation of a notebook by notebook_id."""
     if not self.notebook_exists(notebook_id):
         raise web.HTTPError(404, u'Notebook does not exist: %s' % notebook_id)
     try:
         s = self.blob_service.get_blob(self.container, notebook_id)
     except:
         raise web.HTTPError(500, u'Notebook cannot be read.')
     try:
         # v1 and v2 and json in the .ipynb files.
         nb = current.reads(s, u'json')
     except:
         raise web.HTTPError(500, u'Unreadable JSON notebook.')
     # Todo: The last modified should actually be saved in the notebook document.
     # We are just using the current datetime until that is implemented.
     last_modified = tz.utcnow()
     return last_modified, nb
Exemplo n.º 12
0
 def read_notebook_object(self, notebook_id):
     """Get the object representation of a notebook by notebook_id."""
     if not self.notebook_exists(notebook_id):
         raise web.HTTPError(404,
                             u'Notebook does not exist: %s' % notebook_id)
     try:
         s = self.blob_service.get_blob(self.container, notebook_id)
     except:
         raise web.HTTPError(500, u'Notebook cannot be read.')
     try:
         # v1 and v2 and json in the .ipynb files.
         nb = current.reads(s, u'json')
     except:
         raise web.HTTPError(500, u'Unreadable JSON notebook.')
     # Todo: The last modified should actually be saved in the notebook document.
     # We are just using the current datetime until that is implemented.
     last_modified = tz.utcnow()
     return last_modified, nb
Exemplo n.º 13
0
    def read_notebook_object(self, notebook_id):
        """Get the object representation of a notebook by notebook_id."""
        if not self.notebook_exists(notebook_id):
            raise web.HTTPError(404, NB_DNEXIST_ERR.format(notebook_id))
        try:
            obj = self.container.get_object(notebook_id)

            # Read in the entire notebook file into s
            s = obj.get()
        except:
            raise web.HTTPError(500, "Notebook cannot be read.")
        try:
            nb = current.reads(s, "json")
        except:
            raise web.HTTPError(500, "Unreadable JSON notebook.")

        last_modified = utcnow()
        return last_modified, nb
Exemplo n.º 14
0
    def read_notebook_object(self, notebook_id):
        """Get the object representation of a notebook by notebook_id."""
        if not self.notebook_exists(notebook_id):
            raise web.HTTPError(404, NB_DNEXIST_ERR.format(notebook_id))
        try:
            obj = self.container.get_object(notebook_id)

            # Read in the entire notebook file into s
            s = obj.get()
        except:
            raise web.HTTPError(500, 'Notebook cannot be read.')
        try:
            nb = current.reads(s, 'json')
        except:
            raise web.HTTPError(500, 'Unreadable JSON notebook.')

        last_modified = utcnow()
        return last_modified, nb
Exemplo n.º 15
0
    def create_checkpoint(self, notebook_id):
        """Create a checkpoint of the current state of a notebook

        Returns a dictionary with a checkpoint_id and the timestamp from the
        last modification
        """

        self.log.info("Creating checkpoint for notebook {}".format(notebook_id))

        # We pull the next available checkpoint id (1UP)
        checkpoints = self.container.get_objects(prefix=(notebook_id + "/"))

        checkpoint_id = self.new_checkpoint_id()

        checkpoint_path = self.get_checkpoint_path(notebook_id, checkpoint_id)

        last_modified = utcnow()

        metadata = {
            METADATA_CHK_ID: checkpoint_id,
            METADATA_LAST_MODIFIED: last_modified.strftime(DATE_FORMAT),
            METADATA_NB_ID: notebook_id,
        }
        try:
            self.log.info("Copying notebook {} to {}".format(notebook_id, checkpoint_path))
            self.cf.copy_object(
                container=self.container_name,
                obj=notebook_id,
                new_container=self.container_name,
                new_obj_name=checkpoint_path,
            )

            obj = self.container.get_object(checkpoint_path)
            obj.set_metadata(metadata)

        except Exception as e:
            raise web.HTTPError(400, CHK_SAVE_UNK_ERR.format(e))

        info = dict(checkpoint_id=checkpoint_id, last_modified=last_modified)

        return info
Exemplo n.º 16
0
    def create_checkpoint(self, notebook_id):
        """Create a checkpoint of the current state of a notebook

        Returns a dictionary with a checkpoint_id and the timestamp from the
        last modification
        """

        self.log.info(
            "Creating checkpoint for notebook {}".format(notebook_id))

        # We pull the next available checkpoint id (1UP)
        checkpoints = self.container.get_objects(prefix=(notebook_id + "/"))

        checkpoint_id = self.new_checkpoint_id()

        checkpoint_path = self.get_checkpoint_path(notebook_id, checkpoint_id)

        last_modified = utcnow()

        metadata = {
            METADATA_CHK_ID: checkpoint_id,
            METADATA_LAST_MODIFIED: last_modified.strftime(DATE_FORMAT),
            METADATA_NB_ID: notebook_id
        }
        try:
            self.log.info("Copying notebook {} to {}".format(
                notebook_id, checkpoint_path))
            self.cf.copy_object(container=self.container_name,
                                obj=notebook_id,
                                new_container=self.container_name,
                                new_obj_name=checkpoint_path)

            obj = self.container.get_object(checkpoint_path)
            obj.set_metadata(metadata)

        except Exception as e:
            raise web.HTTPError(400, CHK_SAVE_UNK_ERR.format(e))

        info = dict(checkpoint_id=checkpoint_id, last_modified=last_modified)

        return info
Exemplo n.º 17
0
 def _save_notebook(self, os_path, model, path):
     """save a notebook to shock"""
     # Get name
     name = path.rsplit('/', 1)[-1]
     # Get attributes
     attr = {}
     attr['name'] = self._strip_ext(name)
     attr['type'] = self.node_type
     attr['format'] = 'json'
     attr['last_modified'] = tz.utcnow().isoformat()
     # creation timestamp
     if 'created' in model:
         attr['created'] = model['created'].isoformat()
     elif name in self.nb_list:
         attr['created'] = self.nb_list[name]['attributes']['created']
     else:
         attr['created'] = attr['last_modified']
     # original id
     if name in self.nb_list:
         attr['original'] = self.nb_list[name]['attributes']['original']
     else:
         attr['original'] = str(uuid.uuid4())
     attr_str = json.dumps(attr)
     # Get the notebook content
     nb = nbformat.from_dict(model['content'])
     self.check_and_sign(nb, name)
     nb_str = nbformat.writes(nb, version=nbformat.NO_CONVERT)
     # Save to shock
     try:
         self.log.debug("Saving %s to Shock", name)
         node = self._post_shock_node(name, nb_str, attr_str)
     except Exception as e:
         raise web.HTTPError(400, u'Unexpected error while saving notebook: %s' %e)
     # update lists
     self.nb_list[name] = node
     open(os_path, 'w').close()