class PickleShareDBTestCase(TestCase):

    def setUp(self):
        self.tempdir = TemporaryDirectory()

    def tearDown(self):
        self.tempdir.cleanup()

    def test_picklesharedb(self):
        db = PickleShareDB(self.tempdir.name)
        db.clear()
        print("Should be empty:", db.items())
        db['hello'] = 15
        db['aku ankka'] = [1, 2, 313]
        db['paths/nest/ok/keyname'] = [1, (5, 46)]
        db.hset('hash', 'aku', 12)
        db.hset('hash', 'ankka', 313)
        self.assertEqual(db.hget('hash', 'aku'), 12)
        self.assertEqual(db.hget('hash', 'ankka'), 313)
        print("all hashed", db.hdict('hash'))
        print(db.keys())
        print(db.keys('paths/nest/ok/k*'))
        print(dict(db))  # snapsot of whole db
        db.uncache()  # frees memory, causes re-reads later

        # shorthand for accessing deeply nested files
        lnk = db.getlink('myobjects/test')
        lnk.foo = 2
        lnk.bar = lnk.foo + 5
        self.assertEqual(lnk.bar, 7)

    @skip("Too slow for regular running.")
    def test_stress(self):
        db = PickleShareDB('~/fsdbtest')
        import time
        import sys
        for i in range(1000):
            for j in range(1000):
                if i % 15 == 0 and i < 200:
                    if str(j) in db:
                        del db[str(j)]
                    continue

                if j % 33 == 0:
                    time.sleep(0.02)

                db[str(j)] = db.get(str(j), []) + \
                    [(i, j, "proc %d" % os.getpid())]
                db.hset('hash', j, db.hget('hash', j, 15) + 1)

            print(i, end=' ')
            sys.stdout.flush()
            if i % 10 == 0:
                db.uncache()
class PickleShareDBTestCase(TestCase):
    def setUp(self):
        self.tempdir = TemporaryDirectory()

    def tearDown(self):
        self.tempdir.cleanup()

    def test_picklesharedb(self):
        db = PickleShareDB(self.tempdir.name)
        db.clear()
        print("Should be empty:", db.items())
        db['hello'] = 15
        db['aku ankka'] = [1, 2, 313]
        db['paths/nest/ok/keyname'] = [1, (5, 46)]
        db.hset('hash', 'aku', 12)
        db.hset('hash', 'ankka', 313)
        self.assertEqual(db.hget('hash', 'aku'), 12)
        self.assertEqual(db.hget('hash', 'ankka'), 313)
        print("all hashed", db.hdict('hash'))
        print(db.keys())
        print(db.keys('paths/nest/ok/k*'))
        print(dict(db))  # snapsot of whole db
        db.uncache()  # frees memory, causes re-reads later

        # shorthand for accessing deeply nested files
        lnk = db.getlink('myobjects/test')
        lnk.foo = 2
        lnk.bar = lnk.foo + 5
        self.assertEqual(lnk.bar, 7)

    @skip("Too slow for regular running.")
    def test_stress(self):
        db = PickleShareDB('~/fsdbtest')
        import time, sys
        for i in range(1000):
            for j in range(1000):
                if i % 15 == 0 and i < 200:
                    if str(j) in db:
                        del db[str(j)]
                    continue

                if j % 33 == 0:
                    time.sleep(0.02)

                db[str(j)] = db.get(str(j),
                                    []) + [(i, j, "proc %d" % os.getpid())]
                db.hset('hash', j, db.hget('hash', j, 15) + 1)

            print(i, end=' ')
            sys.stdout.flush()
            if i % 10 == 0:
                db.uncache()
示例#3
0
class FileTestCase(TestContentsManager):
    def setUp(self):
        self._temp_dir = TemporaryDirectory()
        self.td = self._temp_dir.name
        self._file_manager = FileContentsManager(root_dir=self.td)
        self.contents_manager = HybridContentsManager(
            managers={'': self._file_manager})

    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._file_manager, api_path)
示例#4
0
def test_get_ipython_dir_3():
    """test_get_ipython_dir_3, use XDG if defined and exists, and .ipython doesn't exist."""
    tmphome = TemporaryDirectory()
    try:
        with patch_get_home_dir(tmphome.name), \
                patch('os.name', 'posix'), \
                modified_env({
                    'IPYTHON_DIR': None,
                    'IPYTHONDIR': None,
                    'XDG_CONFIG_HOME': XDG_TEST_DIR,
                }), warnings.catch_warnings(record=True) as w:
            ipdir = paths.get_ipython_dir()

        assert ipdir == os.path.join(tmphome.name, XDG_TEST_DIR, "ipython")
        assert len(w) == 0
    finally:
        tmphome.cleanup()
示例#5
0
def test_extension():
    tmpdir = TemporaryDirectory()
    orig_ipython_dir = _ip.ipython_dir
    try:
        _ip.ipython_dir = tmpdir.name
        nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
        url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
        _ip.magic("install_ext %s" % url)
        _ip.user_ns.pop('arq', None)
        invalidate_caches()   # Clear import caches
        _ip.magic("load_ext daft_extension")
        nt.assert_equal(_ip.user_ns['arq'], 185)
        _ip.magic("unload_ext daft_extension")
        assert 'arq' not in _ip.user_ns
    finally:
        _ip.ipython_dir = orig_ipython_dir
        tmpdir.cleanup()
示例#6
0
class FileTestCase(TestContentsManager):

    def setUp(self):
        self._temp_dir = TemporaryDirectory()
        self.td = self._temp_dir.name
        self._file_manager = FileContentsManager(root_dir=self.td)
        self.contents_manager = HybridContentsManager(
            managers={'': self._file_manager}
        )

    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._file_manager, api_path)
示例#7
0
def test_get_ipython_dir_3():
    """test_get_ipython_dir_3, move XDG if defined, and .ipython doesn't exist."""
    tmphome = TemporaryDirectory()
    try:
        with patch_get_home_dir(tmphome.name):
            os.name = "posix"
            env.pop('IPYTHON_DIR', None)
            env.pop('IPYTHONDIR', None)
            env['XDG_CONFIG_HOME'] = XDG_TEST_DIR

            with warnings.catch_warnings(record=True) as w:
                ipdir = path.get_ipython_dir()

            nt.assert_equal(ipdir, os.path.join(tmphome.name, ".ipython"))
            if sys.platform != 'darwin':
                nt.assert_equal(len(w), 1)
                nt.assert_in('Moving', str(w[0]))
    finally:
        tmphome.cleanup()
示例#8
0
def test_get_ipython_dir_3():
    """test_get_ipython_dir_3, move XDG if defined, and .ipython doesn't exist."""
    tmphome = TemporaryDirectory()
    try:
        with patch_get_home_dir(tmphome.name):
            os.name = "posix"
            env.pop('IPYTHON_DIR', None)
            env.pop('IPYTHONDIR', None)
            env['XDG_CONFIG_HOME'] = XDG_TEST_DIR

            with warnings.catch_warnings(record=True) as w:
                ipdir = path.get_ipython_dir()

            nt.assert_equal(ipdir, os.path.join(tmphome.name, ".ipython"))
            if sys.platform != 'darwin':
                nt.assert_equal(len(w), 1)
                nt.assert_in('Moving', str(w[0]))
    finally:
        tmphome.cleanup()
示例#9
0
def test_get_ipython_dir_3():
    """test_get_ipython_dir_3, move XDG if defined, and .ipython doesn't exist."""
    tmphome = TemporaryDirectory()
    try:
        with patch_get_home_dir(tmphome.name), \
                patch('os.name', 'posix'), \
                modified_env({
                    'IPYTHON_DIR': None,
                    'IPYTHONDIR': None,
                    'XDG_CONFIG_HOME': XDG_TEST_DIR,
                }), warnings.catch_warnings(record=True) as w:
            ipdir = paths.get_ipython_dir()

        nt.assert_equal(ipdir, os.path.join(tmphome.name, ".ipython"))
        if sys.platform != 'darwin':
            nt.assert_equal(len(w), 1)
            nt.assert_in('Moving', str(w[0]))
    finally:
        tmphome.cleanup()
示例#10
0
def test_get_ipython_dir_3():
    """test_get_ipython_dir_3, move XDG if defined, and .ipython doesn't exist."""
    tmphome = TemporaryDirectory()
    try:
        with patch_get_home_dir(tmphome.name), \
                patch('os.name', 'posix'), \
                modified_env({
                    'IPYTHON_DIR': None,
                    'IPYTHONDIR': None,
                    'XDG_CONFIG_HOME': XDG_TEST_DIR,
                }), warnings.catch_warnings(record=True) as w:
            ipdir = paths.get_ipython_dir()

        nt.assert_equal(ipdir, os.path.join(tmphome.name, ".ipython"))
        if sys.platform != 'darwin':
            nt.assert_equal(len(w), 1)
            nt.assert_in('Moving', str(w[0]))
    finally:
        tmphome.cleanup()
示例#11
0
def test_get_ipython_dir_3():
    """test_get_ipython_dir_3, move XDG if defined, and .ipython doesn't exist."""
    tmphome = TemporaryDirectory()
    try:
        with patch_get_home_dir(tmphome.name), patch(
                "os.name", "posix"), modified_env({
                    "IPYTHON_DIR":
                    None,
                    "IPYTHONDIR":
                    None,
                    "XDG_CONFIG_HOME":
                    XDG_TEST_DIR
                }), warnings.catch_warnings(record=True) as w:
            ipdir = paths.get_ipython_dir()

        nt.assert_equal(ipdir, os.path.join(tmphome.name, ".ipython"))
        if sys.platform != "darwin":
            nt.assert_equal(len(w), 1)
            nt.assert_in("Moving", str(w[0]))
    finally:
        tmphome.cleanup()
