def test_migrate_config(td):
    profile = pjoin(td, 'profile')
    jpy = pjoin(td, 'jupyter_config')
    ensure_dir_exists(profile)

    env = {
        'profile': profile,
        'jupyter_config': jpy,
    }
    cfg_py = pjoin(profile, 'ipython_test_config.py')
    touch(cfg_py, 'c.Klass.trait = 5\n')
    empty_cfg_py = pjoin(profile, 'ipython_empty_config.py')
    touch(empty_cfg_py, '# c.Klass.trait = 5\n')

    assert not migrate_config('empty', env)
    assert not os.path.exists(jpy)

    with patch.dict(migrate_mod.config_substitutions, {
            re.compile(r'\bKlass\b'): 'Replaced',
    }):
        assert migrate_config('test', env)

    assert os.path.isdir(jpy)
    assert sorted(os.listdir(jpy)) == [
        'jupyter_test_config.py',
    ]

    with open(pjoin(jpy, 'jupyter_test_config.py')) as f:
        text = f.read()
    assert text == 'c.Replaced.trait = 5\n'
Example #2
0
def test_migrate_config(td):
    profile = pjoin(td, 'profile')
    jpy = pjoin(td, 'jupyter_config')
    ensure_dir_exists(profile)
    
    env = {
        'profile': profile,
        'jupyter_config': jpy,
    }
    cfg_py = pjoin(profile, 'ipython_test_config.py')
    touch(cfg_py, 'c.Klass.trait = 5\n')
    empty_cfg_py = pjoin(profile, 'ipython_empty_config.py')
    touch(empty_cfg_py, '# c.Klass.trait = 5\n')
    
    assert not migrate_config('empty', env)
    assert not os.path.exists(jpy)
    
    with patch.dict(migrate_mod.config_substitutions, {
        re.compile(r'\bKlass\b'): 'Replaced',
    }):
        assert migrate_config('test', env)
    
    assert os.path.isdir(jpy)
    assert sorted(os.listdir(jpy)) == [
        'jupyter_test_config.py',
    ]
    
    with open(pjoin(jpy, 'jupyter_test_config.py')) as f:
        text = f.read()
    assert text == 'c.Replaced.trait = 5\n'
Example #3
0
def launch(image, cwd):
    d = os.path.join(jupyter_runtime_dir(), 'docker_kernels')
    ensure_dir_exists(d)
    set_sticky_bit(d)
    conn_file_tmpdir = TemporaryDirectory(dir=d)
    conn_info = make_connection_file(conn_file_tmpdir.name)

    container = docker.from_env().containers.run(image,
                                                 detach=True,
                                                 volumes={
                                                     conn_file_tmpdir.name: {
                                                         'bind': '/connect',
                                                         'mode': 'rw'
                                                     },
                                                     cwd: {
                                                         'bind': '/working',
                                                         'mode': 'rw'
                                                     },
                                                 })

    container.reload()  # Need this to get the IP address
    ip = container.attrs['NetworkSettings']['Networks']['bridge']['IPAddress']
    if not ip:
        raise RuntimeError("No IP address for docker container")
    print(container.attrs['NetworkSettings']['Networks'])
    conn_info['ip'] = ip

    return conn_info, DockerKernelManager(container, conn_file_tmpdir)
 def checkpoint_path(self, checkpoint_id, path):
     """find the path to a checkpoint"""
     checkpoint_dir = self.get_checkpoints_path_for_file(path)
     with self.perm_to_403():
         ensure_dir_exists(checkpoint_dir)
     cp_path = os.path.join(checkpoint_dir, checkpoint_id)
     return cp_path
Example #5
0
    def _template_paths(self, prune=True, root_dirs=None):
        paths = []
        root_dirs = self.get_prefix_root_dirs()
        template_names = self.get_template_names()
        for template_name in template_names:
            for base_dir in self.extra_template_basedirs:
                path = os.path.join(base_dir, template_name)
                if not prune or os.path.exists(path):
                    paths.append(path)
            for root_dir in root_dirs:
                base_dir = os.path.join(root_dir, 'nbconvert', 'templates')
                path = os.path.join(base_dir, template_name)
                if not prune or os.path.exists(path):
                    paths.append(path)

        for root_dir in root_dirs:
            # we include root_dir for when we want to be very explicit, e.g.
            # {% extends 'nbconvert/templates/classic/base.html' %}
            paths.append(root_dir)
            # we include base_dir for when we want to be explicit, but less than root_dir, e.g.
            # {% extends 'classic/base.html' %}
            base_dir = os.path.join(root_dir, 'nbconvert', 'templates')
            paths.append(base_dir)

            compatibility_dir = os.path.join(root_dir, 'nbconvert', 'templates', 'compatibility')
            paths.append(compatibility_dir)

        additional_paths = self.template_data_paths
        for path in additional_paths:
            try:
                ensure_dir_exists(path, mode=0o700)
            except OSError:
                pass

        return paths + self.extra_template_paths + additional_paths
Example #6
0
    def write_connection_file(self):
        runtime_dir = jupyter_runtime_dir()
        ensure_dir_exists(runtime_dir)
        fname = os.path.join(runtime_dir, 'kernelnanny-%s.json' % os.getpid())

        with open(fname, 'w') as f:
            f.write(json.dumps(self.connection_info, indent=2))

        set_sticky_bit(fname)
        return fname
Example #7
0
    def record_connection_info(self, conn_info):
        log.info("Connection info: %s", conn_info)
        runtime_dir = jupyter_runtime_dir()
        ensure_dir_exists(runtime_dir)
        fname = os.path.join(runtime_dir, 'kernel-%s.json' % uuid4())

        # Only ever write this file as user read/writeable
        # This would otherwise introduce a vulnerability as a file has secrets
        # which would let others execute arbitrarily code as you
        with secure_write(fname) as f:
            f.write(json.dumps(conn_info, indent=2))

        log.info("To connect a client: --existing %s", os.path.basename(fname))
        return fname
Example #8
0
    def checkpoint_path(self, checkpoint_id, path):
        """find the path to a checkpoint"""
        path = path.strip('/')
        parent, name = ('/' + path).rsplit('/', 1)
        parent = parent.strip('/')
        basename, ext = os.path.splitext(name)
        filename = u"{name}-{checkpoint_id}{ext}".format(
            name=basename,
            checkpoint_id=checkpoint_id,
            ext=ext,
        )
        os_path = self._get_os_path(path=parent)
        cp_dir = os.path.join(os_path, self.checkpoint_dir)
        # iOS, move checkpoint directory to ~/Documents if local dir is not writeable
        import sys
        if (sys.platform == 'darwin' and os.uname().machine.startswith('iP')):
            try:
                ensure_dir_exists(cp_dir)
                if not os.access(cp_dir, os.X_OK | os.W_OK):
                    cp_dir = os.path.join(os.path.expanduser('~'), 'Documents',
                                          self.checkpoint_dir)
                    with self.perm_to_403():
                        ensure_dir_exists(cp_dir)
            except (OSError, IOError) as e:
                cp_dir = os.path.join(os.path.expanduser('~'), 'Documents',
                                      self.checkpoint_dir)
                with self.perm_to_403():
                    ensure_dir_exists(cp_dir)
        else:
            with self.perm_to_403():
                ensure_dir_exists(cp_dir)

        cp_path = os.path.join(cp_dir, filename)
        return cp_path
Example #9
0
 def checkpoint_path(self, checkpoint_id, path):
     """find the path to a checkpoint"""
     path = path.strip("/")
     parent, name = ("/" + path).rsplit("/", 1)
     parent = parent.strip("/")
     basename, ext = os.path.splitext(name)
     filename = "{name}-{checkpoint_id}{ext}".format(
         name=basename,
         checkpoint_id=checkpoint_id,
         ext=ext,
     )
     os_path = self._get_os_path(path=parent)
     cp_dir = os.path.join(os_path, self.checkpoint_dir)
     with self.perm_to_403():
         ensure_dir_exists(cp_dir)
     cp_path = os.path.join(cp_dir, filename)
     return cp_path
Example #10
0
    def make_connection_file(self):
        """Generates a JSON config file, including the selection of random ports.
        """
        runtime_dir = jupyter_runtime_dir()
        ensure_dir_exists(runtime_dir)
        fname = os.path.join(runtime_dir, 'kernel-%s.json' % new_key())

        cfg = self.make_ports()
        cfg['ip'] = self.ip
        cfg['key'] = new_key()
        cfg['transport'] = self.transport
        cfg['signature_scheme'] = 'hmac-sha256'

        with open(fname, 'w') as f:
            f.write(json.dumps(cfg, indent=2))

        set_sticky_bit(fname)

        return fname, cfg
Example #11
0
    def make_connection_file(self):
        """Generates a JSON config file, including the selection of random ports.
        """
        runtime_dir = jupyter_runtime_dir()
        ensure_dir_exists(runtime_dir)
        fname = os.path.join(runtime_dir, 'kernel-%s.json' % new_key())

        cfg = self.make_ports()
        cfg['ip'] = self.ip
        cfg['key'] = new_key()
        cfg['transport'] = self.transport
        cfg['signature_scheme'] = 'hmac-sha256'

        # Only ever write this file as user read/writeable
        # This would otherwise introduce a vulnerability as a file has secrets
        # which would let others execute arbitrarily code as you
        with secure_write(fname) as f:
            f.write(json.dumps(cfg, indent=2))

        set_sticky_bit(fname)

        return fname, cfg
Example #12
0
    def _create_environment(self):
        """
        Create the Jinja templating environment.
        """
        here = os.path.dirname(os.path.realpath(__file__))

        additional_paths = self.template_data_paths
        for path in additional_paths:
            try:
                ensure_dir_exists(path, mode=0o700)
            except OSError:
                pass

        paths = self.template_path + \
            additional_paths + \
            [os.path.join(here, self.default_template_path),
             os.path.join(here, self.template_skeleton_path)]

        loaders = self.extra_loaders + [
            ExtensionTolerantLoader(FileSystemLoader(paths),
                                    self.template_extension),
            DictLoader({self._raw_template_key: self.raw_template})
        ]
        environment = Environment(loader=ChoiceLoader(loaders),
                                  extensions=JINJA_EXTENSIONS)

        environment.globals['uuid4'] = uuid.uuid4

        # Add default filters to the Jinja2 environment
        for key, value in self.default_filters():
            self._register_filter(environment, key, value)

        # Load user filters.  Overwrite existing filters if need be.
        if self.filters:
            for key, user_filter in self.filters.items():
                self._register_filter(environment, key, user_filter)

        return environment
