def test_get_connection_info(): with TemporaryDirectory() as d: cf = os.path.join(d, 'kernel.json') connect.write_connection_file(cf, **sample_info) json_info = connect.get_connection_info(cf) info = connect.get_connection_info(cf, unpack=True) nt.assert_equal(type(json_info), type("")) sub_info = {k:v for k,v in info.items() if k in sample_info} nt.assert_equal(sub_info, sample_info) info2 = json.loads(json_info) info2['key'] = str_to_bytes(info2['key']) sub_info2 = {k:v for k,v in info.items() if k in sample_info} nt.assert_equal(sub_info2, sample_info)
def test_overwrite_file(self): with TemporaryDirectory() as d: fname = u'ƒ.js' src = pjoin(d, fname) with open(src, 'w') as f: f.write('first') mtime = touch(src) dest = pjoin(self.system_nbext, fname) install_nbextension(src) with open(src, 'w') as f: f.write('overwrite') mtime = touch(src, mtime - 100) install_nbextension(src, overwrite=True) with open(dest) as f: self.assertEqual(f.read(), 'overwrite')
def test_get_connection_info(): with TemporaryDirectory() as d: cf = os.path.join(d, 'kernel.json') connect.write_connection_file(cf, **sample_info) json_info = connect.get_connection_info(cf) info = connect.get_connection_info(cf, unpack=True) assert isinstance(json_info, str) sub_info = {k: v for k, v in info.items() if k in sample_info} assert sub_info == sample_info info2 = json.loads(json_info) info2['key'] = str_to_bytes(info2['key']) sub_info2 = {k: v for k, v in info.items() if k in sample_info} assert sub_info2 == sample_info
def test_load_connection_file_session(): """test load_connection_file() after """ session = Session() app = DummyConsoleApp(session=Session()) app.initialize(argv=[]) session = app.session with TemporaryDirectory() as d: cf = os.path.join(d, 'kernel.json') connect.write_connection_file(cf, **sample_info) app.connection_file = cf app.load_connection_file() nt.assert_equal(session.key, sample_info['key']) nt.assert_equal(session.signature_scheme, sample_info['signature_scheme'])
def test_save_history(): # Saving history from the kernel with %hist -f was failing because of # unicode problems on Python 2. with kernel() as kc, TemporaryDirectory() as td: file = os.path.join(td, 'hist.out') execute('a=1', kc=kc) wait_for_idle(kc) execute('b="abcþ"', kc=kc) wait_for_idle(kc) _, reply = execute("%hist -f " + file, kc=kc) assert reply['status'] == 'ok' with io.open(file, encoding='utf-8') as f: content = f.read() assert 'a=1' in content assert 'b="abcþ"' in content
def test_checkpoint_subdir(self): subd = u'sub ∂ir' cp_name = 'test-cp.ipynb' with TemporaryDirectory() as td: root = td os.mkdir(os.path.join(td, subd)) fm = FileContentsManager(root_dir=root) cpm = fm.checkpoints cp_dir = cpm.checkpoint_path('cp', 'test.ipynb') cp_subdir = cpm.checkpoint_path('cp', '/%s/test.ipynb' % subd) self.assertNotEqual(cp_dir, cp_subdir) self.assertEqual(cp_dir, os.path.join(root, cpm.checkpoint_dir, cp_name)) self.assertEqual(cp_subdir, os.path.join(root, subd, cpm.checkpoint_dir, cp_name))
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 link_package(self, path): """Link a package at the given path. """ if not osp.exists(path) or not osp.isdir(path): raise ValueError('Can only link local directories') with TemporaryDirectory() as tempdir: info = self._extract_package(path, tempdir) if _is_extension(info['data']): return self.install_extension(path) # 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_update_file(self): with TemporaryDirectory() as d: fname = u'ƒ.js' src = pjoin(d, fname) with open(src, 'w') as f: f.write('first') mtime = touch(src) install_nbextension(src) self.assert_installed(fname) dest = pjoin(self.system_nbext, fname) old_mtime = os.stat(dest).st_mtime with open(src, 'w') as f: f.write('overwrite') touch(src, mtime + 10) install_nbextension(src) with open(dest) as f: self.assertEqual(f.read(), 'overwrite')
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 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()
def test_overwrite_broken_symlink(self): with TemporaryDirectory() as d: f = u'ƒ.js' f2 = u'ƒ2.js' src = pjoin(d, f) src2 = pjoin(d, f2) touch(src) install_nbextension(src, symlink=True) os.rename(src, src2) install_nbextension(src2, symlink=True, overwrite=True, destination=f) dest = pjoin(self.system_nbext, f) assert os.path.islink(dest) link = os.readlink(dest) self.assertEqual(link, src2)
def test_dynamic_updates(self): app = self.app # Get the actual EnterpriseGatewayApp instance s1 = time.time() name = app.config_file_name + '.py' with TemporaryDirectory('_1') as td1: os.environ['JUPYTER_CONFIG_DIR'] = td1 config_file = pjoin(td1, name) with open(config_file, 'w') as f: f.writelines([ "c.EnterpriseGatewayApp.impersonation_enabled = False\n", "c.AsyncMappingKernelManager.cull_connected = False\n" ]) # app.jupyter_path.append(td1) app.load_config_file() app.add_dynamic_configurable("EnterpriseGatewayApp", app) app.add_dynamic_configurable("RemoteMappingKernelManager", app.kernel_manager) with self.assertRaises(RuntimeError): app.add_dynamic_configurable("Bogus", app.log) self.assertEqual(app.impersonation_enabled, False) self.assertEqual(app.kernel_manager.cull_connected, False) # Ensure file update doesn't happen during same second as initial value. # This is necessary on test systems that don't have finer-grained # timestamps (of less than a second). s2 = time.time() if s2 - s1 < 1.0: time.sleep(1.0 - (s2 - s1)) # update config file with open(config_file, 'w') as f: f.writelines([ "c.EnterpriseGatewayApp.impersonation_enabled = True\n", "c.AsyncMappingKernelManager.cull_connected = True\n" ]) # trigger reload and verify updates app.update_dynamic_configurables() self.assertEqual(app.impersonation_enabled, True) self.assertEqual(app.kernel_manager.cull_connected, True) # repeat to ensure no unexpected changes occurred app.update_dynamic_configurables() self.assertEqual(app.impersonation_enabled, True) self.assertEqual(app.kernel_manager.cull_connected, True)
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 check_handler_with_file(self, inpath, handler): shell = self.shell configname = '{0}_image_handler'.format(handler) funcname = 'handle_image_{0}'.format(handler) assert hasattr(shell, configname) assert hasattr(shell, funcname) with TemporaryDirectory() as tmpdir: outpath = os.path.join(tmpdir, 'data') cmd = [sys.executable, SCRIPT_PATH, inpath, outpath] setattr(shell, configname, cmd) getattr(shell, funcname)(self.data, self.mime) # cmd is called and file is closed. So it's safe to open now. with open(outpath, 'rb') as file: transferred = file.read() self.assertEqual(transferred, self.raw)
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 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_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_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 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_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 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 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_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_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_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_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 setUp(self): self._temp_dir = TemporaryDirectory() self.td = self._temp_dir.name self.contents_manager = FileContentsManager( root_dir=self.td, )
class TestContentsManager(TestCase): @contextmanager def assertRaisesHTTPError(self, status, msg=None): msg = msg or "Should have raised HTTPError(%i)" % status try: yield except HTTPError as e: self.assertEqual(e.status_code, status) else: self.fail(msg) def make_populated_dir(self, api_path): cm = self.contents_manager self.make_dir(api_path) cm.new(path="/".join([api_path, "nb.ipynb"])) cm.new(path="/".join([api_path, "file.txt"])) def check_populated_dir_files(self, api_path): dir_model = self.contents_manager.get(api_path) self.assertEqual(dir_model['path'], api_path) self.assertEqual(dir_model['type'], "directory") for entry in dir_model['content']: if entry['type'] == "directory": continue elif entry['type'] == "file": self.assertEqual(entry['name'], "file.txt") complete_path = "/".join([api_path, "file.txt"]) self.assertEqual(entry["path"], complete_path) elif entry['type'] == "notebook": self.assertEqual(entry['name'], "nb.ipynb") complete_path = "/".join([api_path, "nb.ipynb"]) self.assertEqual(entry["path"], complete_path) def setUp(self): self._temp_dir = TemporaryDirectory() self.td = self._temp_dir.name self.contents_manager = FileContentsManager( root_dir=self.td, ) def tearDown(self): self._temp_dir.cleanup() def make_dir(self, api_path): """make a subdirectory at api_path override in subclasses if contents are not on the filesystem. """ _make_dir(self.contents_manager, api_path) def add_code_cell(self, nb): output = nbformat.new_output("display_data", {'application/javascript': "alert('hi');"}) cell = nbformat.new_code_cell("print('hi')", outputs=[output]) nb.cells.append(cell) def new_notebook(self): cm = self.contents_manager model = cm.new_untitled(type='notebook') name = model['name'] path = model['path'] full_model = cm.get(path) nb = full_model['content'] nb['metadata']['counter'] = int(1e6 * time.time()) self.add_code_cell(nb) cm.save(full_model, path) return nb, name, path def test_new_untitled(self): cm = self.contents_manager # Test in root directory model = cm.new_untitled(type='notebook') assert isinstance(model, dict) self.assertIn('name', model) self.assertIn('path', model) self.assertIn('type', model) self.assertEqual(model['type'], 'notebook') self.assertEqual(model['name'], 'Untitled.ipynb') self.assertEqual(model['path'], 'Untitled.ipynb') # Test in sub-directory model = cm.new_untitled(type='directory') assert isinstance(model, dict) self.assertIn('name', model) self.assertIn('path', model) self.assertIn('type', model) self.assertEqual(model['type'], 'directory') self.assertEqual(model['name'], 'Untitled Folder') self.assertEqual(model['path'], 'Untitled Folder') sub_dir = model['path'] model = cm.new_untitled(path=sub_dir) assert isinstance(model, dict) self.assertIn('name', model) self.assertIn('path', model) self.assertIn('type', model) self.assertEqual(model['type'], 'file') self.assertEqual(model['name'], 'untitled') self.assertEqual(model['path'], '%s/untitled' % sub_dir) # Test with a compound extension model = cm.new_untitled(path=sub_dir, ext='.foo.bar') self.assertEqual(model['name'], 'untitled.foo.bar') model = cm.new_untitled(path=sub_dir, ext='.foo.bar') self.assertEqual(model['name'], 'untitled1.foo.bar') def test_modified_date(self): cm = self.contents_manager # Create a new notebook. nb, name, path = self.new_notebook() model = cm.get(path) # Add a cell and save. self.add_code_cell(model['content']) cm.save(model, path) # Reload notebook and verify that last_modified incremented. saved = cm.get(path) self.assertGreaterEqual(saved['last_modified'], model['last_modified']) # Move the notebook and verify that last_modified stayed the same. # (The frontend fires a warning if last_modified increases on the # renamed file.) new_path = 'renamed.ipynb' cm.rename(path, new_path) renamed = cm.get(new_path) self.assertGreaterEqual( renamed['last_modified'], saved['last_modified'], ) def test_get(self): cm = self.contents_manager # Create a notebook model = cm.new_untitled(type='notebook') name = model['name'] path = model['path'] # Check that we 'get' on the notebook we just created model2 = cm.get(path) assert isinstance(model2, dict) self.assertIn('name', model2) self.assertIn('path', model2) self.assertEqual(model['name'], name) self.assertEqual(model['path'], path) nb_as_file = cm.get(path, content=True, type='file') self.assertEqual(nb_as_file['path'], path) self.assertEqual(nb_as_file['type'], 'file') self.assertEqual(nb_as_file['format'], 'text') self.assertNotIsInstance(nb_as_file['content'], dict) nb_as_bin_file = cm.get(path, content=True, type='file', format='base64') self.assertEqual(nb_as_bin_file['format'], 'base64') # Test in sub-directory sub_dir = '/foo/' self.make_dir('foo') model = cm.new_untitled(path=sub_dir, ext='.ipynb') model2 = cm.get(sub_dir + name) assert isinstance(model2, dict) self.assertIn('name', model2) self.assertIn('path', model2) self.assertIn('content', model2) self.assertEqual(model2['name'], 'Untitled.ipynb') self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name)) # Test with a regular file. file_model_path = cm.new_untitled(path=sub_dir, ext='.txt')['path'] file_model = cm.get(file_model_path) self.assertDictContainsSubset( { 'content': u'', 'format': u'text', 'mimetype': u'text/plain', 'name': u'untitled.txt', 'path': u'foo/untitled.txt', 'type': u'file', 'writable': True, }, file_model, ) self.assertIn('created', file_model) self.assertIn('last_modified', file_model) # Test getting directory model # Create a sub-sub directory to test getting directory contents with a # subdir. self.make_dir('foo/bar') dirmodel = cm.get('foo') self.assertEqual(dirmodel['type'], 'directory') self.assertIsInstance(dirmodel['content'], list) self.assertEqual(len(dirmodel['content']), 3) self.assertEqual(dirmodel['path'], 'foo') self.assertEqual(dirmodel['name'], 'foo') # Directory contents should match the contents of each individual entry # when requested with content=False. model2_no_content = cm.get(sub_dir + name, content=False) file_model_no_content = cm.get(u'foo/untitled.txt', content=False) sub_sub_dir_no_content = cm.get('foo/bar', content=False) self.assertEqual(sub_sub_dir_no_content['path'], 'foo/bar') self.assertEqual(sub_sub_dir_no_content['name'], 'bar') for entry in dirmodel['content']: # Order isn't guaranteed by the spec, so this is a hacky way of # verifying that all entries are matched. if entry['path'] == sub_sub_dir_no_content['path']: self.assertEqual(entry, sub_sub_dir_no_content) elif entry['path'] == model2_no_content['path']: self.assertEqual(entry, model2_no_content) elif entry['path'] == file_model_no_content['path']: self.assertEqual(entry, file_model_no_content) else: self.fail("Unexpected directory entry: %s" % entry()) with self.assertRaises(HTTPError): cm.get('foo', type='file') def test_update(self): cm = self.contents_manager # Create a notebook model = cm.new_untitled(type='notebook') name = model['name'] path = model['path'] # Change the name in the model for rename model['path'] = 'test.ipynb' model = cm.update(model, path) assert isinstance(model, dict) self.assertIn('name', model) self.assertIn('path', model) self.assertEqual(model['name'], 'test.ipynb') # Make sure the old name is gone self.assertRaises(HTTPError, cm.get, path) # Test in sub-directory # Create a directory and notebook in that directory sub_dir = '/foo/' self.make_dir('foo') model = cm.new_untitled(path=sub_dir, type='notebook') path = model['path'] # Change the name in the model for rename d = path.rsplit('/', 1)[0] new_path = model['path'] = d + '/test_in_sub.ipynb' model = cm.update(model, path) assert isinstance(model, dict) self.assertIn('name', model) self.assertIn('path', model) self.assertEqual(model['name'], 'test_in_sub.ipynb') self.assertEqual(model['path'], new_path) # Make sure the old name is gone self.assertRaises(HTTPError, cm.get, path) def test_save(self): cm = self.contents_manager # Create a notebook model = cm.new_untitled(type='notebook') name = model['name'] path = model['path'] # Get the model with 'content' full_model = cm.get(path) # Save the notebook model = cm.save(full_model, path) assert isinstance(model, dict) self.assertIn('name', model) self.assertIn('path', model) self.assertEqual(model['name'], name) self.assertEqual(model['path'], path) # Test in sub-directory # Create a directory and notebook in that directory sub_dir = '/foo/' self.make_dir('foo') model = cm.new_untitled(path=sub_dir, type='notebook') name = model['name'] path = model['path'] model = cm.get(path) # Change the name in the model for rename model = cm.save(model, path) assert isinstance(model, dict) self.assertIn('name', model) self.assertIn('path', model) self.assertEqual(model['name'], 'Untitled.ipynb') self.assertEqual(model['path'], 'foo/Untitled.ipynb') def test_delete(self): cm = self.contents_manager # Create a notebook nb, name, path = self.new_notebook() # Delete the notebook cm.delete(path) # Check that deleting a non-existent path raises an error. self.assertRaises(HTTPError, cm.delete, path) # Check that a 'get' on the deleted notebook raises and error self.assertRaises(HTTPError, cm.get, path) def test_rename(self): cm = self.contents_manager # Create a new notebook nb, name, path = self.new_notebook() # Rename the notebook cm.rename(path, "changed_path") # Attempting to get the notebook under the old name raises an error self.assertRaises(HTTPError, cm.get, path) # Fetching the notebook under the new name is successful assert isinstance(cm.get("changed_path"), dict) # Ported tests on nested directory renaming from pgcontents all_dirs = ['foo', 'bar', 'foo/bar', 'foo/bar/foo', 'foo/bar/foo/bar'] unchanged_dirs = all_dirs[:2] changed_dirs = all_dirs[2:] for _dir in all_dirs: self.make_populated_dir(_dir) self.check_populated_dir_files(_dir) # Renaming to an existing directory should fail for src, dest in combinations(all_dirs, 2): with self.assertRaisesHTTPError(409): cm.rename(src, dest) # Creating a notebook in a non_existant directory should fail with self.assertRaisesHTTPError(404): cm.new_untitled("foo/bar_diff", ext=".ipynb") cm.rename("foo/bar", "foo/bar_diff") # Assert that unchanged directories remain so for unchanged in unchanged_dirs: self.check_populated_dir_files(unchanged) # Assert changed directories can no longer be accessed under old names for changed_dirname in changed_dirs: with self.assertRaisesHTTPError(404): cm.get(changed_dirname) new_dirname = changed_dirname.replace("foo/bar", "foo/bar_diff", 1) self.check_populated_dir_files(new_dirname) # Created a notebook in the renamed directory should work cm.new_untitled("foo/bar_diff", ext=".ipynb") def test_delete_root(self): cm = self.contents_manager with self.assertRaises(HTTPError) as err: cm.delete('') self.assertEqual(err.exception.status_code, 400) def test_copy(self): cm = self.contents_manager parent = u'å b' name = u'nb √.ipynb' path = u'{0}/{1}'.format(parent, name) self.make_dir(parent) orig = cm.new(path=path) # copy with unspecified name copy = cm.copy(path) self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy1.ipynb')) # copy with specified name copy2 = cm.copy(path, u'å b/copy 2.ipynb') self.assertEqual(copy2['name'], u'copy 2.ipynb') self.assertEqual(copy2['path'], u'å b/copy 2.ipynb') # copy with specified path copy2 = cm.copy(path, u'/') self.assertEqual(copy2['name'], name) self.assertEqual(copy2['path'], name) def test_trust_notebook(self): cm = self.contents_manager nb, name, path = self.new_notebook() untrusted = cm.get(path)['content'] assert not cm.notary.check_cells(untrusted) # print(untrusted) cm.trust_notebook(path) trusted = cm.get(path)['content'] # print(trusted) assert cm.notary.check_cells(trusted) def test_mark_trusted_cells(self): cm = self.contents_manager nb, name, path = self.new_notebook() cm.mark_trusted_cells(nb, path) for cell in nb.cells: if cell.cell_type == 'code': assert not cell.metadata.trusted cm.trust_notebook(path) nb = cm.get(path)['content'] for cell in nb.cells: if cell.cell_type == 'code': assert cell.metadata.trusted def test_check_and_sign(self): cm = self.contents_manager nb, name, path = self.new_notebook() cm.mark_trusted_cells(nb, path) cm.check_and_sign(nb, path) assert not cm.notary.check_signature(nb) cm.trust_notebook(path) nb = cm.get(path)['content'] cm.mark_trusted_cells(nb, path) cm.check_and_sign(nb, path) assert cm.notary.check_signature(nb)