示例#12
0
class GLFRepl:
    def __init__(self, GF_BIN):
        self.GF_BIN = GF_BIN

        GF_ARGS = [GF_BIN, '--run']

        self.td = TemporaryDirectory()
        self.to_clean_up = ['.dot', '.png', '.gfo']
        self.out_file_name = os.path.join(self.td.name, 'shell.out')
        self.out = open(self.out_file_name, 'w+')
        self.shell = Popen(GF_ARGS,
                           stdin=PIPE,
                           stdout=self.out,
                           stderr=self.out)
        self.pid = os.getpid()
        self.out_count = 0

        # initialize the MMT interface
        self.mmtInterface = MMTInterface()

        # register the signal handler for the notify process
        signal.signal(signal.SIGUSR1, self.signal_handler)

    def do_shutdown(self):
        "Terminates the GF shell and the MMT subprocess"
        # terminate gf shell
        self.td.cleanup()
        self.shell.communicate(b'q\n')[0]
        self.shell.stdin.close()
        self.shell.kill()

        # terminate mmt
        self.mmtInterface.do_shutdown()

    def clean_up(self):
        """Removes all files whose extensions are contained in `self.to_clean_up`"""
        removed = []
        files = os.listdir('.')
        for file in files:
            _, file_extension = os.path.splitext(file)
            if file_extension in self.to_clean_up:
                removed.append(file)
                os.remove(file)

        if removed:
            s = map(lambda x: 'Removed: %s' % (x), removed)
            return "\n".join(s)
        else:
            return "No files removed"

    def do_export(self, file_name):
        source_path = os.path.join(self.mmtInterface.content_path,
                                   self.mmtInterface.archive, 'source')
        files = os.listdir(source_path)
        file_reg = re.compile('^%s.gf$' % (file_name))
        for file in files:
            if file_reg.match(file):
                from shutil import copy2
                copy2(os.path.join(source_path, file), file)
                return 'Exported %s' % (file)
        return 'Could not find %s' % (file_name)

    def handle_input(self, code):
        """Handles all kinds of user inputs"""
        messages = []
        parse_dict = parse(code)
        if parse_dict['type']:
            if parse_dict['type'] == 'commands':
                for command in parse_dict['commands']:
                    name = command['name']
                    args = command['args']
                    if name == 'view':
                        messages.append(
                            self.handle_multiple_view(' '.join(args)))
                    elif name == 'clean':
                        messages.append(
                            to_message_format(message=self.clean_up()))
                    elif name == 'export':
                        if len(args) > 1:
                            messages.append(
                                to_message_format(
                                    message="export only takes one argument!"))
                        else:
                            messages.append(
                                to_message_format(
                                    message=self.do_export(args[0])))
                    elif name == 'archive':
                        if len(args) > 2:
                            messages.append(
                                to_message_format(
                                    message=
                                    "archive takes at maximum two arguments!"))
                        else:
                            messages.append(
                                to_message_format(message=self.mmtInterface.
                                                  handle_archive(args)))
                    elif name == 'request':
                        messages.append(
                            to_message_format(message=self.mmtInterface.
                                              handle_request(args)))
                    elif name == 'help':
                        # TODO move this to another external file (probably a json)
                        messages.append(
                            to_message_format("""Available kernel commands: 
view 'gf_command' : view the graph(s) generated by 'gf_command'
clean : remove all %s files from the current directory.
export 'name' : export the grammar with 'name' to your current directory
h : display more information on the GF shell commands
Otherwise you can use the kernel as an editor for your grammars.
Stated grammars are automatically imported upon definiton.""" %
                                              (", ".join(self.to_clean_up))))
                    else:
                        cmd = '%s %s' % (name, ' '.join(args))
                        msg = self.handle_shell_input(cmd)
                        if name == 'import' and not msg:
                            messages.append(
                                to_message_format(
                                    message='Import successful!'))
                        else:
                            messages.append(to_message_format(message=msg))
            elif parse_dict['type'] == 'GFContent':
                messages.append(
                    to_message_format(
                        message=self.handle_grammar(code, parse_dict['name'])))
            elif parse_dict['type'] == 'MMTContent':
                messages.append(
                    to_message_format(
                        message=self.mmtInterface.create_mmt_file(
                            code, parse_dict['name'], parse_dict['mmt_type'])))

        else:
            messages.append(
                to_message_format(
                    message=
                    "Input is neither valid GF or MMT content nor a valid shell command!"
                ))

        return messages

    def handle_grammar(self, content, name):
        """
            Handles a grammar input

            ``grammar``: str; the content of the grammar

            ``name``: str; the name of the grammar
        """

        file_path = "%s.gf" % (os.path.join(self.mmtInterface.content_path,
                                            self.mmtInterface.archive,
                                            'source', name))
        try:
            with open(file_path, 'w') as f:
                f.write(content)
                f.close()
        except OSError:
            return 'Failed to create grammar %s' % (name)
        out = self.handle_shell_input("import %s" % (file_path))
        if not out:
            self.mmtInterface.build_archive()
            out = "Defined %s" % (name)
        return out

    def handle_multiple_view(self, command):
        """Handles view commands with possibly multiple graph outputs"""
        cmd = parse_command(command)
        if cmd['tree_type']:
            raw_command = cmd['cmd']
            out = self.handle_shell_input(raw_command)
            lines = out.split('\n')
            trees = []
            for line in lines:
                if line != '' and line != ' ':
                    trees.append(line)
            if len(trees) > 1:
                return to_message_format(trees=trees,
                                         tree_type=cmd['tree_type'])

        return to_message_format(file=self.handle_single_view(command))

    def handle_single_view(self, command):
        """
            Handles a single view command

            Sends the `command` to the GF shell and converts the output to a .png file
            returns the name of the .png file
        """
        out = self.handle_shell_input(command)
        if not out:
            return "no file"

        out_dot = os.path.join(self.td.name, 'out%s.dot' % (self.out_count))
        out_png = os.path.join(self.td.name, 'out%s.png' % (self.out_count))

        with open(out_dot, 'w') as f:
            f.write(out)

        DOT_ARGS = ['dot', '-Tpng', out_dot, '-o', out_png]
        p = Popen(DOT_ARGS, shell=False)
        p.communicate()[0]
        p.kill()
        self.out_count += 1

        return out_png

    def handle_shell_input(self, code):
        """Sends the `code` to the GF shell"""

        if self.out.closed:
            self.out = open(self.out_file_name, 'w')

        cp_s = self.out.tell()

        # send the command
        code = code + '\n'
        self.shell.stdin.write(code.encode())
        self.shell.stdin.flush()

        # start the notify process
        cmd = 'sp -command=\"python %s/notify.py %s\"\n' % (os.path.dirname(
            os.path.abspath(__file__)), self.pid)
        self.shell.stdin.write(cmd.encode())
        self.shell.stdin.flush()

        # wait for the notify process
        signal.pause()

        # some shell commands (mostly the ones that are dealing with files) are asynchronous from the shells execution,
        # like e.g. searching a file to include. This means the notify process can report back even though the shell
        # hasn't actually written its output to the output file yet. Hence we need to wait a little here to be sure the output is there.
        time.sleep(0.2)
        out = readFile(self.out_file_name, cp_s).replace('ExitFailure 1', '')

        return out

    def start(self):
        """Starts the REPL"""
        i = sys.stdin.readline()
        while i and i != 'quit\n' and i != 'q\n':
            # send input without the newline
            print(self.handle_shell_input(i[:-1]))
            i = sys.stdin.readline()

    def signal_handler(self, signum, frame):
        """Signal handler for the notify process"""
        pass
class TestMagicRunWithPackage(unittest.TestCase):

    def writefile(self, name, content):
        path = os.path.join(self.tempdir.name, name)
        d = os.path.dirname(path)
        if not os.path.isdir(d):
            os.makedirs(d)
        with open(path, 'w') as f:
            f.write(textwrap.dedent(content))

    def setUp(self):
        self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
        """Temporary  (probably) valid python package name."""

        self.value = int(random.random() * 10000)

        self.tempdir = TemporaryDirectory()
        self.__orig_cwd = os.getcwd()
        sys.path.insert(0, self.tempdir.name)

        self.writefile(os.path.join(package, '__init__.py'), '')
        self.writefile(os.path.join(package, 'sub.py'), """
        x = {0!r}
        """.format(self.value))
        self.writefile(os.path.join(package, 'relative.py'), """
        from .sub import x
        """)
        self.writefile(os.path.join(package, 'absolute.py'), """
        from {0}.sub import x
        """.format(package))
        self.writefile(os.path.join(package, 'args.py'), """
        import sys
        a = " ".join(sys.argv[1:])
        """.format(package))

    def tearDown(self):
        os.chdir(self.__orig_cwd)
        sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
        self.tempdir.cleanup()

    def check_run_submodule(self, submodule, opts=''):
        _ip.user_ns.pop('x', None)
        _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
        self.assertEqual(_ip.user_ns['x'], self.value,
                         'Variable `x` is not loaded from module `{0}`.'
                         .format(submodule))

    def test_run_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute')

    def test_run_submodule_with_relative_import(self):
        """Run submodule that has a relative import statement (#2727)."""
        self.check_run_submodule('relative')

    def test_prun_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute', '-p')

    def test_prun_submodule_with_relative_import(self):
        self.check_run_submodule('relative', '-p')

    def with_fake_debugger(func):
        @functools.wraps(func)
        def wrapper(*args, **kwds):
            with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
                return func(*args, **kwds)
        return wrapper

    @with_fake_debugger
    def test_debug_run_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute', '-d')

    @with_fake_debugger
    def test_debug_run_submodule_with_relative_import(self):
        self.check_run_submodule('relative', '-d')

    def test_module_options(self):
        _ip.user_ns.pop('a', None)
        test_opts = '-x abc -m test'
        _ip.run_line_magic('run', '-m {0}.args {1}'.format(self.package, test_opts))
        nt.assert_equal(_ip.user_ns['a'], test_opts)

    def test_module_options_with_separator(self):
        _ip.user_ns.pop('a', None)
        test_opts = '-x abc -m test'
        _ip.run_line_magic('run', '-m {0}.args -- {1}'.format(self.package, test_opts))
        nt.assert_equal(_ip.user_ns['a'], test_opts)
