File: console.py

package info (click to toggle)
python-scrapy 1.5.1-1%2Bdeb10u1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 4,404 kB
  • sloc: python: 25,793; xml: 199; makefile: 95; sh: 33
file content (94 lines) | stat: -rw-r--r-- 3,403 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from functools import wraps
from collections import OrderedDict

def _embed_ipython_shell(namespace={}, banner=''):
    """Start an IPython Shell"""
    try:
        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()
        # Always use .instace() to ensure _instance propagation to all parents
        # this is needed for <TAB> completion works well for new imports
        # and clear the instance to always have the fresh env
        # on repeated breaks like with inspect_response()
        InteractiveShellEmbed.clear_instance()
        shell = InteractiveShellEmbed.instance(
            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_ptpython_shell(namespace={}, banner=''):
    """Start a ptpython shell"""
    import ptpython.repl
    @wraps(_embed_ptpython_shell)
    def wrapper(namespace=namespace, banner=''):
        print(banner)
        ptpython.repl.embed(locals=namespace)
    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

DEFAULT_PYTHON_SHELLS = OrderedDict([
    ('ptpython', _embed_ptpython_shell),
    ('ipython', _embed_ipython_shell),
    ('bpython', _embed_bpython_shell),
    ('python', _embed_standard_shell),
])

def get_shell_embed_func(shells=None, known_shells=None):
    """Return the first acceptable shell-embed function
    from a given list of shell names.
    """
    if shells is None: # list, preference order of shells
        shells = DEFAULT_PYTHON_SHELLS.keys()
    if known_shells is None: # available embeddable shells
        known_shells = DEFAULT_PYTHON_SHELLS.copy()
    for shell in shells:
        if shell in known_shells:
            try:
                # function test: run all setup code (imports),
                # but dont fall into the shell
                return known_shells[shell]()
            except ImportError:
                continue

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 = {}

    try:
        shell = get_shell_embed_func(shells)
        if shell is not None:
            shell(namespace=namespace, banner=banner)
    except SystemExit: # raised when using exit() in python code.interact
        pass