From f1013bebcdd013cd1cb47cf7585c0eaa34ec3b75 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Camguilhem Date: Sat, 19 Nov 2011 16:09:41 +0100 Subject: add bpython support for pshell --- docs/narr/commandline.rst | 14 ++++++++++++++ pyramid/scripts/pshell.py | 18 ++++++++++++++++++ pyramid/tests/test_scripts/dummy.py | 9 +++++++-- pyramid/tests/test_scripts/test_pshell.py | 9 +++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 0dc41e919..dc2b75ed6 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -111,6 +111,7 @@ For a URL that doesn't match any views, ``pviews`` will simply print out a single: interactive shell single: IPython single: pshell + single: bpython .. _interactive_shell: @@ -284,6 +285,19 @@ standard Python interpreter shell unconditionally. development.ini#MyProject +bpython +~~~~~~~ + +If you have `bpython `_ installed in +the interpreter you use to invoke the ``pshell`` command, ``pshell`` will use +a bpython interactive shell instead of a standard Python if you pass the ``-b`` +or ``--enable-bpython`` flag to the ``pshell`` command. + +.. code-block:: text + + [chrism@vitaminf shellenv]$ ../bin/pshell --enable-bpython \ + development.ini#MyProject + .. index:: pair: routes; printing single: proutes diff --git a/pyramid/scripts/pshell.py b/pyramid/scripts/pshell.py index 499d96aca..d04d9faff 100644 --- a/pyramid/scripts/pshell.py +++ b/pyramid/scripts/pshell.py @@ -40,6 +40,10 @@ class PShellCommand(object): action='store_true', dest='disable_ipython', help="Don't use IPython even if it is available") + parser.add_option('-b', '--enable-bpython', + action='store_true', + dest='enable_bpython', + help="Use bpython as pshell") parser.add_option('--setup', dest='setup', help=("A callable that will be passed the environment " @@ -142,6 +146,9 @@ class PShellCommand(object): for var in sorted(self.object_help.keys()): help += '\n %-12s %s' % (var, self.object_help[var]) + if shell is None and self.options.enable_bpython: + shell = self.make_bpython_shell() + if shell is None and not self.options.disable_ipython: shell = self.make_ipython_v0_11_shell() if shell is None: @@ -163,6 +170,17 @@ class PShellCommand(object): interact(banner, local=env) return shell + def make_bpython_shell(self, BPShellFactory=None): + if BPShellFactory is None: # pragma: no cover + try: + from bpython import embed + BPShellFactory = embed + except ImportError: + return None + def shell(env, help): + BPShell = BPShellFactory(locals_=env, banner=help + '\n') + return shell + def make_ipython_v0_11_shell(self, IPShellFactory=None): if IPShellFactory is None: # pragma: no cover try: diff --git a/pyramid/tests/test_scripts/dummy.py b/pyramid/tests/test_scripts/dummy.py index 3275f7804..d580203af 100644 --- a/pyramid/tests/test_scripts/dummy.py +++ b/pyramid/tests/test_scripts/dummy.py @@ -5,7 +5,7 @@ class DummyTweens(object): self.name_to_alias = {} def implicit(self): return self._implicit - + class Dummy: pass @@ -31,6 +31,11 @@ class DummyInteractor: self.banner = banner self.local = local +class DummyBPythonShell: + def __call__(self, locals_, banner): + self.locals_ = locals_ + self.banner = banner + class DummyIPShell(object): IP = Dummy() IP.BANNER = 'foo' @@ -72,7 +77,7 @@ class DummyRoute(object): def match(self, route): return self.matchdict - + class DummyRequest: application_url = 'http://example.com:5432' script_name = '' diff --git a/pyramid/tests/test_scripts/test_pshell.py b/pyramid/tests/test_scripts/test_pshell.py index e38da2077..95bdce463 100644 --- a/pyramid/tests/test_scripts/test_pshell.py +++ b/pyramid/tests/test_scripts/test_pshell.py @@ -22,6 +22,7 @@ class TestPShellCommand(unittest.TestCase): class Options(object): pass self.options = Options() self.options.disable_ipython = True + self.options.enable_bpython = False self.options.setup = None cmd.options = self.options return cmd @@ -34,6 +35,14 @@ class TestPShellCommand(unittest.TestCase): self.assertEqual(interact.local, {'foo': 'bar'}) self.assertTrue('a help message' in interact.banner) + def test_make_bpython_shell(self): + command = self._makeOne() + bpython = dummy.DummyBPythonShell() + shell = command.make_bpython_shell(bpython) + shell({'foo': 'bar'}, 'a help message') + self.assertEqual(bpython.locals_, {'foo': 'bar'}) + self.assertTrue('a help message' in bpython.banner) + def test_make_ipython_v0_11_shell(self): command = self._makeOne() ipshell_factory = dummy.DummyIPShellFactory() -- cgit v1.2.3 From 7bae406b11df0e3039798898e7951a09f31c0e53 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Camguilhem Date: Sun, 20 Nov 2011 21:45:21 +0100 Subject: add test_command_loads_bpython_shell --- pyramid/tests/test_scripts/test_pshell.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pyramid/tests/test_scripts/test_pshell.py b/pyramid/tests/test_scripts/test_pshell.py index 95bdce463..4f3853f91 100644 --- a/pyramid/tests/test_scripts/test_pshell.py +++ b/pyramid/tests/test_scripts/test_pshell.py @@ -82,6 +82,25 @@ class TestPShellCommand(unittest.TestCase): self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) + def test_command_loads_bpython_shell(self): + command = self._makeOne() + shell = dummy.DummyBPythonShell() + command.make_bpython_shell = lambda: shell + command.options.enable_bpython = True + command.run() + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.locals_, { + 'app':self.bootstrap.app, 'root':self.bootstrap.root, + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.banner) + def test_command_loads_default_shell_with_ipython_disabled(self): command = self._makeOne() shell = dummy.DummyShell() -- cgit v1.2.3 From 2cf5d280866e8936b0fee0952c89ebde164337ee Mon Sep 17 00:00:00 2001 From: Jean-Philippe Camguilhem Date: Tue, 22 Nov 2011 00:20:07 +0100 Subject: add bpython support to pshell with raydeo remarks and design --- docs/narr/commandline.rst | 34 +++++++------------ pyramid/scripts/pshell.py | 26 ++++++++------- pyramid/tests/test_scripts/test_pshell.py | 55 +++++++++++++++++-------------- 3 files changed, 56 insertions(+), 59 deletions(-) diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index dc2b75ed6..0f0e17ca6 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -268,34 +268,22 @@ exposed, and the request is configured to generate urls from the host .. index:: single: IPython + single: bpython -IPython -~~~~~~~ - -If you have `IPython `_ installed in -the interpreter you use to invoke the ``pshell`` command, ``pshell`` will use -an IPython interactive shell instead of a standard Python interpreter shell. -If you don't want this to happen, even if you have IPython installed, you can -pass the ``--disable-ipython`` flag to the ``pshell`` command to use a -standard Python interpreter shell unconditionally. - -.. code-block:: text - - [chrism@vitaminf shellenv]$ ../bin/pshell --disable-ipython \ - development.ini#MyProject - - -bpython -~~~~~~~ +IPython or bpython +~~~~~~~~~~~~~~~~~~ -If you have `bpython `_ installed in -the interpreter you use to invoke the ``pshell`` command, ``pshell`` will use -a bpython interactive shell instead of a standard Python if you pass the ``-b`` -or ``--enable-bpython`` flag to the ``pshell`` command. +If you have `IPython `_ or +`bpython `_ or both installed in +the interpreter you use to invoke the ``pshell`` command, ``pshell`` will +autodiscover them and use the first respectively found in this order : +IPython, bpython, standard Python interpreter. However you could +specifically invoke one of your choice with the ``-p choice`` or +``--python-shell choice`` option. .. code-block:: text - [chrism@vitaminf shellenv]$ ../bin/pshell --enable-bpython \ + [chrism@vitaminf shellenv]$ ../bin/pshell -p ipython | bpython | python \ development.ini#MyProject .. index:: diff --git a/pyramid/scripts/pshell.py b/pyramid/scripts/pshell.py index d04d9faff..3fbfa5e62 100644 --- a/pyramid/scripts/pshell.py +++ b/pyramid/scripts/pshell.py @@ -36,14 +36,9 @@ class PShellCommand(object): summary = "Open an interactive shell with a Pyramid application loaded" parser = optparse.OptionParser() - parser.add_option('-d', '--disable-ipython', - action='store_true', - dest='disable_ipython', - help="Don't use IPython even if it is available") - parser.add_option('-b', '--enable-bpython', - action='store_true', - dest='enable_bpython', - help="Use bpython as pshell") + parser.add_option('-p', '--python-shell', + action='store', type='string', dest='python_shell', + default = '', help='ipython | bpython | python') parser.add_option('--setup', dest='setup', help=("A callable that will be passed the environment " @@ -146,14 +141,23 @@ class PShellCommand(object): for var in sorted(self.object_help.keys()): help += '\n %-12s %s' % (var, self.object_help[var]) - if shell is None and self.options.enable_bpython: - shell = self.make_bpython_shell() + user_shell = self.options.python_shell.lower() + if not user_shell: + if shell is None: + shell = self.make_ipython_v0_11_shell() + if shell is None: + shell = self.make_ipython_v0_10_shell() + if shell is None: + shell = self.make_bpython_shell() - if shell is None and not self.options.disable_ipython: + if shell is None and user_shell == 'ipython': shell = self.make_ipython_v0_11_shell() if shell is None: shell = self.make_ipython_v0_10_shell() + if shell is None and user_shell == 'bpython': + shell = self.make_bpython_shell() + if shell is None: shell = self.make_default_shell() diff --git a/pyramid/tests/test_scripts/test_pshell.py b/pyramid/tests/test_scripts/test_pshell.py index 4f3853f91..4e5deb31d 100644 --- a/pyramid/tests/test_scripts/test_pshell.py +++ b/pyramid/tests/test_scripts/test_pshell.py @@ -21,8 +21,7 @@ class TestPShellCommand(unittest.TestCase): if patch_options: class Options(object): pass self.options = Options() - self.options.disable_ipython = True - self.options.enable_bpython = False + self.options.python_shell = '' self.options.setup = None cmd.options = self.options return cmd @@ -67,6 +66,7 @@ class TestPShellCommand(unittest.TestCase): shell = dummy.DummyShell() command.make_ipython_v0_11_shell = lambda: None command.make_ipython_v0_10_shell = lambda: None + command.make_bpython_shell = lambda: None command.make_default_shell = lambda: shell command.run() self.assertTrue(self.config_factory.parser) @@ -82,33 +82,15 @@ class TestPShellCommand(unittest.TestCase): self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) - def test_command_loads_bpython_shell(self): - command = self._makeOne() - shell = dummy.DummyBPythonShell() - command.make_bpython_shell = lambda: shell - command.options.enable_bpython = True - command.run() - self.assertTrue(self.config_factory.parser) - self.assertEqual(self.config_factory.parser.filename, - '/foo/bar/myapp.ini') - self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') - self.assertEqual(shell.locals_, { - 'app':self.bootstrap.app, 'root':self.bootstrap.root, - 'registry':self.bootstrap.registry, - 'request':self.bootstrap.request, - 'root_factory':self.bootstrap.root_factory, - }) - self.assertTrue(self.bootstrap.closer.called) - self.assertTrue(shell.banner) - - def test_command_loads_default_shell_with_ipython_disabled(self): + def test_command_loads_default_shell_with_unknow_shell(self): command = self._makeOne() shell = dummy.DummyShell() bad_shell = dummy.DummyShell() command.make_ipython_v0_11_shell = lambda: bad_shell command.make_ipython_v0_10_shell = lambda: bad_shell + command.make_bpython_shell = lambda: bad_shell command.make_default_shell = lambda: shell - command.options.disable_ipython = True + command.options.python_shell = 'unknow_python_shell' command.run() self.assertTrue(self.config_factory.parser) self.assertEqual(self.config_factory.parser.filename, @@ -129,8 +111,9 @@ class TestPShellCommand(unittest.TestCase): shell = dummy.DummyShell() command.make_ipython_v0_11_shell = lambda: shell command.make_ipython_v0_10_shell = lambda: None + command.make_bpython_shell = lambda: None command.make_default_shell = lambda: None - command.options.disable_ipython = False + command.options.python_shell = 'ipython' command.run() self.assertTrue(self.config_factory.parser) self.assertEqual(self.config_factory.parser.filename, @@ -150,8 +133,9 @@ class TestPShellCommand(unittest.TestCase): shell = dummy.DummyShell() command.make_ipython_v0_11_shell = lambda: None command.make_ipython_v0_10_shell = lambda: shell + command.make_bpython_shell = lambda: None command.make_default_shell = lambda: None - command.options.disable_ipython = False + command.options.python_shell = 'ipython' command.run() self.assertTrue(self.config_factory.parser) self.assertEqual(self.config_factory.parser.filename, @@ -166,6 +150,27 @@ class TestPShellCommand(unittest.TestCase): self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) + def test_command_loads_bpython_shell(self): + command = self._makeOne() + shell = dummy.DummyBPythonShell() + command.make_ipython_v0_11_shell = lambda: None + command.make_ipython_v0_10_shell = lambda: None + command.make_bpython_shell = lambda: shell + command.options.python_shell = 'bpython' + command.run() + self.assertTrue(self.config_factory.parser) + self.assertEqual(self.config_factory.parser.filename, + '/foo/bar/myapp.ini') + self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp') + self.assertEqual(shell.locals_, { + 'app':self.bootstrap.app, 'root':self.bootstrap.root, + 'registry':self.bootstrap.registry, + 'request':self.bootstrap.request, + 'root_factory':self.bootstrap.root_factory, + }) + self.assertTrue(self.bootstrap.closer.called) + self.assertTrue(shell.banner) + def test_command_loads_custom_items(self): command = self._makeOne() model = dummy.Dummy() -- cgit v1.2.3 From ce1d0f0ea126fc8d1e90e0a85a5e735ac34afbae Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 21 Nov 2011 19:01:18 -0600 Subject: bpython doesn't actually use a factory --- pyramid/scripts/pshell.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyramid/scripts/pshell.py b/pyramid/scripts/pshell.py index 3fbfa5e62..8cf1a4b39 100644 --- a/pyramid/scripts/pshell.py +++ b/pyramid/scripts/pshell.py @@ -178,11 +178,11 @@ class PShellCommand(object): if BPShellFactory is None: # pragma: no cover try: from bpython import embed - BPShellFactory = embed + BPShell = embed except ImportError: return None def shell(env, help): - BPShell = BPShellFactory(locals_=env, banner=help + '\n') + BPShell(locals_=env, banner=help + '\n') return shell def make_ipython_v0_11_shell(self, IPShellFactory=None): -- cgit v1.2.3 From 3808f7fe58f9e5724fbf9ab7e213cde4f21e26f2 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 21 Nov 2011 19:30:40 -0600 Subject: Added tests for shell ordering in pshell. --- pyramid/scripts/pshell.py | 34 ++++++++++++--------- pyramid/tests/test_scripts/test_pshell.py | 49 +++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/pyramid/scripts/pshell.py b/pyramid/scripts/pshell.py index 8cf1a4b39..72e2c0a89 100644 --- a/pyramid/scripts/pshell.py +++ b/pyramid/scripts/pshell.py @@ -38,7 +38,7 @@ class PShellCommand(object): parser = optparse.OptionParser() parser.add_option('-p', '--python-shell', action='store', type='string', dest='python_shell', - default = '', help='ipython | bpython | python') + default='', help='ipython | bpython | python') parser.add_option('--setup', dest='setup', help=("A callable that will be passed the environment " @@ -141,30 +141,36 @@ class PShellCommand(object): for var in sorted(self.object_help.keys()): help += '\n %-12s %s' % (var, self.object_help[var]) + if shell is None: + shell = self.make_shell() + + try: + shell(env, help) + finally: + closer() + + def make_shell(self): + shell = None user_shell = self.options.python_shell.lower() if not user_shell: + shell = self.make_ipython_v0_11_shell() if shell is None: - shell = self.make_ipython_v0_11_shell() - if shell is None: - shell = self.make_ipython_v0_10_shell() - if shell is None: - shell = self.make_bpython_shell() + shell = self.make_ipython_v0_10_shell() + if shell is None: + shell = self.make_bpython_shell() - if shell is None and user_shell == 'ipython': + elif user_shell == 'ipython': shell = self.make_ipython_v0_11_shell() if shell is None: shell = self.make_ipython_v0_10_shell() - if shell is None and user_shell == 'bpython': + elif user_shell == 'bpython': shell = self.make_bpython_shell() if shell is None: shell = self.make_default_shell() - try: - shell(env, help) - finally: - closer() + return shell def make_default_shell(self, interact=interact): def shell(env, help): @@ -174,8 +180,8 @@ class PShellCommand(object): interact(banner, local=env) return shell - def make_bpython_shell(self, BPShellFactory=None): - if BPShellFactory is None: # pragma: no cover + def make_bpython_shell(self, BPShell=None): + if BPShell is None: # pragma: no cover try: from bpython import embed BPShell = embed diff --git a/pyramid/tests/test_scripts/test_pshell.py b/pyramid/tests/test_scripts/test_pshell.py index 4e5deb31d..c1f648b6f 100644 --- a/pyramid/tests/test_scripts/test_pshell.py +++ b/pyramid/tests/test_scripts/test_pshell.py @@ -171,6 +171,55 @@ class TestPShellCommand(unittest.TestCase): self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.banner) + def test_shell_ipython_ordering(self): + command = self._makeOne() + shell0_11 = dummy.DummyShell() + shell0_10 = dummy.DummyShell() + command.make_ipython_v0_11_shell = lambda: shell0_11 + command.make_ipython_v0_10_shell = lambda: shell0_10 + command.make_bpython_shell = lambda: None + shell = command.make_shell() + self.assertEqual(shell, shell0_11) + + command.options.python_shell = 'ipython' + shell = command.make_shell() + self.assertEqual(shell, shell0_11) + + def test_shell_ordering(self): + command = self._makeOne() + ipshell = dummy.DummyShell() + bpshell = dummy.DummyShell() + dshell = dummy.DummyShell() + command.make_ipython_v0_11_shell = lambda: None + command.make_ipython_v0_10_shell = lambda: None + command.make_bpython_shell = lambda: None + command.make_default_shell = lambda: dshell + + shell = command.make_shell() + self.assertEqual(shell, dshell) + + command.options.python_shell = 'ipython' + shell = command.make_shell() + self.assertEqual(shell, dshell) + + command.options.python_shell = 'bpython' + shell = command.make_shell() + self.assertEqual(shell, dshell) + + command.make_ipython_v0_11_shell = lambda: ipshell + command.make_bpython_shell = lambda: bpshell + command.options.python_shell = 'ipython' + shell = command.make_shell() + self.assertEqual(shell, ipshell) + + command.options.python_shell = 'bpython' + shell = command.make_shell() + self.assertEqual(shell, bpshell) + + command.options.python_shell = 'python' + shell = command.make_shell() + self.assertEqual(shell, dshell) + def test_command_loads_custom_items(self): command = self._makeOne() model = dummy.Dummy() -- cgit v1.2.3 From 995133918877809aeea06bce93149104ba800304 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 21 Nov 2011 20:44:42 -0600 Subject: typo --- pyramid/tests/test_scripts/test_pshell.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyramid/tests/test_scripts/test_pshell.py b/pyramid/tests/test_scripts/test_pshell.py index c1f648b6f..765042152 100644 --- a/pyramid/tests/test_scripts/test_pshell.py +++ b/pyramid/tests/test_scripts/test_pshell.py @@ -82,7 +82,7 @@ class TestPShellCommand(unittest.TestCase): self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) - def test_command_loads_default_shell_with_unknow_shell(self): + def test_command_loads_default_shell_with_unknown_shell(self): command = self._makeOne() shell = dummy.DummyShell() bad_shell = dummy.DummyShell() -- cgit v1.2.3