Example #13
0
def install_nbextension(path,
                        overwrite=False,
                        symlink=False,
                        user=False,
                        prefix=None,
                        nbextensions_dir=None,
                        destination=None,
                        verbose=DEPRECATED_ARGUMENT,
                        logger=None,
                        sys_prefix=False):
    """Install a Javascript extension for the notebook
    
    Stages files and/or directories into the nbextensions directory.
    By default, this compares modification time, and only stages files that need updating.
    If `overwrite` is specified, matching files are purged before proceeding.
    
    Parameters
    ----------
    
    path : path to file, directory, zip or tarball archive, or URL to install
        By default, the file will be installed with its base name, so '/path/to/foo'
        will install to 'nbextensions/foo'. See the destination argument below to change this.
        Archives (zip or tarballs) will be extracted into the nbextensions directory.
    overwrite : bool [default: False]
        If True, always install the files, regardless of what may already be installed.
    symlink : bool [default: False]
        If True, create a symlink in nbextensions, rather than copying files.
        Not allowed with URLs or archives. Windows support for symlinks requires
        Vista or above, Python 3, and a permission bit which only admin users
        have by default, so don't rely on it.
    user : bool [default: False]
        Whether to install to the user's nbextensions directory.
        Otherwise do a system-wide install (e.g. /usr/local/share/jupyter/nbextensions).
    prefix : str [optional]
        Specify install prefix, if it should differ from default (e.g. /usr/local).
        Will install to ``<prefix>/share/jupyter/nbextensions``
    nbextensions_dir : str [optional]
        Specify absolute path of nbextensions directory explicitly.
    destination : str [optional]
        name the nbextension is installed to.  For example, if destination is 'foo', then
        the source file will be installed to 'nbextensions/foo', regardless of the source name.
        This cannot be specified if an archive is given as the source.
    logger : Jupyter logger [optional]
        Logger instance to use
    """
    if verbose != DEPRECATED_ARGUMENT:
        import warnings
        warnings.warn(
            "`install_nbextension`'s `verbose` parameter is deprecated, it will have no effects and will be removed in Notebook 5.0",
            DeprecationWarning)

    # the actual path to which we eventually installed
    full_dest = None

    nbext = _get_nbextension_dir(user=user,
                                 sys_prefix=sys_prefix,
                                 prefix=prefix,
                                 nbextensions_dir=nbextensions_dir)
    # make sure nbextensions dir exists
    ensure_dir_exists(nbext)

    # forcing symlink parameter to False if os.symlink does not exist (e.g., on Windows machines running python 2)
    if not hasattr(os, 'symlink'):
        symlink = False

    if isinstance(path, (list, tuple)):
        raise TypeError(
            "path must be a string pointing to a single extension to install; call this function multiple times to install multiple extensions"
        )

    path = cast_unicode_py2(path)

    if path.startswith(('https://', 'http://')):
        if symlink:
            raise ValueError("Cannot symlink from URLs")
        # Given a URL, download it
        with TemporaryDirectory() as td:
            filename = urlparse(path).path.split('/')[-1]
            local_path = os.path.join(td, filename)
            if logger:
                logger.info("Downloading: %s -> %s" % (path, local_path))
            urlretrieve(path, local_path)
            # now install from the local copy
            full_dest = install_nbextension(local_path,
                                            overwrite=overwrite,
                                            symlink=symlink,
                                            nbextensions_dir=nbext,
                                            destination=destination,
                                            logger=logger)
    elif path.endswith('.zip') or _safe_is_tarfile(path):
        if symlink:
            raise ValueError("Cannot symlink from archives")
        if destination:
            raise ValueError("Cannot give destination for archives")
        if logger:
            logger.info("Extracting: %s -> %s" % (path, nbext))

        if path.endswith('.zip'):
            archive = zipfile.ZipFile(path)
        elif _safe_is_tarfile(path):
            archive = tarfile.open(path)
        archive.extractall(nbext)
        archive.close()
        # TODO: what to do here
        full_dest = None
    else:
        if not destination:
            destination = basename(normpath(path))
        destination = cast_unicode_py2(destination)
        full_dest = normpath(pjoin(nbext, destination))
        if overwrite and os.path.lexists(full_dest):
            if logger:
                logger.info("Removing: %s" % full_dest)
            if os.path.isdir(full_dest) and not os.path.islink(full_dest):
                shutil.rmtree(full_dest)
            else:
                os.remove(full_dest)

        if symlink:
            path = os.path.abspath(path)
            if not os.path.exists(full_dest):
                if logger:
                    logger.info("Symlinking: %s -> %s" % (full_dest, path))
                os.symlink(path, full_dest)
        elif os.path.isdir(path):
            path = pjoin(os.path.abspath(path), '')  # end in path separator
            for parent, dirs, files in os.walk(path):
                dest_dir = pjoin(full_dest, parent[len(path):])
                if not os.path.exists(dest_dir):
                    if logger:
                        logger.info("Making directory: %s" % dest_dir)
                    os.makedirs(dest_dir)
                for file_name in files:
                    src = pjoin(parent, file_name)
                    dest_file = pjoin(dest_dir, file_name)
                    _maybe_copy(src, dest_file, logger=logger)
        else:
            src = path
            _maybe_copy(src, full_dest, logger=logger)

    return full_dest
def touch(path, content=''):
    ensure_dir_exists(os.path.dirname(path))
    with open(path, 'w') as f:
        f.write(content)
Example #15
0
def touch(path, content=''):
    ensure_dir_exists(os.path.dirname(path))
    with open(path, 'w') as f:
        f.write(content)
