def start(self): self.test_dir = td = TemporaryDirectory() self.env_patch = patch.dict( os.environ, { 'JUPYTER_CONFIG_DIR': pjoin(td.name, 'jupyter'), 'JUPYTER_DATA_DIR': pjoin(td.name, 'jupyter_data'), 'JUPYTER_RUNTIME_DIR': pjoin(td.name, 'jupyter_runtime'), 'IPYTHONDIR': pjoin(td.name, 'ipython'), }) self.env_patch.start() self.path_patch = patch.multiple( jupyter_core.paths, SYSTEM_JUPYTER_PATH=[pjoin(td.name, 'share', 'jupyter')], ENV_JUPYTER_PATH=[pjoin(td.name, 'env', 'share', 'jupyter')], SYSTEM_CONFIG_PATH=[pjoin(td.name, 'etc', 'jupyter')], ENV_CONFIG_PATH=[pjoin(td.name, 'env', 'etc', 'jupyter')], ) self.path_patch.start()
def test_good_symlink(self): with TemporaryDirectory() as td: cm = FileContentsManager(root_dir=td) parent = 'test good symlink' name = 'good symlink' path = '{0}/{1}'.format(parent, name) _make_dir(cm, parent) file_model = cm.new(path=parent + '/zfoo.txt') # create a good symlink self.symlink(cm, file_model['path'], path) symlink_model = cm.get(path, content=False) dir_model = cm.get(parent) self.assertEqual( sorted(dir_model['content'], key=lambda x: x['name']), [symlink_model, file_model], )
def test_server_info_file(): td = TemporaryDirectory() nbapp = NotebookApp(runtime_dir=td.name, log=logging.getLogger()) def get_servers(): return list(notebookapp.list_running_servers(nbapp.runtime_dir)) nbapp.initialize(argv=[]) nbapp.write_server_info_file() servers = get_servers() nt.assert_equal(len(servers), 1) nt.assert_equal(servers[0]['port'], nbapp.port) nt.assert_equal(servers[0]['url'], nbapp.connection_url) nbapp.remove_server_info_file() nt.assert_equal(get_servers(), []) # The ENOENT error should be silenced. nbapp.remove_server_info_file()
def test_log_collisions(self): app = MyApp() app.log = logging.getLogger() app.log.setLevel(logging.INFO) name = 'config' with TemporaryDirectory('_1') as td: with open(pjoin(td, name + '.py'), 'w') as f: f.write("get_config().Bar.b = 1") with open(pjoin(td, name + '.json'), 'w') as f: json.dump({'Bar': {'b': 2}}, f) with self.assertLogs(app.log, logging.WARNING) as captured: app.load_config_file(name, path=[td]) app.init_bar() assert app.bar.b == 2 output = '\n'.join(captured.output) assert 'Collision' in output assert '1 ignored, using 2' in output assert pjoin(td, name + '.py') in output assert pjoin(td, name + '.json') in output
def test_bad_symlink(self): with TemporaryDirectory() as td: cm = FileContentsManager(root_dir=td) path = 'test bad symlink' _make_dir(cm, path) file_model = cm.new_untitled(path=path, ext='.txt') # create a broken symlink self.symlink(cm, "target", '%s/%s' % (path, 'bad symlink')) model = cm.get(path) contents = { content['name']: content for content in model['content'] } self.assertTrue('untitled.txt' in contents) self.assertEqual(contents['untitled.txt'], file_model) # broken symlinks should still be shown in the contents manager self.assertTrue('bad symlink' in contents)
def setUp(self): """Build an isolated config environment.""" td = TemporaryDirectory() self.test_dir = py3compat.cast_unicode(td.name) self.data_dir = os.path.join(self.test_dir, 'data') self.config_dir = os.path.join(self.test_dir, 'config') self.system_data_dir = os.path.join(self.test_dir, 'system_data') self.system_path = [self.system_data_dir] # Use temp directory, not real user or system config paths self.patch_env = patch.dict('os.environ', { 'JUPYTER_CONFIG_DIR': self.config_dir, 'JUPYTER_DATA_DIR': self.data_dir, }) self.patch_env.start() self.patch_system_path = patch.object(nbextensions, 'SYSTEM_JUPYTER_PATH', self.system_path) self.patch_system_path.start()
def test_find_connection_file(): with TemporaryDirectory() as d: cf = 'kernel.json' app = DummyConsoleApp(runtime_dir=d, connection_file=cf) app.initialize() security_dir = app.runtime_dir profile_cf = os.path.join(security_dir, cf) with open(profile_cf, 'w') as f: f.write("{}") for query in ( 'kernel.json', 'kern*', '*ernel*', 'k*', ): assert connect.find_connection_file(query, path=security_dir) == profile_cf
def test_recursive_symlink(self): with TemporaryDirectory() as td: cm = FileContentsManager(root_dir=td) path = 'test recursive symlink' _make_dir(cm, path) os_path = cm._get_os_path(path) os.symlink("recursive", os.path.join(os_path, "recursive")) file_model = cm.new_untitled(path=path, ext='.txt') model = cm.get(path) contents = { content['name']: content for content in model['content'] } self.assertIn('untitled.txt', contents) self.assertEqual(contents['untitled.txt'], file_model) # recursive symlinks should not be shown in the contents manager self.assertNotIn('recursive', contents)
def from_notebook_node(self, nb, resources=None, **kw): if not hasattr(self, "_ipynb_file"): self._ipynb_file = None url_root = "http://{}".format("localhost:{}".format(self.port)) output_root = Path(resources["output_files_dir"]) lab_path = self.lab_path() static_path = Path(notebook.__file__).parent / "static" nb_names = [ resources["metadata"]["name"] ] + [ str(ef)[:-6] for ef in self.extra_files if ef.name.endswith('.ipynb') ] urls = [ "lab" ] + [ "api/contents/{}.ipynb".format(nb_name) for nb_name in nb_names ] + [ "api/contents/{}".format(ef) for ef in self.extra_files if not ef.name.endswith(".ipynb") ] + self.extra_urls with TemporaryDirectory() as tmpdir: urls += list(self.prepare_contents(tmpdir)) urls += list(self.prepare_notebooks(tmpdir, nb, nb_names)) self.fetch_all(tmpdir, url_root, urls, resources) self.copy_assets(output_root, lab_path, static_path) self.fix_urls(output_root, nb_names) self.fake_apis(output_root) self.fake_home(output_root) langinfo = nb.metadata.get('language_info', {}) lexer = langinfo.get('pygments_lexer', langinfo.get('name', None)) self.register_filter('highlight_code', Highlight2HTML(pygments_lexer=lexer, parent=self)) return super(HTMLExporter, self).from_notebook_node( nb, resources, **kw)
def test_403(self): if hasattr(os, 'getuid'): if os.getuid() == 0: raise SkipTest("Can't test permissions as root") if sys.platform.startswith('win'): raise SkipTest("Can't test permissions on Windows") with TemporaryDirectory() as td: cm = FileContentsManager(root_dir=td) model = cm.new_untitled(type='file') os_path = cm._get_os_path(model['path']) os.chmod(os_path, 0o400) try: with cm.open(os_path, 'w') as f: f.write(u"don't care") except HTTPError as e: self.assertEqual(e.status_code, 403) else: self.fail("Should have raised HTTPError(403)")
def test_get_os_path(self): # full filesystem path should be returned with correct operating system # separators. with TemporaryDirectory() as td: root = td fm = FileContentsManager(root_dir=root) path = fm._get_os_path('/path/to/notebook/test.ipynb') rel_path_list = '/path/to/notebook/test.ipynb'.split('/') fs_path = os.path.join(fm.root_dir, *rel_path_list) self.assertEqual(path, fs_path) fm = FileContentsManager(root_dir=root) path = fm._get_os_path('test.ipynb') fs_path = os.path.join(fm.root_dir, 'test.ipynb') self.assertEqual(path, fs_path) fm = FileContentsManager(root_dir=root) path = fm._get_os_path('////test.ipynb') fs_path = os.path.join(fm.root_dir, 'test.ipynb') self.assertEqual(path, fs_path)
def install_extension(self, extension, existing=None): """Install an extension package into JupyterLab. The extension is first validated. """ extension = _normalize_path(extension) extensions = self.info['extensions'] # Check for a core extensions. if extension in self.info['core_extensions']: config = self._read_build_config() uninstalled = config.get('uninstalled_core_extensions', []) if extension in uninstalled: uninstalled.remove(extension) config['uninstalled_core_extensions'] = uninstalled self._write_build_config(config) return # Create the app dirs if needed. self._ensure_app_dirs() # Install the package using a temporary directory. with TemporaryDirectory() as tempdir: info = self._install_extension(extension, tempdir) name = info['name'] # Local directories get name mangled and stored in metadata. if info['is_dir']: config = self._read_build_config() local = config.setdefault('local_extensions', dict()) local[name] = info['source'] self._write_build_config(config) # Remove an existing extension with the same name and different path if name in extensions: other = extensions[name] if other['path'] != info['path'] and other['location'] == 'app': os.remove(other['path']) return True
def _update_local(self, name, source, dname, data, dtype): """Update a local dependency. Return `True` if changed. """ # Extract the package in a temporary directory. existing = data['filename'] with TemporaryDirectory() as tempdir: info = self._extract_package(source, tempdir) # Bail if the file content has not changed. if info['filename'] == existing: return existing shutil.move(info['path'], pjoin(dname, info['filename'])) # Remove the existing tarball and return the new file name. if existing: os.remove(pjoin(dname, existing)) data['filename'] = info['filename'] data['path'] = pjoin(data['tar_dir'], data['filename']) return info['filename']
def test_is_hidden(): with TemporaryDirectory() as root: subdir1 = os.path.join(root, 'subdir') os.makedirs(subdir1) nt.assert_equal(is_hidden(subdir1, root), False) nt.assert_equal(is_file_hidden(subdir1), False) subdir2 = os.path.join(root, '.subdir2') os.makedirs(subdir2) nt.assert_equal(is_hidden(subdir2, root), True) nt.assert_equal(is_file_hidden(subdir2), True) subdir34 = os.path.join(root, 'subdir3', '.subdir4') os.makedirs(subdir34) nt.assert_equal(is_hidden(subdir34, root), True) nt.assert_equal(is_hidden(subdir34), True) subdir56 = os.path.join(root, '.subdir5', 'subdir6') os.makedirs(subdir56) nt.assert_equal(is_hidden(subdir56, root), True) nt.assert_equal(is_hidden(subdir56), True) nt.assert_equal(is_file_hidden(subdir56), False) nt.assert_equal(is_file_hidden(subdir56, os.stat(subdir56)), False)
def test_escape_root(self): with TemporaryDirectory() as td: cm = FileContentsManager(root_dir=td) # make foo, bar next to root with open(os.path.join(cm.root_dir, '..', 'foo'), 'w') as f: f.write('foo') with open(os.path.join(cm.root_dir, '..', 'bar'), 'w') as f: f.write('bar') with self.assertRaisesHTTPError(404): cm.get('..') with self.assertRaisesHTTPError(404): cm.get('foo/../../../bar') with self.assertRaisesHTTPError(404): cm.delete('../foo') with self.assertRaisesHTTPError(404): cm.rename('../foo', '../bar') with self.assertRaisesHTTPError(404): cm.save(model={ 'type': 'file', 'content': u'', 'format': 'text', }, path='../foo')
def test_find_connection_file(): cfg = Config() with TemporaryDirectory() as d: cfg.ProfileDir.location = d cf = 'kernel.json' app = DummyConsoleApp(config=cfg, connection_file=cf) app.initialize() security_dir = app.runtime_dir profile_cf = os.path.join(security_dir, cf) with open(profile_cf, 'w') as f: f.write("{}") for query in ( 'kernel.json', 'kern*', '*ernel*', 'k*', ): nt.assert_equal(connect.find_connection_file(query, path=security_dir), profile_cf) JupyterApp._instance = None
def test_server_info_file(): import threading, tornado.ioloop as iom, tornado.platform.asyncio as torio td = TemporaryDirectory() if iom.asyncio is not None: iom.asyncio.set_event_loop_policy(torio.AnyThreadEventLoopPolicy()) iom.IOLoop.configure("tornado.platform.asyncio.AsyncIOLoop") nbapp = NotebookApp(runtime_dir=td.name, log=logging.getLogger()) nbapp.initialize(argv=[]) nbapp.io_loop = iom.IOLoop.current() nbapp.open_browser = False super(NotebookApp, nbapp).start() nbapp.write_server_info_file() def check_thread(): try: servers = list(notebookapp.list_running_servers(nbapp.runtime_dir)) nt.assert_equal(len(servers), 1) nt.assert_equal(servers[0]['port'], nbapp.port) nt.assert_equal(servers[0]['url'], nbapp.connection_url) finally: nbapp.stop() nbapp.io_loop.add_callback(nbapp.io_loop.run_in_executor, executor=None, func=check_thread) if sys.platform.startswith("win"): pc = iom.PeriodicCallback(lambda: None, 5000) pc.start() try: nbapp.io_loop.start() except KeyboardInterrupt: print("Interrupted...") finally: nbapp.remove_server_info_file()
def test_loaded_config_files(self): app = MyApp() app.log = logging.getLogger() name = 'config.py' with TemporaryDirectory('_1') as td1: config_file = pjoin(td1, name) with open(config_file, 'w') as f: f.writelines(["c.MyApp.running = True\n"]) app.load_config_file(name, path=[td1]) self.assertEqual(len(app.loaded_config_files), 1) self.assertEquals(app.loaded_config_files[0], config_file) app.start() self.assertEqual(app.running, True) # emulate an app that allows dynamic updates and update config file with open(config_file, 'w') as f: f.writelines(["c.MyApp.running = False\n"]) # reload and verify update, and that loaded_configs was not increased app.load_config_file(name, path=[td1]) self.assertEqual(len(app.loaded_config_files), 1) self.assertEqual(app.running, False) # Attempt to update, ensure error... with self.assertRaises(AttributeError): app.loaded_config_files = "/foo" # ensure it can't be udpated via append app.loaded_config_files.append("/bar") self.assertEqual(len(app.loaded_config_files), 1) # repeat to ensure no unexpected changes occurred app.load_config_file(name, path=[td1]) self.assertEqual(len(app.loaded_config_files), 1) self.assertEqual(app.running, False)
def test_atomic_writing_newlines(): with TemporaryDirectory() as td: path = os.path.join(td, 'testfile') lf = u'a\nb\nc\n' plat = lf.replace(u'\n', os.linesep) crlf = lf.replace(u'\n', u'\r\n') # test default with stdlib_io.open(path, 'w') as f: f.write(lf) with stdlib_io.open(path, 'r', newline='') as f: read = f.read() nt.assert_equal(read, plat) # test newline=LF with stdlib_io.open(path, 'w', newline='\n') as f: f.write(lf) with stdlib_io.open(path, 'r', newline='') as f: read = f.read() nt.assert_equal(read, lf) # test newline=CRLF with atomic_writing(path, newline='\r\n') as f: f.write(lf) with stdlib_io.open(path, 'r', newline='') as f: read = f.read() nt.assert_equal(read, crlf) # test newline=no convert text = u'crlf\r\ncr\rlf\n' with atomic_writing(path, newline='') as f: f.write(text) with stdlib_io.open(path, 'r', newline='') as f: read = f.read() nt.assert_equal(read, text)
def test_ipython_cli_priority(self): # this test is almost entirely redundant with above, # but we can keep it around in case of subtle issues creeping into # the exact sequence IPython follows. name = 'config.py' class TestApp(Application): value = Unicode().tag(config=True) config_file_loaded = Bool().tag(config=True) aliases = {'v': 'TestApp.value'} app = TestApp() with TemporaryDirectory() as td: config_file = pjoin(td, name) with open(config_file, 'w') as f: f.writelines([ "c.TestApp.value = 'config file'\n", "c.TestApp.config_file_loaded = True\n" ]) # follow IPython's config-loading sequence to ensure CLI priority is preserved app.parse_command_line(['--v=cli']) # this is where IPython makes a mistake: # it assumes app.config will not be modified, # and storing a reference is storing a copy cli_config = app.config assert 'value' in app.config.TestApp assert app.config.TestApp.value == 'cli' assert app.value == 'cli' app.load_config_file(name, path=[td]) assert app.config_file_loaded # enforce cl-opts override config file opts: # this is where IPython makes a mistake: it assumes # that cl_config is a different object, but it isn't. app.update_config(cli_config) assert app.config.TestApp.value == 'cli' assert app.value == 'cli'
def link_package(self, path): """Link a package at the given path. """ path = _normalize_path(path) if not osp.exists(path) or not osp.isdir(path): msg = 'Can install "%s" only link local directories' raise ValueError(msg % path) with TemporaryDirectory() as tempdir: info = self._extract_package(path, tempdir) messages = _validate_extension(info['data']) if not messages: return self.install_extension(path) # Warn that it is a linked package. self.logger.warn('Installing %s as a linked package:', path) [self.logger.warn(m) for m in messages] # Add to metadata. config = self._read_build_config() linked = config.setdefault('linked_packages', dict()) linked[info['name']] = info['source'] self._write_build_config(config)
def test_no_create_nb_dir(): with TemporaryDirectory() as td: nbdir = os.path.join(td, 'notebooks') app = NotebookApp() with nt.assert_raises(TraitError): app.notebook_dir = nbdir
def test_missing_nb_dir(): with TemporaryDirectory() as td: nbdir = os.path.join(td, 'notebook', 'dir', 'is', 'missing') app = NotebookApp() with nt.assert_raises(TraitError): app.notebook_dir = nbdir
def test_nb_dir(): with TemporaryDirectory() as td: app = NotebookApp(notebook_dir=td) nt.assert_equal(app.notebook_dir, td)
def test_root_dir(self): with TemporaryDirectory() as td: fm = FileContentsManager(root_dir=td) self.assertEqual(fm.root_dir, td)
def test_missing_root_dir(self): with TemporaryDirectory() as td: root = os.path.join(td, 'notebook', 'dir', 'is', 'missing') self.assertRaises(TraitError, FileContentsManager, root_dir=root)
def test_nb_dir_with_slash(): with TemporaryDirectory(suffix="_slash" + os.sep) as td: app = NotebookApp(notebook_dir=td) nt.assert_false(app.notebook_dir.endswith(os.sep))
def setup_class(cls): cls.tmp_dir = TemporaryDirectory() def tmp(*parts): path = os.path.join(cls.tmp_dir.name, *parts) try: os.makedirs(path) except OSError as e: if e.errno != errno.EEXIST: raise return path cls.home_dir = tmp('home') data_dir = cls.data_dir = tmp('data') config_dir = cls.config_dir = tmp('config') runtime_dir = cls.runtime_dir = tmp('runtime') cls.notebook_dir = tmp('notebooks') cls.env_patch = patch.dict('os.environ', { 'HOME': cls.home_dir, 'PYTHONPATH': os.pathsep.join(sys.path), 'IPYTHONDIR': pjoin(cls.home_dir, '.ipython'), 'JUPYTER_NO_CONFIG': '1', # needed in the future 'JUPYTER_CONFIG_DIR': config_dir, 'JUPYTER_DATA_DIR': data_dir, 'JUPYTER_RUNTIME_DIR': runtime_dir, }) cls.env_patch.start() cls.path_patch = patch.multiple( jupyter_core.paths, SYSTEM_JUPYTER_PATH=[tmp('share', 'jupyter')], ENV_JUPYTER_PATH=[tmp('env', 'share', 'jupyter')], SYSTEM_CONFIG_PATH=[tmp('etc', 'jupyter')], ENV_CONFIG_PATH=[tmp('env', 'etc', 'jupyter')], ) cls.path_patch.start() config = cls.config or Config() config.NotebookNotary.db_file = ':memory:' cls.token = hexlify(os.urandom(4)).decode('ascii') started = Event() lab_config = LabConfig(schemas_dir=pjoin(here, 'schemas'), user_settings_dir=tmp('user_settings')) def start_thread(): app = cls.notebook = LabLauncherApp( port=cls.port, port_retries=0, open_browser=False, config_dir=cls.config_dir, data_dir=cls.data_dir, runtime_dir=cls.runtime_dir, notebook_dir=cls.notebook_dir, base_url=cls.url_prefix, config=config, allow_root=True, token=cls.token, lab_config=lab_config ) # don't register signal handler during tests app.init_signal = lambda: None # clear log handlers and propagate to root for nose to capture it # needs to be redone after initialize, which reconfigures logging app.log.propagate = True app.log.handlers = [] app.initialize(argv=[]) app.log.propagate = True app.log.handlers = [] loop = IOLoop.current() loop.add_callback(started.set) try: app.start() finally: # set the event, so failure to start doesn't cause a hang started.set() app.session_manager.close() cls.notebook_thread = Thread(target=start_thread) cls.notebook_thread.daemon = True cls.notebook_thread.start() started.wait() cls.wait_until_alive()
def tempdir(self): td = TemporaryDirectory() self.tempdirs.append(td) return py3compat.cast_unicode(td.name)
def setUp(self): self._temp_dir = TemporaryDirectory() self.td = self._temp_dir.name self.contents_manager = LargeFileManager(root_dir=self.td)