Completed
Pull Request — master (#179)
by Björn
02:28 queued 01:02
created

neovim.NullHandler   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 3
Duplicated Lines 0 %

Test Coverage

Coverage 100%
Metric Value
dl 0
loc 3
ccs 3
cts 3
cp 1
rs 10
wmc 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A emit() 0 2 1
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
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
           '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
        elif os.path.isdir(arg):
43
            init = os.path.join(arg, '__init__.py')
44
            if os.path.isfile(init):
45
                plugins.append(arg)
46
47
    # This is a special case to support the old workaround of
48
    # adding an empty .py file to make a package directory
49
    # visible, and it should be removed soon.
50
    for path in list(plugins):
51
        dup = path + ".py"
52
        if os.path.isdir(path) and dup in plugins:
53
            plugins.remove(dup)
54
55
    if not plugins:
56
        sys.exit('must specify at least one plugin as argument')
57
58
    setup_logging()
59
60
    if not session:
61
        session = stdio_session()
62
    host = Host(Nvim.from_session(session))
63
    host.start(plugins)
64
65
66 6
def attach(session_type, address=None, port=None, path=None, argv=None):
67
    """Provide a nicer interface to create python api sessions.
68
69
    Previous machinery to create python api sessions is still there. This only
70
    creates a facade function to make things easier for the most usual cases.
71
    Thus, instead of:
72
        from neovim import socket_session, Nvim
73
        session = tcp_session(address=<address>, port=<port>)
74
        nvim = Nvim.from_session(session)
75
    You can now do:
76
        from neovim import attach
77
        nvim = attach('tcp', address=<address>, port=<port>)
78
    And also:
79
        nvim = attach('socket', path=<path>)
80
        nvim = attach('child', argv=<argv>)
81
        nvim = attach('stdio')
82
    """
83 6
    session = (tcp_session(address, port) if session_type == 'tcp' else
84
               socket_session(path) if session_type == 'socket' else
85
               stdio_session() if session_type == 'stdio' else
86
               child_session(argv) if session_type == 'child' else
87
               None)
88
89 6
    if not session:
90
        raise Exception('Unknown session type "%s"' % session_type)
91
92 6
    return Nvim.from_session(session)
93
94
95 6
def setup_logging():
96
    """Setup logging according to environment variables."""
97 6
    logger = logging.getLogger(__name__)
98 6
    if 'NVIM_PYTHON_LOG_FILE' in os.environ:
99
        logfile = (os.environ['NVIM_PYTHON_LOG_FILE'].strip() +
100
                   '_' + str(os.getpid()))
101
        handler = logging.FileHandler(logfile, 'w')
102
        handler.formatter = logging.Formatter(
103
            '%(asctime)s [%(levelname)s @ '
104
            '%(filename)s:%(funcName)s:%(lineno)s] %(process)s - %(message)s')
105
        logging.root.addHandler(handler)
106
        level = logging.INFO
107
        if 'NVIM_PYTHON_LOG_LEVEL' in os.environ:
108
            l = getattr(logging,
109
                        os.environ['NVIM_PYTHON_LOG_LEVEL'].strip(),
110
                        level)
111
            if isinstance(l, int):
112
                level = l
113
        logger.setLevel(level)
114
115
116
# Required for python 2.6
117 6
class NullHandler(logging.Handler):
118 6
    def emit(self, record):
119 6
        pass
120
121
122 6
if not logging.root.handlers:
123
    logging.root.addHandler(NullHandler())
124