You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			256 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			256 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Python
		
	
"""
 | 
						|
Classes for managing Checkpoints.
 | 
						|
"""
 | 
						|
 | 
						|
# Copyright (c) Jupyter Development Team.
 | 
						|
# Distributed under the terms of the Modified BSD License.
 | 
						|
from tornado.web import HTTPError
 | 
						|
from traitlets.config.configurable import LoggingConfigurable
 | 
						|
 | 
						|
 | 
						|
class Checkpoints(LoggingConfigurable):
 | 
						|
    """
 | 
						|
    Base class for managing checkpoints for a ContentsManager.
 | 
						|
 | 
						|
    Subclasses are required to implement:
 | 
						|
 | 
						|
    create_checkpoint(self, contents_mgr, path)
 | 
						|
    restore_checkpoint(self, contents_mgr, checkpoint_id, path)
 | 
						|
    rename_checkpoint(self, checkpoint_id, old_path, new_path)
 | 
						|
    delete_checkpoint(self, checkpoint_id, path)
 | 
						|
    list_checkpoints(self, path)
 | 
						|
    """
 | 
						|
 | 
						|
    def create_checkpoint(self, contents_mgr, path):
 | 
						|
        """Create a checkpoint."""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    def restore_checkpoint(self, contents_mgr, checkpoint_id, path):
 | 
						|
        """Restore a checkpoint"""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    def rename_checkpoint(self, checkpoint_id, old_path, new_path):
 | 
						|
        """Rename a single checkpoint from old_path to new_path."""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    def delete_checkpoint(self, checkpoint_id, path):
 | 
						|
        """delete a checkpoint for a file"""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    def list_checkpoints(self, path):
 | 
						|
        """Return a list of checkpoints for a given file"""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    def rename_all_checkpoints(self, old_path, new_path):
 | 
						|
        """Rename all checkpoints for old_path to new_path."""
 | 
						|
        for cp in self.list_checkpoints(old_path):
 | 
						|
            self.rename_checkpoint(cp["id"], old_path, new_path)
 | 
						|
 | 
						|
    def delete_all_checkpoints(self, path):
 | 
						|
        """Delete all checkpoints for the given path."""
 | 
						|
        for checkpoint in self.list_checkpoints(path):
 | 
						|
            self.delete_checkpoint(checkpoint["id"], path)
 | 
						|
 | 
						|
 | 
						|
class GenericCheckpointsMixin:
 | 
						|
    """
 | 
						|
    Helper for creating Checkpoints subclasses that can be used with any
 | 
						|
    ContentsManager.
 | 
						|
 | 
						|
    Provides a ContentsManager-agnostic implementation of `create_checkpoint`
 | 
						|
    and `restore_checkpoint` in terms of the following operations:
 | 
						|
 | 
						|
    - create_file_checkpoint(self, content, format, path)
 | 
						|
    - create_notebook_checkpoint(self, nb, path)
 | 
						|
    - get_file_checkpoint(self, checkpoint_id, path)
 | 
						|
    - get_notebook_checkpoint(self, checkpoint_id, path)
 | 
						|
 | 
						|
    To create a generic CheckpointManager, add this mixin to a class that
 | 
						|
    implement the above four methods plus the remaining Checkpoints API
 | 
						|
    methods:
 | 
						|
 | 
						|
    - delete_checkpoint(self, checkpoint_id, path)
 | 
						|
    - list_checkpoints(self, path)
 | 
						|
    - rename_checkpoint(self, checkpoint_id, old_path, new_path)
 | 
						|
    """
 | 
						|
 | 
						|
    def create_checkpoint(self, contents_mgr, path):
 | 
						|
        model = contents_mgr.get(path, content=True)
 | 
						|
        type_ = model["type"]
 | 
						|
        if type_ == "notebook":
 | 
						|
            return self.create_notebook_checkpoint(
 | 
						|
                model["content"],
 | 
						|
                path,
 | 
						|
            )
 | 
						|
        elif type_ == "file":
 | 
						|
            return self.create_file_checkpoint(
 | 
						|
                model["content"],
 | 
						|
                model["format"],
 | 
						|
                path,
 | 
						|
            )
 | 
						|
        else:
 | 
						|
            raise HTTPError(500, "Unexpected type %s" % type)
 | 
						|
 | 
						|
    def restore_checkpoint(self, contents_mgr, checkpoint_id, path):
 | 
						|
        """Restore a checkpoint."""
 | 
						|
        type_ = contents_mgr.get(path, content=False)["type"]
 | 
						|
        if type_ == "notebook":
 | 
						|
            model = self.get_notebook_checkpoint(checkpoint_id, path)
 | 
						|
        elif type_ == "file":
 | 
						|
            model = self.get_file_checkpoint(checkpoint_id, path)
 | 
						|
        else:
 | 
						|
            raise HTTPError(500, "Unexpected type %s" % type_)
 | 
						|
        contents_mgr.save(model, path)
 | 
						|
 | 
						|
    # Required Methods
 | 
						|
    def create_file_checkpoint(self, content, format, path):
 | 
						|
        """Create a checkpoint of the current state of a file
 | 
						|
 | 
						|
        Returns a checkpoint model for the new checkpoint.
 | 
						|
        """
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    def create_notebook_checkpoint(self, nb, path):
 | 
						|
        """Create a checkpoint of the current state of a file
 | 
						|
 | 
						|
        Returns a checkpoint model for the new checkpoint.
 | 
						|
        """
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    def get_file_checkpoint(self, checkpoint_id, path):
 | 
						|
        """Get the content of a checkpoint for a non-notebook file.
 | 
						|
 | 
						|
        Returns a dict of the form::
 | 
						|
 | 
						|
            {
 | 
						|
                'type': 'file',
 | 
						|
                'content': <str>,
 | 
						|
                'format': {'text','base64'},
 | 
						|
            }
 | 
						|
        """
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    def get_notebook_checkpoint(self, checkpoint_id, path):
 | 
						|
        """Get the content of a checkpoint for a notebook.
 | 
						|
 | 
						|
        Returns a dict of the form::
 | 
						|
 | 
						|
            {
 | 
						|
                'type': 'notebook',
 | 
						|
                'content': <output of nbformat.read>,
 | 
						|
            }
 | 
						|
        """
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
 | 
						|
