Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'pull.356' into 1.2-branch

  • Loading branch information...
commit 415d082e8a8f39d3a39ea5a96f05ace9d55ec1e4 2 parents bf72c55 + c5d4f02
@mmerickel mmerickel authored
View
17 CHANGES.txt
@@ -1,3 +1,20 @@
+Next Release
+============
+
+Features
+--------
+
+- ``bpython`` interpreter compatibility in ``pshell``. See the "Command-Line
+ Pyramid" narrative docs chapter for more information.
+
+Backward Incompatibilities
+--------------------------
+
+- The ``pshell`` command (see "paster pshell") no longer accepts a
+ ``--disable-ipython`` command-line argument. Instead, it accepts a ``-p``
+ or ``--python-shell`` argument, which can be any of the values ``python``,
+ ``ipython`` or ``bpython``.
+
1.2.3 (2011-11-20)
==================
View
22 docs/narr/commandline.rst
@@ -110,6 +110,7 @@ out a *Not found* message.
.. index::
single: interactive shell
single: IPython
+ single: bpython
single: paster pshell
single: pshell
@@ -268,21 +269,22 @@ exposed, and the request is configured to generate urls from the host
.. index::
single: IPython
+ single: bpython
-IPython
-~~~~~~~
+IPython or bpython
+~~~~~~~~~~~~~~~~~~
-If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ installed in
-the interpreter you use to invoke the ``paster`` command, the ``pshell``
-command 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.
+If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ or
+`bpython <http://bpython-interpreter.org/>`_ 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/paster pshell --disable-ipython \
+ [chrism@vitaminf shellenv]$ ../bin/pshell -p ipython | bpython | python \
development.ini#MyProject
View
46 pyramid/paster.py
@@ -127,10 +127,9 @@ class PShellCommand(PCommand):
max_args = 1
parser = Command.standard_parser(simulate=True)
- 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('-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 "
@@ -222,18 +221,36 @@ def command(self, shell=None):
for var in sorted(self.object_help.keys()):
help += '\n %-12s %s' % (var, self.object_help[var])
- if shell is None and not self.options.disable_ipython:
+ 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_10_shell()
+ if shell is None:
+ shell = self.make_bpython_shell()
+
+ elif user_shell == 'ipython':
shell = self.make_ipython_v0_11_shell()
if shell is None:
shell = self.make_ipython_v0_10_shell()
+ 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):
@@ -243,6 +260,17 @@ def shell(env, help):
interact(banner, local=env)
return shell
+ def make_bpython_shell(self, BPShell=None):
+ if BPShell is None: # pragma: no cover
+ try:
+ from bpython import embed
+ BPShell = embed
+ except ImportError:
+ return None
+ def shell(env, help):
+ BPShell(locals_=env, banner=help + '\n')
+ return shell
+
def make_ipython_v0_11_shell(self, IPShellFactory=None):
if IPShellFactory is None: # pragma: no cover
try:
View
111 pyramid/tests/test_paster.py
@@ -20,8 +20,8 @@ def _makeOne(self, patch_bootstrap=True, patch_config=True,
if patch_options:
class Options(object): pass
self.options = Options()
- self.options.disable_ipython = True
self.options.setup = None
+ self.options.python_shell = ''
cmd.options = self.options
return cmd
@@ -33,6 +33,14 @@ def test_make_default_shell(self):
self.assertEqual(interact.local, {'foo': 'bar'})
self.assertTrue('a help message' in interact.banner)
+ def test_make_bpython_shell(self):
+ command = self._makeOne()
+ bpython = 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 = DummyIPShellFactory()
@@ -57,6 +65,7 @@ def test_command_loads_default_shell(self):
shell = 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.command()
self.assertTrue(self.config_factory.parser)
@@ -72,14 +81,15 @@ def test_command_loads_default_shell(self):
self.assertTrue(self.bootstrap.closer.called)
self.assertTrue(shell.help)
- def test_command_loads_default_shell_with_ipython_disabled(self):
+ def test_command_loads_default_shell_with_unknown_shell(self):
command = self._makeOne()
shell = DummyShell()
bad_shell = 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.command()
self.assertTrue(self.config_factory.parser)
self.assertEqual(self.config_factory.parser.filename,
@@ -100,8 +110,9 @@ def test_command_loads_ipython_v0_11(self):
shell = 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.command()
self.assertTrue(self.config_factory.parser)
self.assertEqual(self.config_factory.parser.filename,
@@ -121,8 +132,9 @@ def test_command_loads_ipython_v0_10(self):
shell = 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.command()
self.assertTrue(self.config_factory.parser)
self.assertEqual(self.config_factory.parser.filename,
@@ -137,6 +149,76 @@ def test_command_loads_ipython_v0_10(self):
self.assertTrue(self.bootstrap.closer.called)
self.assertTrue(shell.help)
+ def test_command_loads_bpython_shell(self):
+ command = self._makeOne()
+ shell = 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.command()
+ 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_shell_ipython_ordering(self):
+ command = self._makeOne()
+ shell0_11 = DummyShell()
+ shell0_10 = 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 = DummyShell()
+ bpshell = DummyShell()
+ dshell = 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()
@@ -334,7 +416,7 @@ class IMyRoute(Interface):
self.assertEqual(result, None)
self.assertEqual(len(L), 3)
self.assertEqual(L[-1].split()[:4], ['a', '/a', '<function', 'view'])
-
+
def test_single_route_one_view_registered_with_factory(self):
from zope.interface import Interface
from pyramid.registry import Registry
@@ -371,7 +453,7 @@ def test__get_mapper(self):
registry = Registry()
result = command._get_mapper(registry)
self.assertEqual(result.__class__, RoutesMapper)
-
+
class TestPViewsCommand(unittest.TestCase):
def _getTargetClass(self):
from pyramid.paster import PViewsCommand
@@ -570,7 +652,7 @@ def factory(request): pass
result = command._find_multi_routes(mapper, request)
self.assertEqual(result, [{'match':{}, 'route':routes[0]},
{'match':{}, 'route':routes[1]}])
-
+
def test__find_multi_routes_some_match(self):
command = self._makeOne()
def factory(request): pass
@@ -580,7 +662,7 @@ def factory(request): pass
request = DummyRequest({'PATH_INFO':'/a'})
result = command._find_multi_routes(mapper, request)
self.assertEqual(result, [{'match':{}, 'route':routes[1]}])
-
+
def test__find_multi_routes_none_match(self):
command = self._makeOne()
def factory(request): pass
@@ -590,7 +672,7 @@ def factory(request): pass
request = DummyRequest({'PATH_INFO':'/a'})
result = command._find_multi_routes(mapper, request)
self.assertEqual(result, [])
-
+
def test_views_command_not_found(self):
from pyramid.registry import Registry
registry = Registry()
@@ -953,7 +1035,7 @@ def __init__(self, implicit, explicit):
self.name_to_alias = {}
def implicit(self):
return self._implicit
-
+
class Dummy:
pass
@@ -979,6 +1061,11 @@ def __call__(self, banner, local):
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'
@@ -1030,7 +1117,7 @@ def __init__(self, name, pattern, factory=None,
def match(self, route):
return self.matchdict
-
+
class DummyRequest:
application_url = 'http://example.com:5432'
script_name = ''
Please sign in to comment.
Something went wrong with that request. Please try again.