Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds support for configuration of shells from scrapy.cfg and SCRAPY_PYTHON_SHELL. config snippet: cat <<EOF >> ~/.scrapy.cfg [settings] # shell can be one of ipython, bpython or python; # to be used as the interactive python console, if available. # (default is ipython, fallbacks in the order listed above) shell = python EOF (closes #270, #1100)
- Loading branch information
Showing
5 changed files
with
126 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,77 @@ | ||
from functools import wraps | ||
|
||
from scrapy.exceptions import NotConfigured | ||
|
||
def start_python_console(namespace=None, noipython=False, banner=''): | ||
"""Start Python console binded to the given namespace. If IPython is | ||
available, an IPython console will be started instead, unless `noipython` | ||
is True. Also, tab completion will be used on Unix systems. | ||
""" | ||
if namespace is None: | ||
namespace = {} | ||
|
||
def _embed_ipython_shell(namespace={}, banner=''): | ||
"""Start an IPython Shell""" | ||
try: | ||
try: # use IPython if available | ||
if noipython: | ||
raise ImportError() | ||
from IPython.terminal.embed import InteractiveShellEmbed | ||
from IPython.terminal.ipapp import load_default_config | ||
except ImportError: | ||
from IPython.frontend.terminal.embed import InteractiveShellEmbed | ||
from IPython.frontend.terminal.ipapp import load_default_config | ||
|
||
@wraps(_embed_ipython_shell) | ||
def wrapper(namespace=namespace, banner=''): | ||
config = load_default_config() | ||
shell = InteractiveShellEmbed( | ||
banner1=banner, user_ns=namespace, config=config) | ||
shell() | ||
return wrapper | ||
|
||
def _embed_bpython_shell(namespace={}, banner=''): | ||
"""Start a bpython shell""" | ||
import bpython | ||
@wraps(_embed_bpython_shell) | ||
def wrapper(namespace=namespace, banner=''): | ||
bpython.embed(locals_=namespace, banner=banner) | ||
return wrapper | ||
|
||
def _embed_standard_shell(namespace={}, banner=''): | ||
"""Start a standard python shell""" | ||
import code | ||
try: # readline module is only available on unix systems | ||
import readline | ||
except ImportError: | ||
pass | ||
else: | ||
import rlcompleter | ||
readline.parse_and_bind("tab:complete") | ||
@wraps(_embed_standard_shell) | ||
def wrapper(namespace=namespace, banner=''): | ||
code.interact(banner=banner, local=namespace) | ||
return wrapper | ||
_embed_python_shell = _embed_standard_shell | ||
|
||
def get_shell_embed_func(shells): | ||
"""Return the first acceptable shell-embed function | ||
from a given list of shell names. | ||
""" | ||
for shell in shells: | ||
try: | ||
_f = globals()['_embed_%s_shell' % (shell,)] | ||
except KeyError: continue | ||
if callable(_f): | ||
try: | ||
from IPython.terminal.embed import InteractiveShellEmbed | ||
from IPython.terminal.ipapp import load_default_config | ||
# function test: run all setup code (imports), | ||
# but dont fall into the shell | ||
return _f() | ||
except ImportError: | ||
from IPython.frontend.terminal.embed import InteractiveShellEmbed | ||
from IPython.frontend.terminal.ipapp import load_default_config | ||
continue | ||
|
||
config = load_default_config() | ||
shell = InteractiveShellEmbed( | ||
banner1=banner, user_ns=namespace, config=config) | ||
def start_python_console(namespace=None, banner='', shells=None): | ||
"""Start Python console bound to the given namespace. | ||
Readline support and tab completion will be used on Unix, if available. | ||
""" | ||
if namespace is None: | ||
namespace = {} | ||
if shells is None: | ||
shells = ['ipython', 'bpython', 'python'] | ||
|
||
try: | ||
shell = get_shell_embed_func(shells) | ||
if shell is not None: | ||
shell() | ||
except ImportError: | ||
import code | ||
try: # readline module is only available on unix systems | ||
import readline | ||
except ImportError: | ||
pass | ||
else: | ||
import rlcompleter | ||
readline.parse_and_bind("tab:complete") | ||
code.interact(banner=banner, local=namespace) | ||
except SystemExit: # raised when using exit() in python code.interact | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import unittest | ||
|
||
from scrapy.utils.console import get_shell_embed_func | ||
|
||
class UtilsConsoleTestCase(unittest.TestCase): | ||
|
||
def test_get_shell_embed_func(self): | ||
shell = get_shell_embed_func(['invalid']) | ||
self.assertEqual(shell, None) | ||
|
||
shell = get_shell_embed_func(['invalid','python']) | ||
assert callable(shell) | ||
self.assertEqual(shell.__name__, '_embed_standard_shell') | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |