示例#1
0
    def post(self, path=''):
        """Create a new file in the specified path.

        POST creates new files. The server always decides on the name.

        POST /api/contents/path
          New untitled, empty file or directory.
        POST /api/contents/path
          with body {"copy_from" : "/path/to/OtherNotebook.ipynb"}
          New copy of OtherNotebook in path
        """

        cm = self.contents_manager

        file_exists = yield maybe_future(cm.file_exists(path))
        if file_exists:
            raise web.HTTPError(400, "Cannot POST to files, use PUT instead.")

        dir_exists = yield maybe_future(cm.dir_exists(path))
        if not dir_exists:
            raise web.HTTPError(404, "No such directory: %s" % path)

        model = self.get_json_body()

        if model is not None:
            copy_from = model.get('copy_from')
            ext = model.get('ext', '')
            type = model.get('type', '')
            if copy_from:
                yield self._copy(copy_from, path)
            else:
                yield self._new_untitled(path, type=type, ext=ext)
        else:
            yield self._new_untitled(path)
示例#2
0
    def post(self, path=''):
        """Create a new file in the specified path.

        POST creates new files. The server always decides on the name.

        POST /api/contents/path
          New untitled, empty file or directory.
        POST /api/contents/path
          with body {"copy_from" : "/path/to/OtherNotebook.ipynb"}
          New copy of OtherNotebook in path
        """

        cm = self.contents_manager

        file_exists = yield maybe_future(cm.file_exists(path))
        if file_exists:
            raise web.HTTPError(400, "Cannot POST to files, use PUT instead.")

        dir_exists = yield maybe_future(cm.dir_exists(path))
        if not dir_exists:
            raise web.HTTPError(404, "No such directory: %s" % path)

        model = self.get_json_body()

        if model is not None:
            copy_from = model.get('copy_from')
            ext = model.get('ext', '')
            type = model.get('type', '')
            if copy_from:
                yield self._copy(copy_from, path)
            else:
                yield self._new_untitled(path, type=type, ext=ext)
        else:
            yield self._new_untitled(path)
示例#3
0
    def row_to_model(self, row, tolerate_culled=False):
        """Takes sqlite database session row and turns it into a dictionary"""
        kernel_culled = yield maybe_future(self.kernel_culled(row['kernel_id']))
        if kernel_culled:
            # The kernel was culled or died without deleting the session.
            # We can't use delete_session here because that tries to find
            # and shut down the kernel - so we'll delete the row directly.
            #
            # If caller wishes to tolerate culled kernels, log a warning
            # and return None.  Otherwise, raise KeyError with a similar
            # message.
            self.cursor.execute("DELETE FROM session WHERE session_id=?",
                                (row['session_id'],))
            msg = "Kernel '{kernel_id}' appears to have been culled or died unexpectedly, " \
                  "invalidating session '{session_id}'. The session has been removed.".\
                format(kernel_id=row['kernel_id'],session_id=row['session_id'])
            if tolerate_culled:
                self.log.warning(msg + "  Continuing...")
                raise gen.Return(None)
            raise KeyError(msg)

        kernel_model = yield maybe_future(self.kernel_manager.kernel_model(row['kernel_id']))
        model = {
            'id': row['session_id'],
            'path': row['path'],
            'name': row['name'],
            'type': row['type'],
            'kernel': kernel_model
        }
        if row['type'] == 'notebook':
            # Provide the deprecated API.
            model['notebook'] = {'path': row['path'], 'name': row['name']}
        raise gen.Return(model)
示例#4
0
 def delete_session(self, session_id):
     """Deletes the row in the session database with given session_id"""
     session = yield maybe_future(self.get_session(session_id=session_id))
     yield maybe_future(
         self.kernel_manager.shutdown_kernel(session['kernel']['id']))
     self.cursor.execute("DELETE FROM session WHERE session_id=?",
                         (session_id, ))
示例#5
0
 def get(self, *args, **kwargs):
     # pre_get can be a coroutine in subclasses
     # assign and yield in two step to avoid tornado 3 issues
     res = self.pre_get()
     yield maybe_future(res)
     res = super(AuthenticatedZMQStreamHandler, self).get(*args, **kwargs)
     yield maybe_future(res)
示例#6
0
 def get(self, *args, **kwargs):
     # pre_get can be a coroutine in subclasses
     # assign and yield in two step to avoid tornado 3 issues
     res = self.pre_get()
     yield maybe_future(res)
     res = super(AuthenticatedZMQStreamHandler, self).get(*args, **kwargs)
     yield maybe_future(res)