class AsyncCheckpoints(Checkpoints):
 | 
						|
    """
 | 
						|
    Base class for managing checkpoints for a ContentsManager asynchronously.
 | 
						|
    """
 | 
						|
 | 
						|
    async def create_checkpoint(self, contents_mgr, path):
 | 
						|
        """Create a checkpoint."""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    async def restore_checkpoint(self, contents_mgr, checkpoint_id, path):
 | 
						|
        """Restore a checkpoint"""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    async def rename_checkpoint(self, checkpoint_id, old_path, new_path):
 | 
						|
        """Rename a single checkpoint from old_path to new_path."""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    async def delete_checkpoint(self, checkpoint_id, path):
 | 
						|
        """delete a checkpoint for a file"""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    async def list_checkpoints(self, path):
 | 
						|
        """Return a list of checkpoints for a given file"""
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    async def rename_all_checkpoints(self, old_path, new_path):
 | 
						|
        """Rename all checkpoints for old_path to new_path."""
 | 
						|
        for cp in await self.list_checkpoints(old_path):
 | 
						|
            await self.rename_checkpoint(cp["id"], old_path, new_path)
 | 
						|
 | 
						|
    async def delete_all_checkpoints(self, path):
 | 
						|
        """Delete all checkpoints for the given path."""
 | 
						|
        for checkpoint in await self.list_checkpoints(path):
 | 
						|
            await self.delete_checkpoint(checkpoint["id"], path)
 | 
						|
 | 
						|
 | 
						|
class AsyncGenericCheckpointsMixin(GenericCheckpointsMixin):
 | 
						|
    """
 | 
						|
    Helper for creating Asynchronous Checkpoints subclasses that can be used with any
 | 
						|
    ContentsManager.
 | 
						|
    """
 | 
						|
 | 
						|
    async def create_checkpoint(self, contents_mgr, path):
 | 
						|
        model = await contents_mgr.get(path, content=True)
 | 
						|
        type_ = model["type"]
 | 
						|
        if type_ == "notebook":
 | 
						|
            return await self.create_notebook_checkpoint(
 | 
						|
                model["content"],
 | 
						|
                path,
 | 
						|
            )
 | 
						|
        elif type_ == "file":
 | 
						|
            return await self.create_file_checkpoint(
 | 
						|
                model["content"],
 | 
						|
                model["format"],
 | 
						|
                path,
 | 
						|
            )
 | 
						|
        else:
 | 
						|
            raise HTTPError(500, "Unexpected type %s" % type_)
 | 
						|
 | 
						|
    async def restore_checkpoint(self, contents_mgr, checkpoint_id, path):
 | 
						|
        """Restore a checkpoint."""
 | 
						|
        content_model = await contents_mgr.get(path, content=False)
 | 
						|
        type_ = content_model["type"]
 | 
						|
        if type_ == "notebook":
 | 
						|
            model = await self.get_notebook_checkpoint(checkpoint_id, path)
 | 
						|
        elif type_ == "file":
 | 
						|
            model = await self.get_file_checkpoint(checkpoint_id, path)
 | 
						|
        else:
 | 
						|
            raise HTTPError(500, "Unexpected type %s" % type_)
 | 
						|
        await contents_mgr.save(model, path)
 | 
						|
 | 
						|
    # Required Methods
 | 
						|
    async def create_file_checkpoint(self, content, format, path):
 | 
						|
        """Create a checkpoint of the current state of a file
 | 
						|
 | 
						|
        Returns a checkpoint model for the new checkpoint.
 | 
						|
        """
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    async def create_notebook_checkpoint(self, nb, path):
 | 
						|
        """Create a checkpoint of the current state of a file
 | 
						|
 | 
						|
        Returns a checkpoint model for the new checkpoint.
 | 
						|
        """
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    async def get_file_checkpoint(self, checkpoint_id, path):
 | 
						|
        """Get the content of a checkpoint for a non-notebook file.
 | 
						|
 | 
						|
        Returns a dict of the form::
 | 
						|
 | 
						|
            {
 | 
						|
                'type': 'file',
 | 
						|
                'content': <str>,
 | 
						|
                'format': {'text','base64'},
 | 
						|
            }
 | 
						|
        """
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    async def get_notebook_checkpoint(self, checkpoint_id, path):
 | 
						|
        """Get the content of a checkpoint for a notebook.
 | 
						|
 | 
						|
        Returns a dict of the form::
 | 
						|
 | 
						|
            {
 | 
						|
                'type': 'notebook',
 | 
						|
                'content': <output of nbformat.read>,
 | 
						|
            }
 | 
						|
        """
 | 
						|
        raise NotImplementedError
 |