Completed
Pull Request — master (#169)
by Björn
24:24
created

neovim.start_host()   B

Complexity

Conditions 5

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 24.6646
Metric Value
cc 5
dl 0
loc 30
ccs 1
cts 13
cp 0.0769
crap 24.6646
rs 8.0894
1
"""Python client for Nvim.
2
3
Client library for talking with Nvim processes via it's msgpack-rpc API.
4
"""
5 6
import logging
6 6
import os
7 6
import sys
8
9 6
from .api import DecodeHook, Nvim, SessionHook
10 6
from .msgpack_rpc import (child_session, socket_session, stdio_session,
11
                          tcp_session)
12 6
from .plugin import (Host, autocmd, command, encoding, function, plugin,
13
                     rpc_export, shutdown_hook)
14
15
16 6
__all__ = ('tcp_session', 'socket_session', 'stdio_session', 'child_session',
17
           'start_host', 'autocmd', 'command', 'encoding', 'function',
18
           'plugin', 'rpc_export', 'Host', 'DecodeHook', 'Nvim',
19
           'SessionHook', 'shutdown_hook', 'attach', 'setup_logging')
20
21
22 6
def start_host(session=None):
23
    """Promote the current process into python plugin host for Nvim.
24
25
    Start msgpack-rpc event loop for `session`, listening for Nvim requests
26
    and notifications. It registers Nvim commands for loading/unloading
27
    python plugins.
28
29
    The sys.stdout and sys.stderr streams are redirected to Nvim through
30
    `session`. That means print statements probably won't work as expected
31
    while this function doesn't return.
32
33
    This function is normally called at program startup and could have been
34
    defined as a separate executable. It is exposed as a library function for
35
    testing purposes only.
36
    """
37
    plugins = []
38
    for arg in sys.argv:
39
        _, ext = os.path.splitext(arg)
40
        if ext == '.py':
41
            plugins.append(arg)
42
43
    if not plugins:
44
        sys.exit('must specify at least one plugin as argument')
45
46
    setup_logging()
47
48
    if not session:
49
        session = stdio_session()
50
    host = Host(Nvim.from_session(session))
51
    host.start(plugins)
52
53
54
def attach(session_type, address=None, port=None, path=None, argv=None):
55
    """Provide a nicer interface to create python api sessions.
56
57
    Previous machinery to create python api sessions is still there. This only
58
    creates a facade function to make things easier for the most usual cases.
59
    Thus, instead of:
60
        from neovim import socket_session, Nvim
61
        session = tcp_session(address=<address>, port=<port>)
62
        nvim = Nvim.from_session(session)
63
    You can now do:
64
        from neovim import attach
65
        nvim = attach('tcp', address=<address>, port=<port>)
66
    And also:
67
        nvim = attach('socket', path=<path>)
68
        nvim = attach('child', argv=<argv>)
69 6
        nvim = attach('stdio')
70
    """
71
    session = (tcp_session(address, port) if session_type == 'tcp' else
72
               socket_session(path) if session_type == 'socket' else
73
               stdio_session() if session_type == 'stdio' else
74
               child_session(argv) if session_type == 'child' else
75
               None)
76
77
    if not session:
78
        raise Exception('Unknown session type "%s"' % session_type)
79
80
    return Nvim.from_session(session)
81
82
83
def setup_logging():
84
    """Setup logging according to environment variables."""
85
    logger = logging.getLogger(__name__)
86 6
    if 'NVIM_PYTHON_LOG_FILE' in os.environ:
87
        logfile = (os.environ['NVIM_PYTHON_LOG_FILE'].strip() +
88
                   '_' + str(os.getpid()))
89
        handler = logging.FileHandler(logfile, 'w')
90
        handler.formatter = logging.Formatter(
91
            '%(asctime)s [%(levelname)s @ '
92 6
            '%(filename)s:%(funcName)s:%(lineno)s] %(process)s - %(message)s')
93
        logging.root.addHandler(handler)
94
        level = logging.INFO
95 6
        if 'NVIM_PYTHON_LOG_LEVEL' in os.environ:
96
            l = getattr(logging,
97
                        os.environ['NVIM_PYTHON_LOG_LEVEL'].strip(),
98
                        level)
99 6
            if isinstance(l, int):
100 6
                level = l
101
        logger.setLevel(level)
102
103
104 6
# Required for python 2.6
105 6
class NullHandler(logging.Handler):
106
    def emit(self, record):
107
        pass
108
109
110
if not logging.root.handlers:
111
    logging.root.addHandler(NullHandler())
112