示例#14
0
class TestContentsManager(TestCase):
    def setUp(self):
        self._temp_dir = TemporaryDirectory()
        self.td = self._temp_dir.name
        self.contents_manager = FileContentsManager(root_dir=self.td,
                                                    log=logging.getLogger())

    def tearDown(self):
        self._temp_dir.cleanup()

    def make_dir(self, abs_path, rel_path):
        """make subdirectory, rel_path is the relative path
        to that directory from the location where the server started"""
        os_path = os.path.join(abs_path, rel_path)
        try:
            os.makedirs(os_path)
        except OSError:
            print("Directory already exists: %r" % os_path)
        return os_path

    def add_code_cell(self, nb):
        output = current.new_output("display_data",
                                    output_javascript="alert('hi');")
        cell = current.new_code_cell("print('hi')", outputs=[output])
        if not nb.worksheets:
            nb.worksheets.append(current.new_worksheet())
        nb.worksheets[0].cells.append(cell)

    def new_notebook(self):
        cm = self.contents_manager
        model = cm.create_file()
        name = model['name']
        path = model['path']

        full_model = cm.get_model(name, path)
        nb = full_model['content']
        self.add_code_cell(nb)

        cm.save(full_model, name, path)
        return nb, name, path

    def test_create_file(self):
        cm = self.contents_manager
        # Test in root directory
        model = cm.create_file()
        assert isinstance(model, dict)
        self.assertIn('name', model)
        self.assertIn('path', model)
        self.assertEqual(model['name'], 'Untitled0.ipynb')
        self.assertEqual(model['path'], '')

        # Test in sub-directory
        sub_dir = '/foo/'
        self.make_dir(cm.root_dir, 'foo')
        model = cm.create_file(None, sub_dir)
        assert isinstance(model, dict)
        self.assertIn('name', model)
        self.assertIn('path', model)
        self.assertEqual(model['name'], 'Untitled0.ipynb')
        self.assertEqual(model['path'], sub_dir.strip('/'))

    def test_get(self):
        cm = self.contents_manager
        # Create a notebook
        model = cm.create_file()
        name = model['name']
        path = model['path']

        # Check that we 'get' on the notebook we just created
        model2 = cm.get_model(name, path)
        assert isinstance(model2, dict)
        self.assertIn('name', model2)
        self.assertIn('path', model2)
        self.assertEqual(model['name'], name)
        self.assertEqual(model['path'], path)

        # Test in sub-directory
        sub_dir = '/foo/'
        self.make_dir(cm.root_dir, 'foo')
        model = cm.create_file(None, sub_dir)
        model2 = cm.get_model(name, sub_dir)
        assert isinstance(model2, dict)
        self.assertIn('name', model2)
        self.assertIn('path', model2)
        self.assertIn('content', model2)
        self.assertEqual(model2['name'], 'Untitled0.ipynb')
        self.assertEqual(model2['path'], sub_dir.strip('/'))

    @dec.skip_win32
    def test_bad_symlink(self):
        cm = self.contents_manager
        path = 'test bad symlink'
        os_path = self.make_dir(cm.root_dir, path)

        file_model = cm.create_file(path=path, ext='.txt')

        # create a broken symlink
        os.symlink("target", os.path.join(os_path, "bad symlink"))
        model = cm.get_model(path)
        self.assertEqual(model['content'], [file_model])

    @dec.skip_win32
    def test_good_symlink(self):
        cm = self.contents_manager
        path = 'test good symlink'
        os_path = self.make_dir(cm.root_dir, path)

        file_model = cm.create_file(path=path, ext='.txt')

        # create a good symlink
        os.symlink(file_model['name'], os.path.join(os_path, "good symlink"))
        symlink_model = cm.get_model(name="good symlink",
                                     path=path,
                                     content=False)

        dir_model = cm.get_model(path)
        self.assertEqual(
            sorted(dir_model['content'], key=lambda x: x['name']),
            [symlink_model, file_model],
        )

    def test_update(self):
        cm = self.contents_manager
        # Create a notebook
        model = cm.create_file()
        name = model['name']
        path = model['path']

        # Change the name in the model for rename
        model['name'] = 'test.ipynb'
        model = cm.update(model, name, 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_model, name, path)

        # Test in sub-directory
        # Create a directory and notebook in that directory
        sub_dir = '/foo/'
        self.make_dir(cm.root_dir, 'foo')
        model = cm.create_file(None, sub_dir)
        name = model['name']
        path = model['path']

        # Change the name in the model for rename
        model['name'] = 'test_in_sub.ipynb'
        model = cm.update(model, name, 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'], sub_dir.strip('/'))

        # Make sure the old name is gone
        self.assertRaises(HTTPError, cm.get_model, name, path)

    def test_save(self):
        cm = self.contents_manager
        # Create a notebook
        model = cm.create_file()
        name = model['name']
        path = model['path']

        # Get the model with 'content'
        full_model = cm.get_model(name, path)

        # Save the notebook
        model = cm.save(full_model, name, 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(cm.root_dir, 'foo')
        model = cm.create_file(None, sub_dir)
        name = model['name']
        path = model['path']
        model = cm.get_model(name, path)

        # Change the name in the model for rename
        model = cm.save(model, name, path)
        assert isinstance(model, dict)
        self.assertIn('name', model)
        self.assertIn('path', model)
        self.assertEqual(model['name'], 'Untitled0.ipynb')
        self.assertEqual(model['path'], sub_dir.strip('/'))

    def test_delete(self):
        cm = self.contents_manager
        # Create a notebook
        nb, name, path = self.new_notebook()

        # Delete the notebook
        cm.delete(name, path)

        # Check that a 'get' on the deleted notebook raises and error
        self.assertRaises(HTTPError, cm.get_model, name, path)

    def test_copy(self):
        cm = self.contents_manager
        path = u'å b'
        name = u'nb √.ipynb'
        os.mkdir(os.path.join(cm.root_dir, path))
        orig = cm.create_file({'name': name}, path=path)

        # copy with unspecified name
        copy = cm.copy(name, path=path)
        self.assertEqual(copy['name'],
                         orig['name'].replace('.ipynb', '-Copy0.ipynb'))

        # copy with specified name
        copy2 = cm.copy(name, u'copy 2.ipynb', path=path)
        self.assertEqual(copy2['name'], u'copy 2.ipynb')

    def test_trust_notebook(self):
        cm = self.contents_manager
        nb, name, path = self.new_notebook()

        untrusted = cm.get_model(name, path)['content']
        assert not cm.notary.check_cells(untrusted)

        # print(untrusted)
        cm.trust_notebook(name, path)
        trusted = cm.get_model(name, 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, name, path)
        for cell in nb.worksheets[0].cells:
            if cell.cell_type == 'code':
                assert not cell.trusted

        cm.trust_notebook(name, path)
        nb = cm.get_model(name, path)['content']
        for cell in nb.worksheets[0].cells:
            if cell.cell_type == 'code':
                assert cell.trusted

    def test_check_and_sign(self):
        cm = self.contents_manager
        nb, name, path = self.new_notebook()

        cm.mark_trusted_cells(nb, name, path)
        cm.check_and_sign(nb, name, path)
        assert not cm.notary.check_signature(nb)

        cm.trust_notebook(name, path)
        nb = cm.get_model(name, path)['content']
        cm.mark_trusted_cells(nb, name, path)
        cm.check_and_sign(nb, name, path)
        assert cm.notary.check_signature(nb)
示例#15
0
class TestNotebookManager(TestCase):
    
    def setUp(self):
        self._temp_dir = TemporaryDirectory()
        self.td = self._temp_dir.name
        self.notebook_manager = FileNotebookManager(
            notebook_dir=self.td,
            log=logging.getLogger()
        )
    
    def tearDown(self):
        self._temp_dir.cleanup()
    
    def make_dir(self, abs_path, rel_path):
        """make subdirectory, rel_path is the relative path
        to that directory from the location where the server started"""
        os_path = os.path.join(abs_path, rel_path)
        try:
            os.makedirs(os_path)
        except OSError:
            print("Directory already exists: %r" % os_path)
    
    def add_code_cell(self, nb):
        output = current.new_output("display_data", output_javascript="alert('hi');")
        cell = current.new_code_cell("print('hi')", outputs=[output])
        if not nb.worksheets:
            nb.worksheets.append(current.new_worksheet())
        nb.worksheets[0].cells.append(cell)
    
    def new_notebook(self):
        nbm = self.notebook_manager
        model = nbm.create_notebook()
        name = model['name']
        path = model['path']
        
        full_model = nbm.get_notebook(name, path)
        nb = full_model['content']
        self.add_code_cell(nb)
        
        nbm.save_notebook(full_model, name, path)
        return nb, name, path
    
    def test_create_notebook(self):
        nm = self.notebook_manager
        # Test in root directory
        model = nm.create_notebook()
        assert isinstance(model, dict)
        self.assertIn('name', model)
        self.assertIn('path', model)
        self.assertEqual(model['name'], 'Untitled0.ipynb')
        self.assertEqual(model['path'], '')

        # Test in sub-directory
        sub_dir = '/foo/'
        self.make_dir(nm.notebook_dir, 'foo')
        model = nm.create_notebook(None, sub_dir)
        assert isinstance(model, dict)
        self.assertIn('name', model)
        self.assertIn('path', model)
        self.assertEqual(model['name'], 'Untitled0.ipynb')
        self.assertEqual(model['path'], sub_dir.strip('/'))

    def test_get_notebook(self):
        nm = self.notebook_manager
        # Create a notebook
        model = nm.create_notebook()
        name = model['name']
        path = model['path']

        # Check that we 'get' on the notebook we just created
        model2 = nm.get_notebook(name, path)
        assert isinstance(model2, dict)
        self.assertIn('name', model2)
        self.assertIn('path', model2)
        self.assertEqual(model['name'], name)
        self.assertEqual(model['path'], path)

        # Test in sub-directory
        sub_dir = '/foo/'
        self.make_dir(nm.notebook_dir, 'foo')
        model = nm.create_notebook(None, sub_dir)
        model2 = nm.get_notebook(name, sub_dir)
        assert isinstance(model2, dict)
        self.assertIn('name', model2)
        self.assertIn('path', model2)
        self.assertIn('content', model2)
        self.assertEqual(model2['name'], 'Untitled0.ipynb')
        self.assertEqual(model2['path'], sub_dir.strip('/'))
            
    def test_update_notebook(self):
        nm = self.notebook_manager
        # Create a notebook
        model = nm.create_notebook()
        name = model['name']
        path = model['path']

        # Change the name in the model for rename
        model['name'] = 'test.ipynb'
        model = nm.update_notebook(model, name, 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, nm.get_notebook, name, path)

        # Test in sub-directory
        # Create a directory and notebook in that directory
        sub_dir = '/foo/'
        self.make_dir(nm.notebook_dir, 'foo')
        model = nm.create_notebook(None, sub_dir)
        name = model['name']
        path = model['path']
        
        # Change the name in the model for rename
        model['name'] = 'test_in_sub.ipynb'
        model = nm.update_notebook(model, name, 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'], sub_dir.strip('/'))
        
        # Make sure the old name is gone
        self.assertRaises(HTTPError, nm.get_notebook, name, path)

    def test_save_notebook(self):
        nm = self.notebook_manager
        # Create a notebook
        model = nm.create_notebook()
        name = model['name']
        path = model['path']

        # Get the model with 'content'
        full_model = nm.get_notebook(name, path)

        # Save the notebook
        model = nm.save_notebook(full_model, name, 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(nm.notebook_dir, 'foo')
        model = nm.create_notebook(None, sub_dir)
        name = model['name']
        path = model['path']
        model = nm.get_notebook(name, path)

        # Change the name in the model for rename
        model = nm.save_notebook(model, name, path)
        assert isinstance(model, dict)
        self.assertIn('name', model)
        self.assertIn('path', model)
        self.assertEqual(model['name'], 'Untitled0.ipynb')
        self.assertEqual(model['path'], sub_dir.strip('/'))

    def test_save_notebook_with_script(self):
        nm = self.notebook_manager
        # Create a notebook
        model = nm.create_notebook()
        nm.save_script = True
        model = nm.create_notebook()
        name = model['name']
        path = model['path']

        # Get the model with 'content'
        full_model = nm.get_notebook(name, path)

        # Save the notebook
        model = nm.save_notebook(full_model, name, path)

        # Check that the script was created
        py_path = os.path.join(nm.notebook_dir, os.path.splitext(name)[0]+'.py')
        assert os.path.exists(py_path), py_path

    def test_delete_notebook(self):
        nm = self.notebook_manager
        # Create a notebook
        nb, name, path = self.new_notebook()
        
        # Delete the notebook
        nm.delete_notebook(name, path)
        
        # Check that a 'get' on the deleted notebook raises and error
        self.assertRaises(HTTPError, nm.get_notebook, name, path)
    
    def test_copy_notebook(self):
        nm = self.notebook_manager
        path = u'å b'
        name = u'nb √.ipynb'
        os.mkdir(os.path.join(nm.notebook_dir, path))
        orig = nm.create_notebook({'name' : name}, path=path)
        
        # copy with unspecified name
        copy = nm.copy_notebook(name, path=path)
        self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy0.ipynb'))
        
        # copy with specified name
        copy2 = nm.copy_notebook(name, u'copy 2.ipynb', path=path)
        self.assertEqual(copy2['name'], u'copy 2.ipynb')
    
    def test_trust_notebook(self):
        nbm = self.notebook_manager
        nb, name, path = self.new_notebook()
        
        untrusted = nbm.get_notebook(name, path)['content']
        assert not nbm.notary.check_cells(untrusted)
        
        # print(untrusted)
        nbm.trust_notebook(name, path)
        trusted = nbm.get_notebook(name, path)['content']
        # print(trusted)
        assert nbm.notary.check_cells(trusted)
    
    def test_mark_trusted_cells(self):
        nbm = self.notebook_manager
        nb, name, path = self.new_notebook()
        
        nbm.mark_trusted_cells(nb, name, path)
        for cell in nb.worksheets[0].cells:
            if cell.cell_type == 'code':
                assert not cell.trusted
        
        nbm.trust_notebook(name, path)
        nb = nbm.get_notebook(name, path)['content']
        for cell in nb.worksheets[0].cells:
            if cell.cell_type == 'code':
                assert cell.trusted

    def test_check_and_sign(self):
        nbm = self.notebook_manager
        nb, name, path = self.new_notebook()
        
        nbm.mark_trusted_cells(nb, name, path)
        nbm.check_and_sign(nb, name, path)
        assert not nbm.notary.check_signature(nb)
        
        nbm.trust_notebook(name, path)
        nb = nbm.get_notebook(name, path)['content']
        nbm.mark_trusted_cells(nb, name, path)
        nbm.check_and_sign(nb, name, path)
        assert nbm.notary.check_signature(nb)
示例#16
0
文件: GLFRepl.py 项目: KWARC/GLIF
class GLFRepl:
    def __init__(self):
        self.td = TemporaryDirectory()
        self.to_clean_up = ['.dot', '.png', '.gfo']
        # by default save grammars into td
        self.grammar_path = self.td.name
        self.out_count = 0

        self.gfRepl = None
        self.mmtInterface = None

        if GF_PATH:
            # start the GF Repl
            self.gfRepl = GFRepl(GF_PATH)

        if os.path.isdir(MMT_PATH):
            # initialize the MMT interface
            self.mmtInterface = MMTInterface(MMT_PATH)
            # in case of MMT installation store grammars in MMT archive
            self.grammar_path = self.mmtInterface.get_cwd()

        self.MMT_blocked = False

        self.grammars = self.search_grammars()

        # content handlers
        self.handlers = {
            'MMT_command': self.handle_mmt_command,
            'ELPI_command': self.handle_elpi_command,
            'GF_command': self.handle_gf_command,
            'kernel_command': self.handle_kernel_command
        }

        # load help messages from messages.json file
        messages_path = os.path.dirname(os.path.realpath(__file__))
        try:
            with open(os.path.join(messages_path, 'messages.json')) as f:
                self.messages = load(f)
        except:
            self.messages = None

    def do_shutdown(self):
        """Terminates the GF shell and the MMT subprocess"""
        self.td.cleanup()
        if self.gfRepl:
            self.gfRepl.do_shutdown()
        if self.mmtInterface:
            self.mmtInterface.do_shutdown()

    def reload_gfrepl(self):
        if GF_PATH:
            self.gfRepl = GFRepl(GF_PATH, self.grammar_path)
            return 'Successfully reloaded GF'
        else:
            return 'No gf executable was found'

    # ---------------------------------------------------------------------------- #
    #                           General Content Handling                           #
    # ---------------------------------------------------------------------------- #

    def handle_input(self, code):
        """
            Parses the `code` from the notebook and delegates 
            command handling to the respective handlers

            `code`: str; the user input from the notebook
        """
        messages = []
        parse_dict = parse(code)
        if parse_dict['type']:
            if parse_dict['type'] == 'commands':
                for command in parse_dict['commands']:
                    pipe_commands = command['pipe_commands']
                    pipe_res = []
                    for pipe_command in pipe_commands:
                        pipe_command_type = pipe_command['type']
                        pipe_command_str = pipe_command['command']
                        if pipe_commands.index(pipe_command) == 0:
                            res = self.handlers[pipe_command_type](
                                pipe_command_str)
                            name = get_name(pipe_command_str)
                            trees = []
                            try:  # TODO make this produce a meaningful error message
                                lines = res.split('\n')
                            except:
                                continue

                            for line in lines:
                                if line != '' and line != ' ' and line != '\n':
                                    if name == 'parse' or name == 'p':
                                        trees.append(line)
                                    pipe_res.append(line)
                        else:
                            # in case the output contains multiple lines
                            new_pipe_res = []
                            for res in pipe_res:
                                new_res = self.handlers[pipe_command_type](
                                    '%s %s' % (pipe_command_str, res))
                                new_pipe_res.append(new_res)
                            pipe_res = new_pipe_res

                    messages.append(to_message_format(trees=trees))

                    for res in pipe_res:
                        if type(res) is dict:
                            messages.append(res)
                        else:
                            messages.append(to_message_format(message=res))

            elif parse_dict['type'] == 'GFContent':
                messages.append(
                    to_message_format(
                        message=self.handle_grammar(code, parse_dict['name'])))
            elif parse_dict['type'] == 'MMTContent':
                if self.mmtInterface:
                    messages.append(
                        to_message_format(
                            message=self.mmtInterface.create_mmt_file(
                                code, parse_dict['name'],
                                parse_dict['mmt_type'])))
                else:
                    messages.append(
                        to_message_format(
                            message=
                            "No MMT installation found. MMT content not available."
                        ))
            elif parse_dict['type'] == 'ELPIContent':
                messages.append(
                    to_message_format(message=self.handle_elpi_rules(
                        code, parse_dict['name'])))
        else:
            messages.append(
                to_message_format(
                    message=
                    "Input is neither valid GF or MMT content nor a valid shell command!"
                ))

        return messages

    # ---------------------------------------------------------------------------- #
    #                                Kernel Commands                               #
    # ---------------------------------------------------------------------------- #

    def handle_kernel_command(self, command):
        """
            Handles the Kernel-Commands `show`, `clean, `export` and `help`

            'command': str; the command
        """
        name = get_name(command)
        args = get_args(command)

        if name == 'show':
            graph = ' '.join(args)
            return to_message_format(graph=graph)

        elif name == 'clean':
            return self.clean_up()

        elif name == 'export':
            return self.do_export(args[0])

        elif name == 'grammar-path':
            self.grammar_path = create_nested_dir(os.getcwd(), args[0])
            gf_msg = self.reload_gfrepl()
            if self.mmtInterface:
                self.MMT_blocked = True
                return "Set grammar-path to %s. MMT functionality is now disabled.\n%s" % (
                    self.grammar_path, gf_msg)

            return "Set grammar-path to %s.\n%s" % (self.grammar_path, gf_msg)

        elif name == 'help':
            if not self.messages:
                return "No help available"
            if args:
                name = args[0]
                if name in self.messages.keys():
                    return self.messages[name]
                else:
                    return "No help available on %s" % (name)
            else:
                return self.messages['help']

    def convert_to_png(self, graph):
        """
            Converts the given `graph` into a png
            Returns the file name of the picture

            `graph`: str
        """
        out_dot = os.path.join(self.td.name, 'out%s.dot' % (self.out_count))
        out_png = os.path.join(self.td.name, 'out%s.png' % (self.out_count))

        with open(out_dot, 'w') as f:
            f.write(graph)

        DOT_ARGS = ['dot', '-Tpng', out_dot, '-o', out_png]
        p = Popen(DOT_ARGS, shell=False)
        p.communicate()[0]
        p.kill()
        self.out_count += 1

        return out_png

    def clean_up(self):
        """Removes all files whose extensions are contained in `self.to_clean_up`"""
        removed = []
        files = os.listdir('.')
        for file in files:
            _, file_extension = os.path.splitext(file)
            if file_extension in self.to_clean_up:
                removed.append(file)
                os.remove(file)

        if removed:
            s = map(lambda x: 'Removed: %s' % (x), removed)
            return "\n".join(s)
        else:
            return "No files removed"

    def do_export(self, file_name):
        """
            Handles an export command
            Copies the specified Grammar to the current working directory

            `file_name`: str; the name of the file to export
        """
        args = get_args(file_name)
        if len(args) > 1:
            return "export only takes one argument!"
        source_path = os.path.join(self.mmtInterface.content_path,
                                   self.mmtInterface.archive, 'source')
        files = os.listdir(source_path)
        file_reg = re.compile('^%s.gf$' % (file_name))
        for file in files:
            if file_reg.match(file):
                from shutil import copy2
                copy2(os.path.join(source_path, file), file)
                return 'Exported %s' % (file)
        return 'Could not find %s' % (file_name)

    # ---------------------------------------------------------------------------- #
    #                                 ELPI Commands                                #
    # ---------------------------------------------------------------------------- #

    def handle_elpi_command(self, command):
        args = get_args(command)
        if len(args) < 3:
            return 'ERROR: "elpi" command requires at least 3 arguments (command, file and rule)'
        command = args[0]
        if command not in ['filter']:
            return 'Unknown command: ' + command
        filename = args[1]
        if not filename.endswith('.elpi'):
            filename += '.elpi'
        rule = args[2]
        argsmerged = ' '.join(args[3:])
        fullcommand = f'glif.{command} {rule} [{argsmerged}]'
        extraargs = ''
        elpi = subprocess.Popen((
            find_executable('elpi'),
            '-exec',
            fullcommand,
            os.path.join(self.mmtInterface.get_cwd(), filename),
            '--',
            extraargs,
        ),
                                stdin=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                text=True)
        out, err = elpi.communicate()
        if elpi.returncode not in [0, 1]:
            return 'ELPI ERROR: ' + str(
                elpi.returncode) + '\nOUTPUT:\n' + out + '\nERROR:\n' + err
        else:
            return out

    # ---------------------------------------------------------------------------- #
    #                                 MMT Commands                                 #
    # ---------------------------------------------------------------------------- #

    def handle_mmt_command(self, command):
        """
            Handles the MMT-Commands 'archive', 'construct' and 'subdir'

            'command': str; the command
        """
        if not self.mmtInterface:
            return "MMT functionality unavailable. No MMT installation detected."

        if self.MMT_blocked:
            return "MMT-functionality is blocked due to changes to the storing location for Grammars with 'grammar-location'."

        name = get_name(command)
        args = get_args(command)
        if name == 'archive':
            if not args:
                # TODO make this into a string so output order doesn't get screwed
                tree(dir=self.mmtInterface.get_archive_path(),
                     archive_name=self.mmtInterface.get_archive())
                return ''
            if len(args) > 1:
                return 'archive takes only one argument!'
            msg = self.mmtInterface.handle_archive(args[0])
            self.grammar_path = self.mmtInterface.get_cwd()
            gf_msg = self.reload_gfrepl()
            return msg + '\n' + gf_msg

        if name == 'archives':
            return ', '.join(self.mmtInterface.get_archives())

        elif name == 'construct':
            view = None
            i = 0
            toElpi = False
            while True:
                if args[i] == '-v' or args[i] == '-view':
                    if len(args) <= i:
                        return f'{args[i]} option requires argument'
                    view = args[i + 1]
                    i += 2
                elif args[i] == '-e' or args[i] == '-elpi':
                    toElpi = True
                    i += 1
                else:
                    break

            ASTsStr = ' '.join(args[i:])

            h = ASTsStr.split('|')
            ASTs = list(map(str.strip, h))
            return self.mmtInterface.construct(ASTs, view, toElpi)

        elif name == 'elpigen':
            theory = None
            mode = None
            targetName = None
            meta = False
            includes = True
            i = 0
            while True:
                if not i < len(args):
                    break
                if args[i] == '-o' or args[i] == '-out':
                    if not i + 1 < len(args):
                        return f'Option {args[i]} requires argument'
                    targetName = args[i + 1]
                    i += 2
                    continue
                if args[i] == '-noincludes':
                    includes = False
                elif args[i] == '-withmeta':
                    meta = True
                elif not mode:
                    mode = args[i]
                elif not theory:
                    theory = args[i]
                else:
                    return 'Too many arguments'
                i += 1
            if not mode: return 'No mode specified'
            if not theory: return 'No theory specified'
            result = self.mmtInterface.elpigen(mode, theory, targetName, meta,
                                               includes)
            if not result[0]:
                return 'An error occured:\n' + result[1]
            elpicode = result[1]
            if not targetName:
                targetName = theory
            if not targetName.endswith('.elpi'):
                targetName += '.elpi'
            with open(os.path.join(self.mmtInterface.get_cwd(), targetName),
                      'w') as fp:
                fp.write(str(elpicode))
            return 'Success'

        elif name == 'subdir':
            if args and len(args) == 1:
                msg = self.mmtInterface.create_subdir(args[0])
                self.grammar_path = self.mmtInterface.get_cwd()
                gf_msg = self.reload_gfrepl()
                return msg + '\n' + gf_msg
            elif not args:
                return os.path.relpath(
                    self.mmtInterface.get_cwd(),
                    os.path.join(self.mmtInterface.get_archive_path(),
                                 'source'))

    # ---------------------------------------------------------------------------- #
    #                               GF Content                                     #
    # ---------------------------------------------------------------------------- #

    def handle_gf_command(self, command):
        if not self.gfRepl:
            return "GF functionality unavailable. No GF installation detected."
        return self.gfRepl.handle_gf_command(command)

    def handle_elpi_rules(self, content, name):
        if not name.endswith('.elpi'):
            name += '.elpi'
        file_path = os.path.join(self.grammar_path, name)
        try:
            shutil.copyfile(
                os.path.join(os.path.dirname(os.path.realpath(__file__)),
                             'glif.elpi'),
                os.path.join(self.mmtInterface.get_cwd(), 'glif.elpi'))
            with open(file_path, 'w') as f:
                f.write('accumulate glif.\n' +
                        '\n'.join(content.splitlines()[1:]))
                f.close()
        except OSError as ex:
            return 'Failed to create %s:\n%s' % (name, ex)
        return 'Created ' + name

    def handle_grammar(self, content, name):
        """
            Handles grammar input

            `content`: str; the content of the grammar
            `name`: str; the name of the grammar
        """

        file_name = "%s.gf" % (name)
        file_path = os.path.join(self.grammar_path, file_name)
        try:
            with open(file_path, 'w') as f:
                f.write(content)
                f.close()
        except OSError:
            return 'Failed to create grammar %s' % (name)
        out = self.handle_gf_command("import %s" % (file_path))
        if out == 'success' or out.startswith('Abstract changed'):
            if not self.mmtInterface:
                self.grammars[name] = file_path
                return "Defined %s" % (name)

            build_result = self.mmtInterface.build_file(
                file_name)  # build the Grammar with the GlfBuild extension
            if build_result['isSuccessful']:
                self.grammars[name] = file_path
                return "Defined %s" % (name)
            else:
                return '\n'.join(build_result['errors'])
        return out

    def search_grammars(self):
        grammars = {}
        cwd = self.grammar_path
        for file in os.listdir(cwd):
            if file.endswith(".gf"):
                path = os.path.join(cwd, file)
                name = os.path.splitext(file)
                grammars[name] = path
        return grammars

    def get_grammars(self):
        return self.grammars
示例#17
0
class TestContentsManager(TestCase):
    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()

    @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_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)

    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_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)

    def test_escape_root(self):
        cm = self.contents_manager
        # 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")
示例#18
0
class TestMagicRunWithPackage(unittest.TestCase):

    def writefile(self, name, content):
        path = os.path.join(self.tempdir.name, name)
        d = os.path.dirname(path)
        if not os.path.isdir(d):
            os.makedirs(d)
        with open(path, 'w') as f:
            f.write(textwrap.dedent(content))

    def setUp(self):
        self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
        """Temporary valid python package name."""

        self.value = int(random.random() * 10000)

        self.tempdir = TemporaryDirectory()
        self.__orig_cwd = py3compat.getcwd()
        sys.path.insert(0, self.tempdir.name)

        self.writefile(os.path.join(package, '__init__.py'), '')
        self.writefile(os.path.join(package, 'sub.py'), """
        x = {0!r}
        """.format(self.value))
        self.writefile(os.path.join(package, 'relative.py'), """
        from .sub import x
        """)
        self.writefile(os.path.join(package, 'absolute.py'), """
        from {0}.sub import x
        """.format(package))

    def tearDown(self):
        os.chdir(self.__orig_cwd)
        sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
        self.tempdir.cleanup()

    def check_run_submodule(self, submodule, opts=''):
        _ip.user_ns.pop('x', None)
        _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
        self.assertEqual(_ip.user_ns['x'], self.value,
                         'Variable `x` is not loaded from module `{0}`.'
                         .format(submodule))

    def test_run_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute')

    def test_run_submodule_with_relative_import(self):
        """Run submodule that has a relative import statement (#2727)."""
        self.check_run_submodule('relative')

    def test_prun_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute', '-p')

    def test_prun_submodule_with_relative_import(self):
        self.check_run_submodule('relative', '-p')

    def with_fake_debugger(func):
        @functools.wraps(func)
        def wrapper(*args, **kwds):
            with tt.monkeypatch(debugger.Pdb, 'run', staticmethod(eval)):
                return func(*args, **kwds)
        return wrapper

    @with_fake_debugger
    def test_debug_run_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute', '-d')

    @with_fake_debugger
    def test_debug_run_submodule_with_relative_import(self):
        self.check_run_submodule('relative', '-d')
示例#19
0
class TestContentsManager(TestCase):

    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, abs_path, rel_path):
        """make subdirectory, rel_path is the relative path
        to that directory from the location where the server started"""
        os_path = os.path.join(abs_path, rel_path)
        try:
            os.makedirs(os_path)
        except OSError:
            print("Directory already exists: %r" % os_path)
        return os_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']
        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)

    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(cm.root_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 getting directory model
        dirmodel = cm.get('foo')
        self.assertEqual(dirmodel['type'], 'directory')

        with self.assertRaises(HTTPError):
            cm.get('foo', type='file')

    
    @dec.skip_win32
    def test_bad_symlink(self):
        cm = self.contents_manager
        path = 'test bad symlink'
        os_path = self.make_dir(cm.root_dir, path)
        
        file_model = cm.new_untitled(path=path, ext='.txt')
        
        # create a broken symlink
        os.symlink("target", os.path.join(os_path, "bad symlink"))
        model = cm.get(path)
        self.assertEqual(model['content'], [file_model])
    
    @dec.skip_win32
    def test_good_symlink(self):
        cm = self.contents_manager
        parent = 'test good symlink'
        name = 'good symlink'
        path = '{0}/{1}'.format(parent, name)
        os_path = self.make_dir(cm.root_dir, parent)
        
        file_model = cm.new(path=parent + '/zfoo.txt')
        
        # create a good symlink
        os.symlink(file_model['name'], os.path.join(os_path, name))
        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_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(cm.root_dir, 'foo')
        model = cm.new_untitled(path=sub_dir, type='notebook')
        name = model['name']
        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(cm.root_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 a 'get' on the deleted notebook raises and error
        self.assertRaises(HTTPError, cm.get, path)

    def test_copy(self):
        cm = self.contents_manager
        parent = u'å b'
        name = u'nb √.ipynb'
        path = u'{0}/{1}'.format(parent, name)
        os.mkdir(os.path.join(cm.root_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)
class TestUploadDownload(TestCase):
    def setUp(self):

        self.td = TemporaryDirectory()
        self.checkpoints = PostgresCheckpoints(
            user_id='test',
            db_url=TEST_DB_URL,
        )
        self.contents = FileContentsManager(
            root_dir=self.td.name,
            checkpoints=self.checkpoints,
        )

        self.checkpoints.ensure_user()

    def tearDown(self):
        self.td.cleanup()
        clear_test_db()

    def add_markdown_cell(self, path):
        # Load and update
        model = self.contents.get(path=path)
        model['content'].cells.append(
            new_markdown_cell('Created by test: ' + path))

        # Save and checkpoint again.
        self.contents.save(model, path=path)
        return model

    def test_download_checkpoints(self):
        """
        Create two checkpoints for two notebooks, then call
        download_checkpoints.

        Assert that we get the correct version of both notebooks.
        """
        self.contents.new({'type': 'directory'}, 'subdir')
        paths = ('a.ipynb', 'subdir/a.ipynb')
        expected_content = {}
        for path in paths:
            # Create and checkpoint.
            self.contents.new(path=path)

            self.contents.create_checkpoint(path)

            model = self.add_markdown_cell(path)
            self.contents.create_checkpoint(path)

            # Assert greater because FileContentsManager creates a checkpoint
            # on creation, but this isn't part of the spec.
            self.assertGreater(len(self.contents.list_checkpoints(path)), 2)

            # Store the content to verify correctness after download.
            expected_content[path] = model['content']

        with TemporaryDirectory() as td:
            download_checkpoints(
                self.checkpoints.db_url,
                td,
                user='******',
            )

            fm = FileContentsManager(root_dir=td)
            root_entries = sorted(m['path'] for m in fm.get('')['content'])
            self.assertEqual(root_entries, ['a.ipynb', 'subdir'])
            subdir_entries = sorted(m['path']
                                    for m in fm.get('subdir')['content'])
            self.assertEqual(subdir_entries, ['subdir/a.ipynb'])
            for path in paths:
                content = fm.get(path)['content']
                self.assertEqual(expected_content[path], content)

    def test_checkpoint_all(self):
        """
        Test that checkpoint_all correctly makes a checkpoint for all files.
        """
        paths = populate(self.contents)
        original_content_minus_trust = {
            # Remove metadata that we expect to have dropped
            path: strip_transient(self.contents.get(path)['content'])
            for path in paths
        }

        original_cps = {}
        for path in paths:
            # Create a checkpoint, then update the file.
            original_cps[path] = self.contents.create_checkpoint(path)
            self.add_markdown_cell(path)

        # Verify that we still have the old version checkpointed.
        cp_content = {
            path: self.checkpoints.get_notebook_checkpoint(
                cp['id'],
                path,
            )['content']
            for path, cp in iteritems(original_cps)
        }
        self.assertEqual(original_content_minus_trust, cp_content)

        new_cps = checkpoint_all(
            self.checkpoints.db_url,
            self.td.name,
            self.checkpoints.user_id,
        )

        new_cp_content = {
            path: self.checkpoints.get_notebook_checkpoint(
                cp['id'],
                path,
            )['content']
            for path, cp in iteritems(new_cps)
        }
        for path, new_content in iteritems(new_cp_content):
            old_content = original_content_minus_trust[_norm_unicode(path)]
            self.assertEqual(
                new_content['cells'][:-1],
                old_content['cells'],
            )
            self.assertEqual(
                new_content['cells'][-1],
                new_markdown_cell('Created by test: ' + _norm_unicode(path)),
            )
示例#21
0
class TestLinkOrCopy(object):
    def setUp(self):
        self.tempdir = TemporaryDirectory()
        self.src = self.dst("src")
        with open(self.src, "w") as f:
            f.write("Hello, world!")

    def tearDown(self):
        self.tempdir.cleanup()

    def dst(self, *args):
        return os.path.join(self.tempdir.name, *args)

    def assert_inode_not_equal(self, a, b):
        nt.assert_not_equals(os.stat(a).st_ino, os.stat(b).st_ino,
                             "%r and %r do reference the same indoes" %(a, b))

    def assert_inode_equal(self, a, b):
        nt.assert_equals(os.stat(a).st_ino, os.stat(b).st_ino,
                         "%r and %r do not reference the same indoes" %(a, b))

    def assert_content_equal(self, a, b):
        with open(a) as a_f:
            with open(b) as b_f:
                nt.assert_equals(a_f.read(), b_f.read())

    @skip_win32
    def test_link_successful(self):
        dst = self.dst("target")
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)

    @skip_win32
    def test_link_into_dir(self):
        dst = self.dst("some_dir")
        os.mkdir(dst)
        path.link_or_copy(self.src, dst)
        expected_dst = self.dst("some_dir", os.path.basename(self.src))
        self.assert_inode_equal(self.src, expected_dst)

    @skip_win32
    def test_target_exists(self):
        dst = self.dst("target")
        open(dst, "w").close()
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)

    @skip_win32
    def test_no_link(self):
        real_link = os.link
        try:
            del os.link
            dst = self.dst("target")
            path.link_or_copy(self.src, dst)
            self.assert_content_equal(self.src, dst)
            self.assert_inode_not_equal(self.src, dst)
        finally:
            os.link = real_link

    @skip_if_not_win32
    def test_windows(self):
        dst = self.dst("target")
        path.link_or_copy(self.src, dst)
        self.assert_content_equal(self.src, dst)
示例#22
0
class TestContentsManager(TestCase):

    def setUp(self):
        self._temp_dir = TemporaryDirectory()
        self.td = self._temp_dir.name
        self.contents_manager = FileContentsManager(
            root_dir=self.td,
            log=logging.getLogger()
        )

    def tearDown(self):
        self._temp_dir.cleanup()

    def make_dir(self, abs_path, rel_path):
        """make subdirectory, rel_path is the relative path
        to that directory from the location where the server started"""
        os_path = os.path.join(abs_path, rel_path)
        try:
            os.makedirs(os_path)
        except OSError:
            print("Directory already exists: %r" % os_path)
        return os_path

    def add_code_cell(self, nb):
        output = current.new_output("display_data", output_javascript="alert('hi');")
        cell = current.new_code_cell("print('hi')", outputs=[output])
        if not nb.worksheets:
            nb.worksheets.append(current.new_worksheet())
        nb.worksheets[0].cells.append(cell)

    def new_notebook(self):
        cm = self.contents_manager
        model = cm.create_file()
        name = model['name']
        path = model['path']

        full_model = cm.get_model(name, path)
        nb = full_model['content']
        self.add_code_cell(nb)

        cm.save(full_model, name, path)
        return nb, name, path

    def test_create_file(self):
        cm = self.contents_manager
        # Test in root directory
        model = cm.create_file()
        assert isinstance(model, dict)
        self.assertIn('name', model)
        self.assertIn('path', model)
        self.assertEqual(model['name'], 'Untitled0.ipynb')
        self.assertEqual(model['path'], '')

        # Test in sub-directory
        sub_dir = '/foo/'
        self.make_dir(cm.root_dir, 'foo')
        model = cm.create_file(None, sub_dir)
        assert isinstance(model, dict)
        self.assertIn('name', model)
        self.assertIn('path', model)
        self.assertEqual(model['name'], 'Untitled0.ipynb')
        self.assertEqual(model['path'], sub_dir.strip('/'))

    def test_get(self):
        cm = self.contents_manager
        # Create a notebook
        model = cm.create_file()
        name = model['name']
        path = model['path']

        # Check that we 'get' on the notebook we just created
        model2 = cm.get_model(name, path)
        assert isinstance(model2, dict)
        self.assertIn('name', model2)
        self.assertIn('path', model2)
        self.assertEqual(model['name'], name)
        self.assertEqual(model['path'], path)

        # Test in sub-directory
        sub_dir = '/foo/'
        self.make_dir(cm.root_dir, 'foo')
        model = cm.create_file(None, sub_dir)
        model2 = cm.get_model(name, sub_dir)
        assert isinstance(model2, dict)
        self.assertIn('name', model2)
        self.assertIn('path', model2)
        self.assertIn('content', model2)
        self.assertEqual(model2['name'], 'Untitled0.ipynb')
        self.assertEqual(model2['path'], sub_dir.strip('/'))
    
    @dec.skip_win32
    def test_bad_symlink(self):
        cm = self.contents_manager
        path = 'test bad symlink'
        os_path = self.make_dir(cm.root_dir, path)
        
        file_model = cm.create_file(path=path, ext='.txt')
        
        # create a broken symlink
        os.symlink("target", os.path.join(os_path, "bad symlink"))
        model = cm.get_model(path)
        self.assertEqual(model['content'], [file_model])
    
    @dec.skip_win32
    def test_good_symlink(self):
        cm = self.contents_manager
        path = 'test good symlink'
        os_path = self.make_dir(cm.root_dir, path)
        
        file_model = cm.create_file(path=path, ext='.txt')
        
        # create a good symlink
        os.symlink(file_model['name'], os.path.join(os_path, "good symlink"))
        symlink_model = cm.get_model(name="good symlink", path=path, content=False)
        
        dir_model = cm.get_model(path)
        self.assertEqual(
            sorted(dir_model['content'], key=lambda x: x['name']),
            [symlink_model, file_model],
        )
    
    def test_update(self):
        cm = self.contents_manager
        # Create a notebook
        model = cm.create_file()
        name = model['name']
        path = model['path']

        # Change the name in the model for rename
        model['name'] = 'test.ipynb'
        model = cm.update(model, name, 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_model, name, path)

        # Test in sub-directory
        # Create a directory and notebook in that directory
        sub_dir = '/foo/'
        self.make_dir(cm.root_dir, 'foo')
        model = cm.create_file(None, sub_dir)
        name = model['name']
        path = model['path']

        # Change the name in the model for rename
        model['name'] = 'test_in_sub.ipynb'
        model = cm.update(model, name, 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'], sub_dir.strip('/'))

        # Make sure the old name is gone
        self.assertRaises(HTTPError, cm.get_model, name, path)

    def test_save(self):
        cm = self.contents_manager
        # Create a notebook
        model = cm.create_file()
        name = model['name']
        path = model['path']

        # Get the model with 'content'
        full_model = cm.get_model(name, path)

        # Save the notebook
        model = cm.save(full_model, name, 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(cm.root_dir, 'foo')
        model = cm.create_file(None, sub_dir)
        name = model['name']
        path = model['path']
        model = cm.get_model(name, path)

        # Change the name in the model for rename
        model = cm.save(model, name, path)
        assert isinstance(model, dict)
        self.assertIn('name', model)
        self.assertIn('path', model)
        self.assertEqual(model['name'], 'Untitled0.ipynb')
        self.assertEqual(model['path'], sub_dir.strip('/'))

    def test_delete(self):
        cm = self.contents_manager
        # Create a notebook
        nb, name, path = self.new_notebook()

        # Delete the notebook
        cm.delete(name, path)

        # Check that a 'get' on the deleted notebook raises and error
        self.assertRaises(HTTPError, cm.get_model, name, path)

    def test_copy(self):
        cm = self.contents_manager
        path = u'å b'
        name = u'nb √.ipynb'
        os.mkdir(os.path.join(cm.root_dir, path))
        orig = cm.create_file({'name' : name}, path=path)

        # copy with unspecified name
        copy = cm.copy(name, path=path)
        self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy0.ipynb'))

        # copy with specified name
        copy2 = cm.copy(name, u'copy 2.ipynb', path=path)
        self.assertEqual(copy2['name'], u'copy 2.ipynb')

    def test_trust_notebook(self):
        cm = self.contents_manager
        nb, name, path = self.new_notebook()

        untrusted = cm.get_model(name, path)['content']
        assert not cm.notary.check_cells(untrusted)

        # print(untrusted)
        cm.trust_notebook(name, path)
        trusted = cm.get_model(name, 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, name, path)
        for cell in nb.worksheets[0].cells:
            if cell.cell_type == 'code':
                assert not cell.trusted

        cm.trust_notebook(name, path)
        nb = cm.get_model(name, path)['content']
        for cell in nb.worksheets[0].cells:
            if cell.cell_type == 'code':
                assert cell.trusted

    def test_check_and_sign(self):
        cm = self.contents_manager
        nb, name, path = self.new_notebook()

        cm.mark_trusted_cells(nb, name, path)
        cm.check_and_sign(nb, name, path)
        assert not cm.notary.check_signature(nb)

        cm.trust_notebook(name, path)
        nb = cm.get_model(name, path)['content']
        cm.mark_trusted_cells(nb, name, path)
        cm.check_and_sign(nb, name, path)
        assert cm.notary.check_signature(nb)
示例#23
0
class TestMagicRunWithPackage(unittest.TestCase):

    def writefile(self, name, content):
        path = os.path.join(self.tempdir.name, name)
        d = os.path.dirname(path)
        if not os.path.isdir(d):
            os.makedirs(d)
        with open(path, 'w') as f:
            f.write(textwrap.dedent(content))

    def setUp(self):
        self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
        """Temporary  (probably) valid python package name."""

        self.value = int(random.random() * 10000)

        self.tempdir = TemporaryDirectory()
        self.__orig_cwd = os.getcwd()
        sys.path.insert(0, self.tempdir.name)

        self.writefile(os.path.join(package, '__init__.py'), '')
        self.writefile(os.path.join(package, 'sub.py'), """
        x = {0!r}
        """.format(self.value))
        self.writefile(os.path.join(package, 'relative.py'), """
        from .sub import x
        """)
        self.writefile(os.path.join(package, 'absolute.py'), """
        from {0}.sub import x
        """.format(package))
        self.writefile(os.path.join(package, 'args.py'), """
        import sys
        a = " ".join(sys.argv[1:])
        """.format(package))

    def tearDown(self):
        os.chdir(self.__orig_cwd)
        sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
        self.tempdir.cleanup()

    def check_run_submodule(self, submodule, opts=''):
        _ip.user_ns.pop('x', None)
        _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
        self.assertEqual(_ip.user_ns['x'], self.value,
                         'Variable `x` is not loaded from module `{0}`.'
                         .format(submodule))

    def test_run_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute')

    def test_run_submodule_with_relative_import(self):
        """Run submodule that has a relative import statement (#2727)."""
        self.check_run_submodule('relative')

    def test_prun_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute', '-p')

    def test_prun_submodule_with_relative_import(self):
        self.check_run_submodule('relative', '-p')

    def with_fake_debugger(func):
        @functools.wraps(func)
        def wrapper(*args, **kwds):
            with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
                return func(*args, **kwds)
        return wrapper

    @with_fake_debugger
    def test_debug_run_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute', '-d')

    @with_fake_debugger
    def test_debug_run_submodule_with_relative_import(self):
        self.check_run_submodule('relative', '-d')

    def test_module_options(self):
        _ip.user_ns.pop('a', None)
        test_opts = '-x abc -m test'
        _ip.run_line_magic('run', '-m {0}.args {1}'.format(self.package, test_opts))
        nt.assert_equal(_ip.user_ns['a'], test_opts)

    def test_module_options_with_separator(self):
        _ip.user_ns.pop('a', None)
        test_opts = '-x abc -m test'
        _ip.run_line_magic('run', '-m {0}.args -- {1}'.format(self.package, test_opts))
        nt.assert_equal(_ip.user_ns['a'], test_opts)
示例#24
0
class TestUploadDownload(TestCase):

    def setUp(self):

        drop_testing_db_tables()
        migrate_testing_db()

        self.td = TemporaryDirectory()
        self.checkpoints = PostgresCheckpoints(
            user_id='test',
            db_url=TEST_DB_URL,
        )
        self.contents = FileContentsManager(
            root_dir=self.td.name,
            checkpoints=self.checkpoints,
        )

        self.checkpoints.ensure_user()

    def tearDown(self):
        self.td.cleanup()

    def add_markdown_cell(self, path):
        # Load and update
        model = self.contents.get(path=path)
        model['content'].cells.append(
            new_markdown_cell('Created by test: ' + path)
        )

        # Save and checkpoint again.
        self.contents.save(model, path=path)
        return model

    def test_download_checkpoints(self):
        """
        Create two checkpoints for two notebooks, then call
        download_checkpoints.

        Assert that we get the correct version of both notebooks.
        """
        self.contents.new({'type': 'directory'}, 'subdir')
        paths = ('a.ipynb', 'subdir/a.ipynb')
        expected_content = {}
        for path in paths:
            # Create and checkpoint.
            self.contents.new(path=path)

            self.contents.create_checkpoint(path)

            model = self.add_markdown_cell(path)
            self.contents.create_checkpoint(path)

            # Assert greater because FileContentsManager creates a checkpoint
            # on creation, but this isn't part of the spec.
            self.assertGreater(len(self.contents.list_checkpoints(path)), 2)

            # Store the content to verify correctness after download.
            expected_content[path] = model['content']

        with TemporaryDirectory() as td:
            download_checkpoints(
                self.checkpoints.db_url,
                td,
                user='******',
            )

            fm = FileContentsManager(root_dir=td)
            root_entries = sorted(m['path'] for m in fm.get('')['content'])
            self.assertEqual(root_entries, ['a.ipynb', 'subdir'])
            subdir_entries = sorted(
                m['path'] for m in fm.get('subdir')['content']
            )
            self.assertEqual(subdir_entries, ['subdir/a.ipynb'])
            for path in paths:
                content = fm.get(path)['content']
                self.assertEqual(expected_content[path], content)

    def test_checkpoint_all(self):
        """
        Test that checkpoint_all correctly makes a checkpoint for all files.
        """
        paths = populate(self.contents)
        original_content_minus_trust = {
            # Remove metadata that we expect to have dropped
            path: strip_transient(self.contents.get(path)['content'])
            for path in paths
        }

        original_cps = {}
        for path in paths:
            # Create a checkpoint, then update the file.
            original_cps[path] = self.contents.create_checkpoint(path)
            self.add_markdown_cell(path)

        # Verify that we still have the old version checkpointed.
        cp_content = {
            path: self.checkpoints.get_notebook_checkpoint(
                cp['id'],
                path,
            )['content']
            for path, cp in iteritems(original_cps)
        }
        self.assertEqual(original_content_minus_trust, cp_content)

        new_cps = checkpoint_all(
            self.checkpoints.db_url,
            self.td.name,
            self.checkpoints.user_id,
        )

        new_cp_content = {
            path: self.checkpoints.get_notebook_checkpoint(
                cp['id'],
                path,
            )['content']
            for path, cp in iteritems(new_cps)
        }
        for path, new_content in iteritems(new_cp_content):
            old_content = original_content_minus_trust[_norm_unicode(path)]
            self.assertEqual(
                new_content['cells'][:-1],
                old_content['cells'],
            )
            self.assertEqual(
                new_content['cells'][-1],
                new_markdown_cell('Created by test: ' + _norm_unicode(path)),
            )
示例#25
0
class TestLinkOrCopy(object):
    def setUp(self):
        self.tempdir = TemporaryDirectory()
        self.src = self.dst("src")
        with open(self.src, "w") as f:
            f.write("Hello, world!")

    def tearDown(self):
        self.tempdir.cleanup()

    def dst(self, *args):
        return os.path.join(self.tempdir.name, *args)

    def assert_inode_not_equal(self, a, b):
        nt.assert_not_equal(os.stat(a).st_ino, os.stat(b).st_ino,
                            "%r and %r do reference the same indoes" %(a, b))

    def assert_inode_equal(self, a, b):
        nt.assert_equal(os.stat(a).st_ino, os.stat(b).st_ino,
                        "%r and %r do not reference the same indoes" %(a, b))

    def assert_content_equal(self, a, b):
        with open(a) as a_f:
            with open(b) as b_f:
                nt.assert_equal(a_f.read(), b_f.read())

    @skip_win32
    def test_link_successful(self):
        dst = self.dst("target")
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)

    @skip_win32
    def test_link_into_dir(self):
        dst = self.dst("some_dir")
        os.mkdir(dst)
        path.link_or_copy(self.src, dst)
        expected_dst = self.dst("some_dir", os.path.basename(self.src))
        self.assert_inode_equal(self.src, expected_dst)

    @skip_win32
    def test_target_exists(self):
        dst = self.dst("target")
        open(dst, "w").close()
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)

    @skip_win32
    def test_no_link(self):
        real_link = os.link
        try:
            del os.link
            dst = self.dst("target")
            path.link_or_copy(self.src, dst)
            self.assert_content_equal(self.src, dst)
            self.assert_inode_not_equal(self.src, dst)
        finally:
            os.link = real_link

    @skip_if_not_win32
    def test_windows(self):
        dst = self.dst("target")
        path.link_or_copy(self.src, dst)
        self.assert_content_equal(self.src, dst)

    def test_link_twice(self):
        # Linking the same file twice shouldn't leave duplicates around.
        # See https://github.com/ipython/ipython/issues/6450
        dst = self.dst('target')
        path.link_or_copy(self.src, dst)
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)
        nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target'])
