Skip to content

Commit

Permalink
Merge pull request #252 from davidszotten/optional-interactive-interp…
Browse files Browse the repository at this point in the history
…reters

Test tweaks on top of #245 by @mytho
  • Loading branch information
mattbennett committed May 11, 2015
2 parents 62157c8 + 3bf3215 commit a17a56b
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ are in form of *headline.major.minor* numbers. Backwards-compatible changes
increment the minor version number only.


Unreleased
----------

* Nameko shell to use bpython or ipython interpreter if available


Version 2.1.0
-------------

Expand Down
2 changes: 2 additions & 0 deletions docs/spelling_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ args
async
auth
backend
bpython
bugfix
bugfixes
bytestring
Expand Down Expand Up @@ -45,6 +46,7 @@ instantiate
instantiation
interdependencies
interdependency
ipython
iterable
iterables
javascript
Expand Down
52 changes: 44 additions & 8 deletions nameko/cli/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,52 @@
from nameko.standalone.events import event_dispatcher


SHELLS = ['bpython', 'ipython', 'plain']


class ShellRunner(object):

def __init__(self, banner, local):
self.banner = banner
self.local = local

def bpython(self):
import bpython
bpython.embed(banner=self.banner, locals_=self.local)

def ipython(self):
from IPython import embed
embed(banner1=self.banner, user_ns=self.local)

def plain(self):
code.interact(banner=self.banner, local=self.local)

def start_shell(self, name):
available_shells = [name] if name else SHELLS

# Support the regular Python interpreter startup script if someone
# is using it.
startup = os.environ.get('PYTHONSTARTUP')
if startup and os.path.isfile(startup):
with open(startup, 'r') as f:
eval(compile(f.read(), startup, 'exec'), self.local)
del os.environ['PYTHONSTARTUP']

for name in available_shells:
try:
return getattr(self, name)()
except ImportError:
pass
self.plain()


def init_parser(parser):
parser.add_argument(
'--broker', default='amqp://guest:guest@localhost',
help='RabbitMQ broker url')
parser.add_argument(
'--interface', choices=SHELLS,
help='Specify an interactive interpreter interface.')
return parser


Expand Down Expand Up @@ -53,11 +95,5 @@ def main(args):
ctx = {}
ctx['n'] = make_nameko_helper(config)

# Support the regular Python interpreter startup script if someone
# is using it.
startup = os.environ.get('PYTHONSTARTUP')
if startup and os.path.isfile(startup):
with open(startup, 'r') as f:
eval(compile(f.read(), startup, 'exec'), ctx)

code.interact(banner=banner, local=ctx)
runner = ShellRunner(banner, ctx)
runner.start_shell(name=args.interface)
95 changes: 87 additions & 8 deletions test/cli/test_shell.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from mock import patch
import os
import sys

from mock import patch, Mock
import pytest

from nameko.standalone.rpc import ClusterProxy
from nameko.cli.main import setup_parser
Expand All @@ -11,20 +15,95 @@ def test_helper_module(rabbit_config):
helper.disconnect()


def test_basic(tmpdir):
@pytest.yield_fixture
def pystartup(tmpdir):
startup = tmpdir.join('startup.py')
startup.write('foo = 42')

with patch.dict(os.environ, {'PYTHONSTARTUP': str(startup)}):
yield


@pytest.yield_fixture(autouse=True)
def fake_alternative_interpreters():
# Make sure these appear unavailable even if installed. We cheat slightly,
# and have the call to `embed` raise the ImportError, rather than the
# actual module import (this is easier to do and has the same effect in our
# case).
fake_module = Mock()
fake_module.embed.side_effect = ImportError
with patch.dict(sys.modules, {
'IPython': fake_module,
'bpython': fake_module,
}):
yield


def test_basic(pystartup):
parser = setup_parser()
args = parser.parse_args(['shell'])

startup = tmpdir.join('startup.py')
startup.write('foo = 42')
with patch('nameko.cli.shell.code') as code:
main(args)

with patch('nameko.cli.shell.os.environ') as environ:
environ.get.return_value = str(startup)
with patch('nameko.cli.shell.code') as code:
main(args)
_, kwargs = code.interact.call_args
local = kwargs['local']
assert 'n' in local.keys()
assert local['foo'] == 42
local['n'].disconnect()


def test_plain(pystartup):
parser = setup_parser()
args = parser.parse_args(['shell', '--interface', 'plain'])

with patch('nameko.cli.shell.code') as code:
main(args)

_, kwargs = code.interact.call_args
local = kwargs['local']
assert 'n' in local.keys()
assert local['foo'] == 42
local['n'].disconnect()


def test_plain_fallback(pystartup):
parser = setup_parser()
args = parser.parse_args(['shell', '--interface', 'bpython'])

with patch('nameko.cli.shell.code') as code:
main(args)

_, kwargs = code.interact.call_args
local = kwargs['local']
assert 'n' in local.keys()
assert local['foo'] == 42
local['n'].disconnect()


def test_bpython(pystartup):
parser = setup_parser()
args = parser.parse_args(['shell', '--interface', 'bpython'])

with patch('bpython.embed') as embed:
main(args)

_, kwargs = embed.call_args
local = kwargs['locals_']
assert 'n' in local.keys()
assert local['foo'] == 42
local['n'].disconnect()


def test_ipython(pystartup):
parser = setup_parser()
args = parser.parse_args(['shell', '--interface', 'ipython'])

with patch('IPython.embed') as embed:
main(args)

_, kwargs = embed.call_args
local = kwargs['user_ns']
assert 'n' in local.keys()
assert local['foo'] == 42
local['n'].disconnect()

0 comments on commit a17a56b

Please sign in to comment.