def develop_labextension(path,
                         symlink=True,
                         overwrite=False,
                         user=False,
                         labextensions_dir=None,
                         destination=None,
                         logger=None,
                         sys_prefix=False):
    """Install a dynamic extension for JupyterLab
    
    Stages files and/or directories into the labextensions directory.
    By default, this compares modification time, and only stages files that need updating.
    If `overwrite` is specified, matching files are purged before proceeding.
    
    Parameters
    ----------
    
    path : path to file, directory, zip or tarball archive, or URL to install
        By default, the file will be installed with its base name, so '/path/to/foo'
        will install to 'labextensions/foo'. See the destination argument below to change this.
        Archives (zip or tarballs) will be extracted into the labextensions directory.
    user : bool [default: False]
        Whether to install to the user's labextensions directory.
        Otherwise do a system-wide install (e.g. /usr/local/share/jupyter/labextensions).
    overwrite : bool [default: False]
        If True, always install the files, regardless of what may already be installed.
    symlink : bool [default: True]
        If True, create a symlink in labextensions, rather than copying files.
        Windows support for symlinks requires a permission bit which only admin users
        have by default, so don't rely on it.
    labextensions_dir : str [optional]
        Specify absolute path of labextensions directory explicitly.
    destination : str [optional]
        name the labextension is installed to.  For example, if destination is 'foo', then
        the source file will be installed to 'labextensions/foo', regardless of the source name.
    logger : Jupyter logger [optional]
        Logger instance to use
    """
    # the actual path to which we eventually installed
    full_dest = None

    labext = _get_labextension_dir(user=user,
                                   sys_prefix=sys_prefix,
                                   labextensions_dir=labextensions_dir)
    # make sure labextensions dir exists
    ensure_dir_exists(labext)

    if isinstance(path, (list, tuple)):
        raise TypeError(
            "path must be a string pointing to a single extension to install; call this function multiple times to install multiple extensions"
        )

    path = cast_unicode_py2(path)

    if not destination:
        destination = basename(normpath(path))
    destination = cast_unicode_py2(destination)

    full_dest = normpath(pjoin(labext, destination))
    if overwrite and os.path.lexists(full_dest):
        if logger:
            logger.info("Removing: %s" % full_dest)
        if os.path.isdir(full_dest) and not os.path.islink(full_dest):
            shutil.rmtree(full_dest)
        else:
            os.remove(full_dest)

    # Make sure the parent directory exists
    os.makedirs(os.path.dirname(full_dest), exist_ok=True)

    if symlink:
        path = os.path.abspath(path)
        if not os.path.exists(full_dest):
            if logger:
                logger.info("Symlinking: %s -> %s" % (full_dest, path))
            os.symlink(path, full_dest)
        elif not os.path.islink(full_dest):
            raise ValueError("%s exists and is not a symlink" % path)

    elif os.path.isdir(path):
        path = pjoin(os.path.abspath(path), '')  # end in path separator
        for parent, dirs, files in os.walk(path):
            dest_dir = pjoin(full_dest, parent[len(path):])
            if not os.path.exists(dest_dir):
                if logger:
                    logger.info("Making directory: %s" % dest_dir)
                os.makedirs(dest_dir)
            for file_name in files:
                src = pjoin(parent, file_name)
                dest_file = pjoin(dest_dir, file_name)
                _maybe_copy(src, dest_file, logger=logger)
    else:
        src = path
        _maybe_copy(src, full_dest, logger=logger)

    return full_dest