示例#7
0
    def row_to_model(self, row, tolerate_culled=False):
        """Takes sqlite database session row and turns it into a dictionary"""
        kernel_culled = yield maybe_future(self.kernel_culled(row['kernel_id']))
        if kernel_culled:
            # The kernel was culled or died without deleting the session.
            # We can't use delete_session here because that tries to find
            # and shut down the kernel - so we'll delete the row directly.
            #
            # If caller wishes to tolerate culled kernels, log a warning
            # and return None.  Otherwise, raise KeyError with a similar
            # message.
            self.cursor.execute("DELETE FROM session WHERE session_id=?", 
                                (row['session_id'],))
            msg = "Kernel '{kernel_id}' appears to have been culled or died unexpectedly, " \
                  "invalidating session '{session_id}'. The session has been removed.".\
                format(kernel_id=row['kernel_id'],session_id=row['session_id'])
            if tolerate_culled:
                self.log.warning(msg + "  Continuing...")
                raise gen.Return(None)
            raise KeyError(msg)

        kernel_model = yield maybe_future(self.kernel_manager.kernel_model(row['kernel_id']))
        model = {
            'id': row['session_id'],
            'path': row['path'],
            'name': row['name'],
            'type': row['type'],
            'kernel': kernel_model
        }
        if row['type'] == 'notebook':
            # Provide the deprecated API.
            model['notebook'] = {'path': row['path'], 'name': row['name']}
        raise gen.Return(model)
示例#8
0
    def post(self):
        # Creates a new session
        #(unless a session already exists for the named session)
        sm = self.session_manager

        model = self.get_json_body()
        if model is None:
            raise web.HTTPError(400, "No JSON data provided")

        if 'notebook' in model and 'path' in model['notebook']:
            self.log.warning('Sessions API changed, see updated swagger docs')
            model['path'] = model['notebook']['path']
            model['type'] = 'notebook'

        try:
            path = model['path']
        except KeyError as e:
            raise web.HTTPError(400, "Missing field in JSON data: path") from e

        try:
            mtype = model['type']
        except KeyError as e:
            raise web.HTTPError(400, "Missing field in JSON data: type") from e

        name = model.get('name', None)
        kernel = model.get('kernel', {})
        kernel_name = kernel.get('name', None)
        kernel_id = kernel.get('id', None)

        if not kernel_id and not kernel_name:
            self.log.debug("No kernel specified, using default kernel")
            kernel_name = None

        exists = yield maybe_future(sm.session_exists(path=path))
        if exists:
            model = yield maybe_future(sm.get_session(path=path))
        else:
            try:
                model = yield maybe_future(
                    sm.create_session(path=path,
                                      kernel_name=kernel_name,
                                      kernel_id=kernel_id,
                                      name=name,
                                      type=mtype))
            except NoSuchKernel:
                msg = ("The '%s' kernel is not available. Please pick another "
                       "suitable kernel instead, or install that kernel." %
                       kernel_name)
                status_msg = '%s not found' % kernel_name
                self.log.warning('Kernel not found: %s' % kernel_name)
                self.set_status(501)
                self.finish(
                    json.dumps(dict(message=msg, short_message=status_msg)))
                return

        location = url_path_join(self.base_url, 'api', 'sessions', model['id'])
        self.set_header('Location', location)
        self.set_status(201)
        self.finish(json.dumps(model, default=date_default))
示例#9
0
    def post(self):
        # Creates a new session
        #(unless a session already exists for the named session)
        sm = self.session_manager

        model = self.get_json_body()
        if model is None:
            raise web.HTTPError(400, "No JSON data provided")

        if 'notebook' in model and 'path' in model['notebook']:
            self.log.warning('Sessions API changed, see updated swagger docs')
            model['path'] = model['notebook']['path']
            model['type'] = 'notebook'

        try:
            path = model['path']
        except KeyError:
            raise web.HTTPError(400, "Missing field in JSON data: path")

        try:
            mtype = model['type']
        except KeyError:
            raise web.HTTPError(400, "Missing field in JSON data: type")

        name = model.get('name', None)
        kernel = model.get('kernel', {})
        kernel_name = kernel.get('name', None)
        kernel_id = kernel.get('id', None)

        if not kernel_id and not kernel_name:
            self.log.debug("No kernel specified, using default kernel")
            kernel_name = None

        exists = yield maybe_future(sm.session_exists(path=path))
        if exists:
            model = yield maybe_future(sm.get_session(path=path))
        else:
            try:
                model = yield maybe_future(
                    sm.create_session(path=path, kernel_name=kernel_name,
                                      kernel_id=kernel_id, name=name,
                                      type=mtype))
            except NoSuchKernel:
                msg = ("The '%s' kernel is not available. Please pick another "
                       "suitable kernel instead, or install that kernel." % kernel_name)
                status_msg = '%s not found' % kernel_name
                self.log.warning('Kernel not found: %s' % kernel_name)
                self.set_status(501)
                self.finish(json.dumps(dict(message=msg, short_message=status_msg)))
                return

        location = url_path_join(self.base_url, 'api', 'sessions', model['id'])
        self.set_header('Location', location)
        self.set_status(201)
        self.finish(json.dumps(model, default=date_default))
示例#10
0
    def patch(self, session_id):
        """Patch updates sessions:

        - path updates session to track renamed paths
        - kernel.name starts a new kernel with a given kernelspec
        """
        sm = self.session_manager
        km = self.kernel_manager
        model = self.get_json_body()
        if model is None:
            raise web.HTTPError(400, "No JSON data provided")

        # get the previous session model
        before = yield maybe_future(sm.get_session(session_id=session_id))

        changes = {}
        if 'notebook' in model and 'path' in model['notebook']:
            self.log.warning('Sessions API changed, see updated swagger docs')
            model['path'] = model['notebook']['path']
            model['type'] = 'notebook'
        if 'path' in model:
            changes['path'] = model['path']
        if 'name' in model:
            changes['name'] = model['name']
        if 'type' in model:
            changes['type'] = model['type']
        if 'kernel' in model:
            # Kernel id takes precedence over name.
            if model['kernel'].get('id') is not None:
                kernel_id = model['kernel']['id']
                if kernel_id not in km:
                    raise web.HTTPError(400, "No such kernel: %s" % kernel_id)
                changes['kernel_id'] = kernel_id
            elif model['kernel'].get('name') is not None:
                kernel_name = model['kernel']['name']
                kernel_id = yield sm.start_kernel_for_session(
                    session_id,
                    kernel_name=kernel_name,
                    name=before['name'],
                    path=before['path'],
                    type=before['type'])
                changes['kernel_id'] = kernel_id

        yield maybe_future(sm.update_session(session_id, **changes))
        model = yield maybe_future(sm.get_session(session_id=session_id))

        if model['kernel']['id'] != before['kernel']['id']:
            # kernel_id changed because we got a new kernel
            # shutdown the old one
            yield maybe_future(km.shutdown_kernel(before['kernel']['id']))
        self.finish(
            json.dumps(model, (r"/api/recentlist", RecentList),
                       default=date_default))
 def proxy(self):
     request = self.request
     body = request.body
     hub_api_url = environ.get('JUPYTERHUB_API_URL')
     url = url_path_join(hub_api_url,
                         'notebooks/' + request.uri.split('contents/')[1])
     if request.method == "GET":
         response = yield maybe_future(
             self._api_request(method=request.method, url=url))
     else:
         response = yield maybe_future(
             self._api_request(method=request.method, url=url, data=body))
     self.set_status(response.status_code)
     self.finish(response.text)
示例#12
0
    def patch(self, session_id):
        """Patch updates sessions:

        - path updates session to track renamed paths
        - kernel.name starts a new kernel with a given kernelspec
        """
        sm = self.session_manager
        km = self.kernel_manager
        model = self.get_json_body()
        if model is None:
            raise web.HTTPError(400, "No JSON data provided")

        # get the previous session model
        before = yield maybe_future(sm.get_session(session_id=session_id))

        changes = {}
        if 'notebook' in model and 'path' in model['notebook']:
            self.log.warning('Sessions API changed, see updated swagger docs')
            model['path'] = model['notebook']['path']
            model['type'] = 'notebook'
        if 'path' in model:
            changes['path'] = model['path']
        if 'name' in model:
            changes['name'] = model['name']
        if 'type' in model:
            changes['type'] = model['type']
        if 'kernel' in model:
            # Kernel id takes precedence over name.
            if model['kernel'].get('id') is not None:
                kernel_id = model['kernel']['id']
                if kernel_id not in km:
                    raise web.HTTPError(400, "No such kernel: %s" % kernel_id)
                changes['kernel_id'] = kernel_id
            elif model['kernel'].get('name') is not None:
                kernel_name = model['kernel']['name']
                kernel_id = yield sm.start_kernel_for_session(
                    session_id, kernel_name=kernel_name, name=before['name'],
                    path=before['path'], type=before['type'])
                changes['kernel_id'] = kernel_id

        yield maybe_future(sm.update_session(session_id, **changes))
        model = yield maybe_future(sm.get_session(session_id=session_id))

        if model['kernel']['id'] != before['kernel']['id']:
            # kernel_id changed because we got a new kernel
            # shutdown the old one
            yield maybe_future(
                km.shutdown_kernel(before['kernel']['id'])
            )
        self.finish(json.dumps(model, default=date_default))
示例#13
0
    def post(self):
        km = self.kernel_manager
        model = self.get_json_body()
        if model is None:
            model = {'name': km.default_kernel_name}
        else:
            model.setdefault('name', km.default_kernel_name)

        kernel_id = yield maybe_future(
            km.start_kernel(kernel_name=model['name']))
        model = yield maybe_future(km.kernel_model(kernel_id))
        location = url_path_join(self.base_url, 'api', 'kernels',
                                 url_escape(kernel_id))
        self.set_header('Location', location)
        self.set_status(201)
        self.finish(json.dumps(model, default=date_default))
示例#14
0
    def get(self, path):
        """Bundle the given notebook.
        
        Parameters
        ----------
        path: str
            Path to the notebook (path parameter)
        bundler: str
            Bundler ID to use (query parameter)
        """
        bundler_id = self.get_query_argument('bundler')
        model = self.contents_manager.get(path=url2path(path))

        try:
            bundler = self.get_bundler(bundler_id)
        except KeyError:
            raise web.HTTPError(400, 'Bundler %s not enabled' % bundler_id)

        module_name = bundler['module_name']
        try:
            # no-op in python3, decode error in python2
            module_name = str(module_name)
        except UnicodeEncodeError:
            # Encode unicode as utf-8 in python2 else import_item fails
            module_name = module_name.encode('utf-8')

        try:
            bundler_mod = import_item(module_name)
        except ImportError:
            raise web.HTTPError(500,
                                'Could not import bundler %s ' % bundler_id)

        # Let the bundler respond in any way it sees fit and assume it will
        # finish the request
        yield maybe_future(bundler_mod.bundle(self, model))