示例#26
0
class GLFRepl:
    def __init__(self):
        # initialize the MMT interface
        self.mmtInterface = MMTInterface()

        self.td = TemporaryDirectory()
        self.to_clean_up = ['.dot', '.png', '.gfo']

        # start the GF Repl
        self.gfRepl = GFRepl()
        self.out_count = 0
        self.grammars = self.search_grammars()

        # content handlers
        self.handlers = {
            'MMT_command': self.handle_mmt_command,
            'GF_command': self.gfRepl.handle_gf_command,
            'kernel_command': self.handle_kernel_command
        }

        # load help messages from messages.json file
        messages_path = os.path.dirname(os.path.realpath(__file__))
        try:
            with open(os.path.join(messages_path, 'messages.json')) as f:
                self.messages = load(f)
        except:
            self.messages = None

    def do_shutdown(self):
        """Terminates the GF shell and the MMT subprocess"""
        self.td.cleanup()
        self.gfRepl.do_shutdown()
        self.mmtInterface.do_shutdown()

    # ---------------------------------------------------------------------------- #
    #                           General Content Handling                           #
    # ---------------------------------------------------------------------------- #

    def handle_input(self, code):
        """
            Parses the `code` from the notebook and delegates 
            command handling to the respective handlers

            `code`: str; the user input from the notebook
        """
        messages = []
        parse_dict = parse(code)
        if parse_dict['type']:
            if parse_dict['type'] == 'commands':
                for command in parse_dict['commands']:
                    pipe_commands = command['pipe_commands']
                    pipe_res = []
                    for pipe_command in pipe_commands:
                        pipe_command_type = pipe_command['type']
                        pipe_command_str = pipe_command['command']
                        if pipe_commands.index(pipe_command) == 0:
                            res = self.handlers[pipe_command_type](
                                pipe_command_str)
                            name = get_name(pipe_command_str)
                            trees = []
                            try:  # TODO make this produce a meaningful error message
                                lines = res.split('\n')
                            except:
                                continue

                            for line in lines:
                                if line != '' and line != ' ' and line != '\n':
                                    if name == 'parse' or name == 'p':
                                        trees.append(line)
                                    pipe_res.append(line)
                        else:
                            # in case the output contains multiple lines
                            new_pipe_res = []
                            for res in pipe_res:
                                new_res = self.handlers[pipe_command_type](
                                    '%s %s' % (pipe_command_str, res))
                                new_pipe_res.append(new_res)
                            pipe_res = new_pipe_res

                    messages.append(to_message_format(trees=trees))

                    for res in pipe_res:
                        if type(res) is dict:
                            messages.append(res)
                        else:
                            messages.append(to_message_format(message=res))

            elif parse_dict['type'] == 'GFContent':
                messages.append(
                    to_message_format(
                        message=self.handle_grammar(code, parse_dict['name'])))
            elif parse_dict['type'] == 'MMTContent':
                messages.append(
                    to_message_format(
                        message=self.mmtInterface.create_mmt_file(
                            code, parse_dict['name'], parse_dict['mmt_type'])))
        else:
            messages.append(
                to_message_format(
                    message=
                    "Input is neither valid GF or MMT content nor a valid shell command!"
                ))

        return messages

    # ---------------------------------------------------------------------------- #
    #                                Kernel Commands                               #
    # ---------------------------------------------------------------------------- #

    def handle_kernel_command(self, command):
        """
            Handles the Kernel-Commands `show`, `clean, `export` and `help`

            'command': str; the command
        """
        name = get_name(command)
        args = get_args(command)

        if name == 'show':
            graph = ' '.join(args)
            return to_message_format(graph=graph)

        elif name == 'clean':
            return self.clean_up()

        elif name == 'export':
            return self.do_export(args[0])

        elif name == 'help':
            if not self.messages:
                return "No help available"
            if args:
                name = args[0]
                if name in GF_commands:
                    return self.gfRepl.handle_gf_command('h %s' % (name))
                if name in self.messages.keys():
                    return self.messages[name]
                else:
                    return "No help available on %s" % (name)
            else:
                return self.messages['help']

    def convert_to_png(self, graph):
        """
            Converts the given `graph` into a png
            Returns the file name of the picture

            `graph`: str
        """
        out_dot = os.path.join(self.td.name, 'out%s.dot' % (self.out_count))
        out_png = os.path.join(self.td.name, 'out%s.png' % (self.out_count))

        with open(out_dot, 'w') as f:
            f.write(graph)

        DOT_ARGS = ['dot', '-Tpng', out_dot, '-o', out_png]
        p = Popen(DOT_ARGS, shell=False)
        p.communicate()[0]
        p.kill()
        self.out_count += 1

        return out_png

    def clean_up(self):
        """Removes all files whose extensions are contained in `self.to_clean_up`"""
        removed = []
        files = os.listdir('.')
        for file in files:
            _, file_extension = os.path.splitext(file)
            if file_extension in self.to_clean_up:
                removed.append(file)
                os.remove(file)

        if removed:
            s = map(lambda x: 'Removed: %s' % (x), removed)
            return "\n".join(s)
        else:
            return "No files removed"

    def do_export(self, file_name):
        """
            Handles an export command
            Copies the specified Grammar to the current working directory

            `file_name`: str; the name of the file to export
        """
        args = get_args(file_name)
        if len(args) > 1:
            return "export only takes one argument!"
        source_path = os.path.join(self.mmtInterface.content_path,
                                   self.mmtInterface.archive, 'source')
        files = os.listdir(source_path)
        file_reg = re.compile('^%s.gf$' % (file_name))
        for file in files:
            if file_reg.match(file):
                from shutil import copy2
                copy2(os.path.join(source_path, file), file)
                return 'Exported %s' % (file)
        return 'Could not find %s' % (file_name)

    # ---------------------------------------------------------------------------- #
    #                                 MMT Commands                                 #
    # ---------------------------------------------------------------------------- #

    def handle_mmt_command(self, command):
        """
            Handles the MMT-Commands 'archive', 'construct' and 'subdir'

            'command': str; the command
        """
        name = get_name(command)
        args = get_args(command)
        if name == 'archive':
            if not args:
                # TODO make this into a sring so output order doesn't get screwed
                tree(dir=self.mmtInterface.get_archive_path(),
                     archive_name=self.mmtInterface.get_archive())
                return ''
            if len(args) > 1:
                return 'archive takes only one argument!'
            return self.mmtInterface.handle_archive(args[0])

        if name == 'archives':
            return ', '.join(self.mmtInterface.get_archives())

        elif name == 'construct':
            view = None
            if (args[0] == '-v'):
                view = args[1]
                ASTsStr = ' '.join(args[2:])
            else:
                ASTsStr = ' '.join(args)

            h = ASTsStr.split('|')
            ASTs = list(map(str.strip, h))
            return self.mmtInterface.construct(ASTs, view)

        elif name == 'subdir':
            if args and len(args) == 1:
                return self.mmtInterface.create_subdir(args[0])
            elif not args:
                return os.path.relpath(
                    self.mmtInterface.get_cwd(),
                    os.path.join(self.mmtInterface.get_archive_path(),
                                 'source'))

    # ---------------------------------------------------------------------------- #
    #                               GF Content                                     #
    # ---------------------------------------------------------------------------- #

    def handle_grammar(self, content, name):
        """
            Handles grammar input

            `content`: str; the content of the grammar
            `name`: str; the name of the grammar
        """

        file_name = "%s.gf" % (name)
        file_path = os.path.join(self.mmtInterface.get_cwd(), file_name)
        try:
            with open(file_path, 'w') as f:
                f.write(content)
                f.close()
        except OSError:
            return 'Failed to create grammar %s' % (name)
        out = self.gfRepl.handle_gf_command("import %s" % (file_path))
        if out == 'success' or out.startswith('Abstract changed'):
            build_result = self.mmtInterface.build_file(
                file_name)  # build the Grammar with the GlfBuild extension
            if build_result['isSuccessful']:
                self.grammars[name] = file_path
                return "Defined %s" % (name)
            else:
                return '\n'.join(build_result['errors'])
        return out

    def search_grammars(self):
        grammars = {}
        cwd = self.mmtInterface.get_cwd()
        for file in os.listdir(cwd):
            if file.endswith(".gf"):
                path = os.path.join(cwd, file)
                name = os.path.splitext(file)
                grammars[name] = path
        return grammars

    def get_grammars(self):
        return self.grammars