Example #17
0
def install_nbextension(path, overwrite=False, symlink=False,
                        user=False, prefix=None, nbextensions_dir=None,
                        destination=None, verbose=DEPRECATED_ARGUMENT,
                        logger=None, sys_prefix=False
                        ):
    """Install a Javascript extension for the notebook
    
    Stages files and/or directories into the nbextensions directory.
    By default, this compares modification time, and only stages files that need updating.
    If `overwrite` is specified, matching files are purged before proceeding.
    
    Parameters
    ----------
    
    path : path to file, directory, zip or tarball archive, or URL to install
        By default, the file will be installed with its base name, so '/path/to/foo'
        will install to 'nbextensions/foo'. See the destination argument below to change this.
        Archives (zip or tarballs) will be extracted into the nbextensions directory.
    overwrite : bool [default: False]
        If True, always install the files, regardless of what may already be installed.
    symlink : bool [default: False]
        If True, create a symlink in nbextensions, rather than copying files.
        Not allowed with URLs or archives. Windows support for symlinks requires
        Vista or above, Python 3, and a permission bit which only admin users
        have by default, so don't rely on it.
    user : bool [default: False]
        Whether to install to the user's nbextensions directory.
        Otherwise do a system-wide install (e.g. /usr/local/share/jupyter/nbextensions).
    prefix : str [optional]
        Specify install prefix, if it should differ from default (e.g. /usr/local).
        Will install to ``<prefix>/share/jupyter/nbextensions``
    nbextensions_dir : str [optional]
        Specify absolute path of nbextensions directory explicitly.
    destination : str [optional]
        name the nbextension is installed to.  For example, if destination is 'foo', then
        the source file will be installed to 'nbextensions/foo', regardless of the source name.
        This cannot be specified if an archive is given as the source.
    logger : Jupyter logger [optional]
        Logger instance to use
    """
    if verbose != DEPRECATED_ARGUMENT:
        import warnings
        warnings.warn("`install_nbextension`'s `verbose` parameter is deprecated, it will have no effects and will be removed in Notebook 5.0", DeprecationWarning)

    # the actual path to which we eventually installed
    full_dest = None

    nbext = _get_nbextension_dir(user=user, sys_prefix=sys_prefix, prefix=prefix, nbextensions_dir=nbextensions_dir)
    # make sure nbextensions dir exists
    ensure_dir_exists(nbext)
    
    # forcing symlink parameter to False if os.symlink does not exist (e.g., on Windows machines running python 2)
    if not hasattr(os, 'symlink'):
        symlink = False
    
    if isinstance(path, (list, tuple)):
        raise TypeError("path must be a string pointing to a single extension to install; call this function multiple times to install multiple extensions")
    
    path = cast_unicode_py2(path)

    if path.startswith(('https://', 'http://')):
        if symlink:
            raise ValueError("Cannot symlink from URLs")
        # Given a URL, download it
        with TemporaryDirectory() as td:
            filename = urlparse(path).path.split('/')[-1]
            local_path = os.path.join(td, filename)
            if logger:
                logger.info("Downloading: %s -> %s" % (path, local_path))
            urlretrieve(path, local_path)
            # now install from the local copy
            full_dest = install_nbextension(local_path, overwrite=overwrite, symlink=symlink,
                nbextensions_dir=nbext, destination=destination, logger=logger)
    elif path.endswith('.zip') or _safe_is_tarfile(path):
        if symlink:
            raise ValueError("Cannot symlink from archives")
        if destination:
            raise ValueError("Cannot give destination for archives")
        if logger:
            logger.info("Extracting: %s -> %s" % (path, nbext))

        if path.endswith('.zip'):
            archive = zipfile.ZipFile(path)
        elif _safe_is_tarfile(path):
            archive = tarfile.open(path)
        archive.extractall(nbext)
        archive.close()
        # TODO: what to do here
        full_dest = None
    else:
        if not destination:
            destination = basename(normpath(path))
        destination = cast_unicode_py2(destination)
        full_dest = normpath(pjoin(nbext, destination))
        if overwrite and os.path.lexists(full_dest):
            if logger:
                logger.info("Removing: %s" % full_dest)
            if os.path.isdir(full_dest) and not os.path.islink(full_dest):
                shutil.rmtree(full_dest)
            else:
                os.remove(full_dest)

        if symlink:
            path = os.path.abspath(path)
            if not os.path.exists(full_dest):
                if logger:
                    logger.info("Symlinking: %s -> %s" % (full_dest, path))
                os.symlink(path, full_dest)
        elif os.path.isdir(path):
            path = pjoin(os.path.abspath(path), '') # end in path separator
            for parent, dirs, files in os.walk(path):
                dest_dir = pjoin(full_dest, parent[len(path):])
                if not os.path.exists(dest_dir):
                    if logger:
                        logger.info("Making directory: %s" % dest_dir)
                    os.makedirs(dest_dir)
                for file_name in files:
                    src = pjoin(parent, file_name)
                    dest_file = pjoin(dest_dir, file_name)
                    _maybe_copy(src, dest_file, logger=logger)
        else:
            src = path
            _maybe_copy(src, full_dest, logger=logger)

    return full_dest