示例#15
0
    def post(self):
        km = self.kernel_manager
        model = self.get_json_body()
        if model is None:
            model = {
                'name': km.default_kernel_name
            }
        else:
            model.setdefault('name', km.default_kernel_name)

        kernel_id = yield maybe_future(km.start_kernel(kernel_name=model['name']))
        model = yield maybe_future(km.kernel_model(kernel_id))
        location = url_path_join(self.base_url, 'api', 'kernels', url_escape(kernel_id))
        self.set_header('Location', location)
        self.set_status(201)
        self.finish(json.dumps(model, default=date_default))
示例#16
0
    def post(self, kernel_id, action):
        km = self.kernel_manager
        if action == 'interrupt':
            km.interrupt_kernel(kernel_id)
            self.set_status(204)
        if action == 'restart':

            try:
                yield maybe_future(km.restart_kernel(kernel_id))
            except Exception as e:
                self.log.error("Exception restarting kernel", exc_info=True)
                self.set_status(500)
            else:
                model = yield maybe_future(km.kernel_model(kernel_id))
                self.write(json.dumps(model, default=date_default))
        self.finish()
示例#17
0
    def post(self, kernel_id, action):
        km = self.kernel_manager
        if action == 'interrupt':
            km.interrupt_kernel(kernel_id)
            self.set_status(204)
        if action == 'restart':

            try:
                yield maybe_future(km.restart_kernel(kernel_id))
            except Exception as e:
                self.log.error("Exception restarting kernel", exc_info=True)
                self.set_status(500)
            else:
                model = yield maybe_future(km.kernel_model(kernel_id))
                self.write(json.dumps(model, default=date_default))
        self.finish()
示例#18
0
    def save_session(self, session_id, path=None, name=None, type=None, kernel_id=None):
        """Saves the items for the session with the given session_id

        Given a session_id (and any other of the arguments), this method
        creates a row in the sqlite session database that holds the information
        for a session.

        Parameters
        ----------
        session_id : str
            uuid for the session; this method must be given a session_id
        path : str
            the path for the given session
        name: str
            the name of the session
        type: string
            the type of the session
        kernel_id : str
            a uuid for the kernel associated with this session

        Returns
        -------
        model : dict
            a dictionary of the session model
        """
        self.cursor.execute("INSERT INTO session VALUES (?,?,?,?,?)",
            (session_id, path, name, type, kernel_id)
        )
        result = yield maybe_future(self.get_session(session_id=session_id))
        raise gen.Return(result)
示例#19
0
 def save_session(self, session_id, path=None, name=None, type=None, kernel_id=None):
     """Saves the items for the session with the given session_id
     
     Given a session_id (and any other of the arguments), this method
     creates a row in the sqlite session database that holds the information
     for a session.
     
     Parameters
     ----------
     session_id : str
         uuid for the session; this method must be given a session_id
     path : str
         the path for the given session
     name: str
         the name of the session
     type: string
         the type of the session
     kernel_id : str
         a uuid for the kernel associated with this session
     
     Returns
     -------
     model : dict
         a dictionary of the session model
     """
     self.cursor.execute("INSERT INTO session VALUES (?,?,?,?,?)",
         (session_id, path, name, type, kernel_id)
     )
     result = yield maybe_future(self.get_session(session_id=session_id))
     raise gen.Return(result)
示例#20
0
    def update_session(self, session_id, **kwargs):
        """Updates the values in the session database.
        
        Changes the values of the session with the given session_id
        with the values from the keyword arguments. 
        
        Parameters
        ----------
        session_id : str
            a uuid that identifies a session in the sqlite3 database
        **kwargs : str
            the key must correspond to a column title in session database,
            and the value replaces the current value in the session 
            with session_id.
        """
        yield maybe_future(self.get_session(session_id=session_id))

        if not kwargs:
            # no changes
            return

        sets = []
        for column in kwargs.keys():
            if column not in self._columns:
                raise TypeError("No such column: %r" % column)
            sets.append("%s=?" % column)
        query = "UPDATE session SET %s WHERE session_id=?" % (', '.join(sets))
        self.cursor.execute(query, list(kwargs.values()) + [session_id])
示例#21
0
    def update_session(self, session_id, **kwargs):
        """Updates the values in the session database.

        Changes the values of the session with the given session_id
        with the values from the keyword arguments.

        Parameters
        ----------
        session_id : str
            a uuid that identifies a session in the sqlite3 database
        **kwargs : str
            the key must correspond to a column title in session database,
            and the value replaces the current value in the session
            with session_id.
        """
        yield maybe_future(self.get_session(session_id=session_id))

        if not kwargs:
            # no changes
            return

        sets = []
        for column in kwargs.keys():
            if column not in self._columns:
                raise TypeError("No such column: %r" % column)
            sets.append("%s=?" % column)
        query = "UPDATE session SET %s WHERE session_id=?" % (', '.join(sets))
        self.cursor.execute(query, list(kwargs.values()) + [session_id])
示例#22
0
 def _upload(self, model, path):
     """Handle upload of a new file to path"""
     self.log.info(u"Uploading file to %s", path)
     model = yield maybe_future(self.contents_manager.new(model, path))
     self.set_status(201)
     validate_model(model, expect_content=False)
     self._finish_model(model)
示例#23
0
 def _upload(self, model, path):
     """Handle upload of a new file to path"""
     self.log.info(u"Uploading file to %s", path)
     model = yield maybe_future(self.contents_manager.new(model, path))
     self.set_status(201)
     validate_model(model, expect_content=False)
     self._finish_model(model)
示例#24
0
    def get(self, path=''):
        """Return a model for a file or directory.

        A directory model contains a list of models (without content)
        of the files and directories it contains.
        """
        path = path or ''
        type = self.get_query_argument('type', default=None)
        if type not in {None, 'directory', 'file', 'notebook'}:
            raise web.HTTPError(400, u'Type %r is invalid' % type)

        format = self.get_query_argument('format', default=None)
        if format not in {None, 'text', 'base64'}:
            raise web.HTTPError(400, u'Format %r is invalid' % format)
        content = self.get_query_argument('content', default='1')
        if content not in {'0', '1'}:
            raise web.HTTPError(400, u'Content %r is invalid' % content)
        content = int(content)

        model = yield maybe_future(
            self.contents_manager.get(
                path=path,
                type=type,
                format=format,
                content=content,
            ))
        validate_model(model, expect_content=content)
        self._finish_model(model, location=False)
示例#25
0
 def _new_untitled(self, path, type='', ext=''):
     """Create a new, empty untitled entity"""
     self.log.info(u"Creating new %s in %s", type or 'file', path)
     model = yield maybe_future(self.contents_manager.new_untitled(path=path, type=type, ext=ext))
     self.set_status(201)
     validate_model(model, expect_content=False)
     self._finish_model(model)
示例#26
0
 def delete(self, path=''):
     """delete a file in the given path"""
     cm = self.contents_manager
     self.log.warning('delete %s', path)
     yield maybe_future(cm.delete(path))
     self.set_status(204)
     self.finish()
示例#27
0
 def _new_untitled(self, path, type='', ext=''):
     """Create a new, empty untitled entity"""
     self.log.info(u"Creating new %s in %s", type or 'file', path)
     model = yield maybe_future(self.contents_manager.new_untitled(path=path, type=type, ext=ext))
     self.set_status(201)
     validate_model(model, expect_content=False)
     self._finish_model(model)
示例#28
0
 def delete(self, path=''):
     """delete a file in the given path"""
     cm = self.contents_manager
     self.log.warning('delete %s', path)
     yield maybe_future(cm.delete(path))
     self.set_status(204)
     self.finish()
示例#29
0
    def post(self):
        km = self.kernel_manager
        model = self.get_json_body()
        if model is None:
            model = {"name": km.default_kernel_name}
        else:
            model.setdefault("name", km.default_kernel_name)

        kernel_id = yield maybe_future(
            km.start_kernel(kernel_name=model["name"]))
        model = yield maybe_future(km.kernel_model(kernel_id))
        location = url_path_join(self.base_url, "api", "kernels",
                                 url_escape(kernel_id))
        self.set_header("Location", location)
        self.set_status(201)
        self.finish(json.dumps(model, default=date_default))
示例#30
0
 def get(self):
     """Handler for a get on a specific handler
     """
     resource_name, content_type = self.get_resource_metadata()
     self.set_header('Content-Type', content_type)
     res = web.StaticFileHandler.get(self, resource_name)
     yield maybe_future(res)
示例#31
0
    def create_session(self,
                       path=None,
                       kernel_name=None,
                       kernel_id=None,
                       *args,
                       **kwargs):
        """Creates a session and returns its model.

        Launches a kernel and stores the session metadata for later lookup.

        Parameters
        ----------
        path : str
            Path value to store in the session metadata
        kernel_name : str
            Kernel spec name
        kernel_id : str
            Existing kernel ID to bind to the session (unsupported)

        Returns
        -------
        dict
            Session model
        """
        session_id = self.new_session_id()
        # allow nbm to specify kernels cwd
        kernel_id = yield maybe_future(
            self.kernel_manager.start_kernel(path=path,
                                             kernel_name=kernel_name))
        raise gen.Return(
            self.save_session(session_id, path=path, kernel_id=kernel_id))
示例#32
0
    def put(self, path=''):
        """Saves the file in the location specified by name and path.

        PUT is very similar to POST, but the requester specifies the name,
        whereas with POST, the server picks the name.

        PUT /api/contents/path/Name.ipynb
          Save notebook at ``path/Name.ipynb``. Notebook structure is specified
          in `content` key of JSON request body. If content is not specified,
          create a new empty notebook.
        """
        model = self.get_json_body()
        content = model.get("content", None)
        cells = None
        if content:
            cells = content.get('cells', None)
        if cells:
            source = []
            username = self.current_user.get("name", "")
            header = "\n### " + time.strftime(
                "%Y%-m-%d %H:%M:%S",
                time.localtime()) + "\t" + username + "\t" + path + "\n"
            daystr = time.strftime("%Y%m%d", time.localtime())
            for cell in cells:
                source.append(cell.get('source', ''))
            source.append("$$$ -END- \n\n")
            content_text = '\n'.join(source)
            content_md5 = md5str(content_text)
            old_content_md5 = self.md5cache.get(path, "")
            self.md5cache[path] = content_md5
            if old_content_md5 != content_md5:
                par_dir = f"/tmp/{username}/"
                if not os.path.exists(par_dir):
                    os.makedirs(par_dir)
                with open(f"{par_dir}{daystr}", 'a') as oper:
                    oper.write(header + content_text)
        if model:
            if model.get('copy_from'):
                raise web.HTTPError(400, "Cannot copy with PUT, only POST")
            exists = yield maybe_future(
                self.contents_manager.file_exists(path))
            if exists:
                yield maybe_future(self._save(model, path))
            else:
                yield maybe_future(self._upload(model, path))
        else:
            yield maybe_future(self._new_untitled(path))