示例#27
0
class TestLinkOrCopy(object):
    def setUp(self):
        self.tempdir = TemporaryDirectory()
        self.src = self.dst("src")
        with open(self.src, "w") as f:
            f.write("Hello, world!")

    def tearDown(self):
        self.tempdir.cleanup()

    def dst(self, *args):
        return os.path.join(self.tempdir.name, *args)

    def assert_inode_not_equal(self, a, b):
        nt.assert_not_equals(
            os.stat(a).st_ino,
            os.stat(b).st_ino,
            "%r and %r do reference the same indoes" % (a, b))

    def assert_inode_equal(self, a, b):
        nt.assert_equals(
            os.stat(a).st_ino,
            os.stat(b).st_ino,
            "%r and %r do not reference the same indoes" % (a, b))

    def assert_content_equal(self, a, b):
        with open(a) as a_f:
            with open(b) as b_f:
                nt.assert_equals(a_f.read(), b_f.read())

    @skip_win32
    def test_link_successful(self):
        dst = self.dst("target")
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)

    @skip_win32
    def test_link_into_dir(self):
        dst = self.dst("some_dir")
        os.mkdir(dst)
        path.link_or_copy(self.src, dst)
        expected_dst = self.dst("some_dir", os.path.basename(self.src))
        self.assert_inode_equal(self.src, expected_dst)

    @skip_win32
    def test_target_exists(self):
        dst = self.dst("target")
        open(dst, "w").close()
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)

    @skip_win32
    def test_no_link(self):
        real_link = os.link
        try:
            del os.link
            dst = self.dst("target")
            path.link_or_copy(self.src, dst)
            self.assert_content_equal(self.src, dst)
            self.assert_inode_not_equal(self.src, dst)
        finally:
            os.link = real_link

    @skip_if_not_win32
    def test_windows(self):
        dst = self.dst("target")
        path.link_or_copy(self.src, dst)
        self.assert_content_equal(self.src, dst)
示例#28
0
class TestContentsManager(TestCase):
    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)

    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_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)
示例#29
0
class TestContentsManager(TestCase):
    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, abs_path, rel_path):
        """make subdirectory, rel_path is the relative path
        to that directory from the location where the server started"""
        os_path = os.path.join(abs_path, rel_path)
        try:
            os.makedirs(os_path)
        except OSError:
            print("Directory already exists: %r" % os_path)
        return os_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']
        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)

    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(cm.root_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 getting directory model
        dirmodel = cm.get('foo')
        self.assertEqual(dirmodel['type'], 'directory')

        with self.assertRaises(HTTPError):
            cm.get('foo', type='file')

    @dec.skip_win32
    def test_bad_symlink(self):
        cm = self.contents_manager
        path = 'test bad symlink'
        os_path = self.make_dir(cm.root_dir, path)

        file_model = cm.new_untitled(path=path, ext='.txt')

        # create a broken symlink
        os.symlink("target", os.path.join(os_path, "bad symlink"))
        model = cm.get(path)
        self.assertEqual(model['content'], [file_model])

    @dec.skip_win32
    def test_good_symlink(self):
        cm = self.contents_manager
        parent = 'test good symlink'
        name = 'good symlink'
        path = '{0}/{1}'.format(parent, name)
        os_path = self.make_dir(cm.root_dir, parent)

        file_model = cm.new(path=parent + '/zfoo.txt')

        # create a good symlink
        os.symlink(file_model['name'], os.path.join(os_path, name))
        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_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(cm.root_dir, 'foo')
        model = cm.new_untitled(path=sub_dir, type='notebook')
        name = model['name']
        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(cm.root_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 a 'get' on the deleted notebook raises and error
        self.assertRaises(HTTPError, cm.get, path)

    def test_copy(self):
        cm = self.contents_manager
        parent = u'å b'
        name = u'nb √.ipynb'
        path = u'{0}/{1}'.format(parent, name)
        os.mkdir(os.path.join(cm.root_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)
示例#30
0
class TestMagicRunWithPackage(unittest.TestCase):
    def writefile(self, name, content):
        path = os.path.join(self.tempdir.name, name)
        d = os.path.dirname(path)
        if not os.path.isdir(d):
            os.makedirs(d)
        with open(path, 'w') as f:
            f.write(textwrap.dedent(content))

    def setUp(self):
        self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
        """Temporary valid python package name."""

        self.value = int(random.random() * 10000)

        self.tempdir = TemporaryDirectory()
        self.__orig_cwd = py3compat.getcwd()
        sys.path.insert(0, self.tempdir.name)

        self.writefile(os.path.join(package, '__init__.py'), '')
        self.writefile(os.path.join(package, 'sub.py'), """
        x = {0!r}
        """.format(self.value))
        self.writefile(os.path.join(package, 'relative.py'), """
        from .sub import x
        """)
        self.writefile(
            os.path.join(package, 'absolute.py'), """
        from {0}.sub import x
        """.format(package))

    def tearDown(self):
        os.chdir(self.__orig_cwd)
        sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
        self.tempdir.cleanup()

    def check_run_submodule(self, submodule, opts=''):
        _ip.user_ns.pop('x', None)
        _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
        self.assertEqual(
            _ip.user_ns['x'], self.value,
            'Variable `x` is not loaded from module `{0}`.'.format(submodule))

    def test_run_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute')

    def test_run_submodule_with_relative_import(self):
        """Run submodule that has a relative import statement (#2727)."""
        self.check_run_submodule('relative')

    def test_prun_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute', '-p')

    def test_prun_submodule_with_relative_import(self):
        self.check_run_submodule('relative', '-p')

    def with_fake_debugger(func):
        @functools.wraps(func)
        def wrapper(*args, **kwds):
            with tt.monkeypatch(debugger.Pdb, 'run', staticmethod(eval)):
                return func(*args, **kwds)

        return wrapper

    @with_fake_debugger
    def test_debug_run_submodule_with_absolute_import(self):
        self.check_run_submodule('absolute', '-d')

    @with_fake_debugger
    def test_debug_run_submodule_with_relative_import(self):
        self.check_run_submodule('relative', '-d')
示例#31
0
class TestLinkOrCopy(object):
    def setUp(self):
        self.tempdir = TemporaryDirectory()
        self.src = self.dst("src")
        with open(self.src, "w") as f:
            f.write("Hello, world!")

    def tearDown(self):
        self.tempdir.cleanup()

    def dst(self, *args):
        return os.path.join(self.tempdir.name, *args)

    def assert_inode_not_equal(self, a, b):
        nt.assert_not_equal(os.stat(a).st_ino, os.stat(b).st_ino,
                            "%r and %r do reference the same indoes" %(a, b))

    def assert_inode_equal(self, a, b):
        nt.assert_equal(os.stat(a).st_ino, os.stat(b).st_ino,
                        "%r and %r do not reference the same indoes" %(a, b))

    def assert_content_equal(self, a, b):
        with open(a) as a_f:
            with open(b) as b_f:
                nt.assert_equal(a_f.read(), b_f.read())

    @skip_win32
    def test_link_successful(self):
        dst = self.dst("target")
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)

    @skip_win32
    def test_link_into_dir(self):
        dst = self.dst("some_dir")
        os.mkdir(dst)
        path.link_or_copy(self.src, dst)
        expected_dst = self.dst("some_dir", os.path.basename(self.src))
        self.assert_inode_equal(self.src, expected_dst)

    @skip_win32
    def test_target_exists(self):
        dst = self.dst("target")
        open(dst, "w").close()
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)

    @skip_win32
    def test_no_link(self):
        real_link = os.link
        try:
            del os.link
            dst = self.dst("target")
            path.link_or_copy(self.src, dst)
            self.assert_content_equal(self.src, dst)
            self.assert_inode_not_equal(self.src, dst)
        finally:
            os.link = real_link

    @skip_if_not_win32
    def test_windows(self):
        dst = self.dst("target")
        path.link_or_copy(self.src, dst)
        self.assert_content_equal(self.src, dst)

    def test_link_twice(self):
        # Linking the same file twice shouldn't leave duplicates around.
        # See https://github.com/ipython/ipython/issues/6450
        dst = self.dst('target')
        path.link_or_copy(self.src, dst)
        path.link_or_copy(self.src, dst)
        self.assert_inode_equal(self.src, dst)
        nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target'])
示例#32
0
class TestContentsManager(TestCase):
    
    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)

    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_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)