示例#33
0
 def _save(self, model, path):
     """Save an existing file."""
     chunk = model.get("chunk", None) 
     if not chunk or chunk == -1:  # Avoid tedious log information
         self.log.info(u"Saving file at %s", path)  
     model = yield maybe_future(self.contents_manager.save(model, path))
     validate_model(model, expect_content=False)
     self._finish_model(model)
示例#34
0
    def get(self):

        url = self.get_query_argument('url', default=None)
        if not url:
            raise web.HTTPError(400, u'No url provided')
        check_url(url)

        model = yield maybe_future(self.contents_manager.download(url=url))
        self._finish_model(model)
示例#35
0
 def start_kernel_for_session(self, session_id, path, name, type, kernel_name):
     """Start a new kernel for a given session."""
     # allow contents manager to specify kernels cwd
     kernel_path = self.contents_manager.get_kernel_path(path=path)
     kernel_id = yield maybe_future(
         self.kernel_manager.start_kernel(path=kernel_path, kernel_name=kernel_name)
     )
     # py2-compat
     raise gen.Return(kernel_id)
示例#36
0
 def patch(self, path=''):
     """PATCH renames a file or directory without re-uploading content."""
     cm = self.contents_manager
     model = self.get_json_body()
     if model is None:
         raise web.HTTPError(400, u'JSON body missing')
     model = yield maybe_future(cm.update(model, path))
     validate_model(model, expect_content=False)
     self._finish_model(model)
示例#37
0
 def start_kernel_for_session(self, session_id, path, name, type, kernel_name):
     """Start a new kernel for a given session."""
     # allow contents manager to specify kernels cwd
     kernel_path = self.contents_manager.get_kernel_path(path=path)
     kernel_id = yield maybe_future(
         self.kernel_manager.start_kernel(path=kernel_path, kernel_name=kernel_name)
     )
     # py2-compat
     raise gen.Return(kernel_id)
    def get(self, path=""):
        uri = self.request.uri
        base_uri = uri.split("?")[0]
        parts = base_uri.split("/")
        final_path = "/" + "/".join(parts[-3:])
        model = yield maybe_future(self.contents_manager.get(final_path))

        self.set_status(200)
        self._finish_model(model)
示例#39
0
 def patch(self, path=''):
     """PATCH renames a file or directory without re-uploading content."""
     cm = self.contents_manager
     model = self.get_json_body()
     if model is None:
         raise web.HTTPError(400, u'JSON body missing')
     model = yield maybe_future(cm.update(model, path))
     validate_model(model, expect_content=False)
     self._finish_model(model)
示例#40
0
    def get(self):
        sessions = yield maybe_future(
            self.settings['session_manager'].list_sessions())

        sessions_by_kernel = {}
        for s in sessions:
            try:
                kid = s['kernel']['id']
            except KeyError:
                continue
            sessions_by_kernel.setdefault(kid, []).append(s)

        gpusers = self.nvsmi.DeviceQuery('compute-apps')['gpu']

        #result = {'gpu_sessions': []}
        result = []
        for gid, gpu in enumerate(gpusers):
            result.append({'kernels': []})
            if gpu['processes'] is None: continue
            for p in gpu['processes']:
                pinfo = {}
                with open('/proc/%d/cmdline' % p['pid'], 'r') as ftmp:
                    cmdline = ftmp.read().strip()
                with open('/proc/%d/loginuid' % p['pid'], 'r') as ftmp:
                    pinfo['uid'] = int(ftmp.read().strip())
                if 'ipykernel_launcher' in cmdline:
                    items = cmdline.split('\u0000')
                    kfile = os.path.basename(items[items.index('-f') + 1])
                    if kfile.startswith('kernel-') and kfile.endswith('.json'):
                        pinfo['id'] = kfile[len('kernel-'):-len('.json')]
                try:
                    pinfo['sessions'] = sessions_by_kernel[pinfo['id']]
                except KeyError:
                    continue
                pinfo['used_memory'] = p['used_memory']
                pinfo['pid'] = p['pid']
                pinfo['gpu'] = gid
                pinfo['cmdline'] = cmdline.replace('\u0000', ' ')
                result[-1]['kernels'].append(pinfo)

        gpstats = self.nvsmi.DeviceQuery(
            'name,utilization.gpu,utilization.memory,memory.free,memory.used,memory.total'
        )['gpu']
        for gid, stats in enumerate(gpstats):
            result[gid]['stats'] = {
                'name': stats['product_name'],
                'brand': stats['product_brand'],
                'mem_total': stats['fb_memory_usage']['total'],
                'mem_free': stats['fb_memory_usage']['free'],
                'mem_used': stats['fb_memory_usage']['used'],
                'mem_unit': stats['fb_memory_usage']['unit'],
                'mem_util': stats['utilization']['memory_util'],
                'gpu_util': stats['utilization']['gpu_util'],
                'index': gid,
            }
        self.finish(json.dumps(result))
示例#41
0
 def delete(self, session_id):
     # Deletes the session with given session_id
     sm = self.session_manager
     try:
         yield maybe_future(sm.delete_session(session_id))
     except KeyError:
         # the kernel was deleted but the session wasn't!
         raise web.HTTPError(410, "Kernel deleted before session")
     self.set_status(204)
     self.finish()
示例#42
0
 def _copy(self, copy_from, copy_to=None):
     """Copy a file, optionally specifying a target directory."""
     self.log.info(u"Copying {copy_from} to {copy_to}".format(
         copy_from=copy_from,
         copy_to=copy_to or '',
     ))
     model = yield maybe_future(self.contents_manager.copy(copy_from, copy_to))
     self.set_status(201)
     validate_model(model, expect_content=False)
     self._finish_model(model)
示例#43
0
 def post(self, path=''):
     """post creates a new checkpoint"""
     cm = self.contents_manager
     checkpoint = yield maybe_future(cm.create_checkpoint(path))
     data = json.dumps(checkpoint, default=date_default)
     location = url_path_join(self.base_url, 'api/contents',
         url_escape(path), 'checkpoints', url_escape(checkpoint['id']))
     self.set_header('Location', location)
     self.set_status(201)
     self.finish(data)
示例#44
0
 def post(self, path=''):
     """post creates a new checkpoint"""
     cm = self.contents_manager
     checkpoint = yield maybe_future(cm.create_checkpoint(path))
     data = json.dumps(checkpoint, default=date_default)
     location = url_path_join(self.base_url, 'api/contents',
         url_escape(path), 'checkpoints', url_escape(checkpoint['id']))
     self.set_header('Location', location)
     self.set_status(201)
     self.finish(data)
示例#45
0
 def _copy(self, copy_from, copy_to=None):
     """Copy a file, optionally specifying a target directory."""
     self.log.info(u"Copying {copy_from} to {copy_to}".format(
         copy_from=copy_from,
         copy_to=copy_to or '',
     ))
     model = yield maybe_future(self.contents_manager.copy(copy_from, copy_to))
     self.set_status(201)
     validate_model(model, expect_content=False)
     self._finish_model(model)
示例#46
0
 def create_session(self, path=None, name=None, type=None, kernel_name=None, kernel_id=None):
     """Creates a session and returns its model"""
     session_id = self.new_session_id()
     if kernel_id is not None and kernel_id in self.kernel_manager:
         pass
     else:
         kernel_id = yield self.start_kernel_for_session(session_id, path, name, type, kernel_name)
     result = yield maybe_future(
         self.save_session(session_id, path=path, name=name, type=type, kernel_id=kernel_id)
     )
     # py2-compat
     raise gen.Return(result)
示例#47
0
 def create_session(self, path=None, name=None, type=None, kernel_name=None, kernel_id=None):
     """Creates a session and returns its model"""
     session_id = self.new_session_id()
     if kernel_id is not None and kernel_id in self.kernel_manager:
         pass
     else:
         kernel_id = yield self.start_kernel_for_session(session_id, path, name, type, kernel_name)
     result = yield maybe_future(
         self.save_session(session_id, path=path, name=name, type=type, kernel_id=kernel_id)
     )
     # py2-compat
     raise gen.Return(result)
示例#48
0
    def put(self, path=''):
        """Saves the file in the location specified by name and path.

        PUT is very similar to POST, but the requester specifies the name,
        whereas with POST, the server picks the name.

        PUT /api/contents/path/Name.ipynb
          Save notebook at ``path/Name.ipynb``. Notebook structure is specified
          in `content` key of JSON request body. If content is not specified,
          create a new empty notebook.
        """
        model = self.get_json_body()
        if model:
            if model.get('copy_from'):
                raise web.HTTPError(400, "Cannot copy with PUT, only POST")
            exists = yield maybe_future(self.contents_manager.file_exists(path))
            if exists:
                yield maybe_future(self._save(model, path))
            else:
                yield maybe_future(self._upload(model, path))
        else:
            yield maybe_future(self._new_untitled(path))
示例#49
0
 def list_sessions(self):
     """Returns a list of dictionaries containing all the information from
     the session database"""
     c = self.cursor.execute("SELECT * FROM session")
     result = []
     # We need to use fetchall() here, because row_to_model can delete rows,
     # which messes up the cursor if we're iterating over rows.
     for row in c.fetchall():
         try:
             model = yield maybe_future(self.row_to_model(row))
             result.append(model)
         except KeyError:
             pass
     raise gen.Return(result)
示例#50
0
    def get(self):
        # if started was missing, use unix epoch
        started = self.settings.get('started', utcfromtimestamp(0))
        started = isoformat(started)

        kernels = yield maybe_future(self.kernel_manager.list_kernels())
        total_connections = sum(k['connections'] for k in kernels)
        last_activity = isoformat(self.application.last_activity())
        model = {
            'started': started,
            'last_activity': last_activity,
            'kernels': len(kernels),
            'connections': total_connections,
        }
        self.finish(json.dumps(model, sort_keys=True))
示例#51
0
 def session_exists(self, path):
     """Check to see if the session of a given name exists"""
     exists = False
     self.cursor.execute("SELECT * FROM session WHERE path=?", (path,))
     row = self.cursor.fetchone()
     if row is not None:
         # Note, although we found a row for the session, the associated kernel may have
         # been culled or died unexpectedly.  If that's the case, we should delete the
         # row, thereby terminating the session.  This can be done via a call to
         # row_to_model that tolerates that condition.  If row_to_model returns None,
         # we'll return false, since, at that point, the session doesn't exist anyway.
         model = yield maybe_future(self.row_to_model(row, tolerate_culled=True))
         if model is not None:
             exists = True
     raise gen.Return(exists)
示例#52
0
    def get_session(self, **kwargs):
        """Returns the model for a particular session.
        
        Takes a keyword argument and searches for the value in the session
        database, then returns the rest of the session's info.

        Parameters
        ----------
        **kwargs : keyword argument
            must be given one of the keywords and values from the session database
            (i.e. session_id, path, name, type, kernel_id)

        Returns
        -------
        model : dict
            returns a dictionary that includes all the information from the 
            session described by the kwarg.
        """
        if not kwargs:
            raise TypeError("must specify a column to query")

        conditions = []
        for column in kwargs.keys():
            if column not in self._columns:
                raise TypeError("No such column: %r", column)
            conditions.append("%s=?" % column)

        query = "SELECT * FROM session WHERE %s" % (' AND '.join(conditions))

        self.cursor.execute(query, list(kwargs.values()))
        try:
            row = self.cursor.fetchone()
        except KeyError:
            # The kernel is missing, so the session just got deleted.
            row = None

        if row is None:
            q = []
            for key, value in kwargs.items():
                q.append("%s=%r" % (key, value))

            raise web.HTTPError(404, u'Session not found: %s' % (', '.join(q)))

        model = yield maybe_future(self.row_to_model(row))
        raise gen.Return(model)
示例#53
0
    def get(self, path, include_body=True):
        # /files/ requests must originate from the same site
        self.check_xsrf_cookie()
        cm = self.contents_manager

        if cm.is_hidden(path) and not cm.allow_hidden:
            self.log.info("Refusing to serve hidden file, via 404 Error")
            raise web.HTTPError(404)

        path = path.strip('/')
        if '/' in path:
            _, name = path.rsplit('/', 1)
        else:
            name = path
        
        model = yield maybe_future(cm.get(path, type='file', content=include_body))
        
        if self.get_argument("download", False):
            self.set_attachment_header(name)
        
        # get mimetype from filename
        if name.lower().endswith('.ipynb'):
            self.set_header('Content-Type', 'application/x-ipynb+json')
        else:
            cur_mime = mimetypes.guess_type(name)[0]
            if cur_mime == 'text/plain':
                self.set_header('Content-Type', 'text/plain; charset=UTF-8')
            elif cur_mime is not None:
                self.set_header('Content-Type', cur_mime)
            else:
                if model['format'] == 'base64':
                    self.set_header('Content-Type', 'application/octet-stream')
                else:
                    self.set_header('Content-Type', 'text/plain; charset=UTF-8')

        if include_body:
            if model['format'] == 'base64':
                b64_bytes = model['content'].encode('ascii')
                self.write(decodebytes(b64_bytes))
            elif model['format'] == 'json':
                self.write(json.dumps(model['content']))
            else:
                self.write(model['content'])
            self.flush()
示例#54
0
    def get(self, path=''):
        """Return a model for a file or directory.

        A directory model contains a list of models (without content)
        of the files and directories it contains.
        """
        path = path or ''
        type = self.get_query_argument('type', default=None)
        if type not in {None, 'directory', 'file', 'notebook'}:
            raise web.HTTPError(400, u'Type %r is invalid' % type)

        format = self.get_query_argument('format', default=None)
        if format not in {None, 'text', 'base64'}:
            raise web.HTTPError(400, u'Format %r is invalid' % format)
        content = self.get_query_argument('content', default='1')
        if content not in {'0', '1'}:
            raise web.HTTPError(400, u'Content %r is invalid' % content)
        content = int(content)
        
        model = yield maybe_future(self.contents_manager.get(
            path=path, type=type, format=format, content=content,
        ))
        validate_model(model, expect_content=content)
        self._finish_model(model, location=False)
示例#55
0
 def post(self,path=''):
     cm = self.contents_manager
     yield maybe_future(cm.trust_notebook(path))
     self.set_status(201)
     self.finish()
示例#56
0
 def get(self, path=''):
     """get lists checkpoints for a file"""
     cm = self.contents_manager
     checkpoints = yield maybe_future(cm.list_checkpoints(path))
     data = json.dumps(checkpoints, default=date_default)
     self.finish(data)
示例#57
0
 def post(self, path, checkpoint_id):
     """post restores a file from a checkpoint"""
     cm = self.contents_manager
     yield maybe_future(cm.restore_checkpoint(checkpoint_id, path))
     self.set_status(204)
     self.finish()
示例#58
0
 def delete(self, path, checkpoint_id):
     """delete clears a checkpoint for a given file"""
     cm = self.contents_manager
     yield maybe_future(cm.delete_checkpoint(checkpoint_id, path))
     self.set_status(204)
     self.finish()