Codebase list python-pynvim / 61cb62e
New upstream version 0.4.2 Thomas Goirand 3 years ago
31 changed file(s) with 244 addition(s) and 146 deletion(s). Raw diff Collapse all Expand all
00 Metadata-Version: 2.1
11 Name: pynvim
2 Version: 0.4.0
2 Version: 0.4.2
33 Summary: Python client to neovim
4 Home-page: http://github.com/neovim/python-client
4 Home-page: http://github.com/neovim/pynvim
55 Author: Thiago de Arruda
66 Author-email: tpadilha84@gmail.com
77 License: Apache
8 Download-URL: https://github.com/neovim/python-client/archive/0.4.0.tar.gz
8 Download-URL: https://github.com/neovim/pynvim/archive/0.4.2.tar.gz
99 Description: UNKNOWN
1010 Platform: UNKNOWN
1111 Provides-Extra: pyuv
0 ### Pynvim: Python client to [Neovim](https://github.com/neovim/neovim)
0 Pynvim: Python client to [Neovim](https://github.com/neovim/neovim)
1 ===================================================================
12
23 [![Build Status](https://travis-ci.org/neovim/pynvim.svg?branch=master)](https://travis-ci.org/neovim/pynvim)
34 [![Documentation Status](https://readthedocs.org/projects/pynvim/badge/?version=latest)](http://pynvim.readthedocs.io/en/latest/?badge=latest)
4 [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/neovim/pynvim/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/neovim/pynvim/?branch=master)
5 [![Code Coverage](https://scrutinizer-ci.com/g/neovim/pynvim/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/neovim/pynvim/?branch=master)
5 [![Code coverage](https://codecov.io/gh/neovim/pynvim/branch/master/graph/badge.svg)](https://codecov.io/gh/neovim/pynvim)
66
77 Pynvim implements support for python plugins in Nvim. It also works as a library for
88 connecting to and scripting Nvim processes through its msgpack-rpc API.
99
10 #### Installation
10 Install
11 -------
1112
1213 Supports python 2.7, and 3.4 or later.
1314
3334 pip3 install .
3435 ```
3536
36 #### Python Plugin API
37 Python Plugin API
38 -----------------
3739
3840 Pynvim supports python _remote plugins_ (via the language-agnostic Nvim rplugin
3941 interface), as well as _Vim plugins_ (via the `:python[3]` interface). Thus when
5355
5456 See the [Python Plugin API](http://pynvim.readthedocs.io/en/latest/usage/python-plugin-api.html) documentation for usage of this new functionality.
5557
56 #### Development
58 Development
59 -----------
5760
5861 Use (and activate) a local virtualenv.
5962
7376 [development](http://pynvim.readthedocs.io/en/latest/development.html)
7477 documentation.
7578
76 #### Usage through the python REPL
79 ### Usage from the Python REPL
7780
7881 A number of different transports are supported, but the simplest way to get
7982 started is with the python REPL. First, start Nvim with a known address (or use
116119 continuing startup.
117120
118121 See the tests for more examples.
122
123 Release
124 -------
125
126 1. Create a release commit with title `Pynvim x.y.z`
127 - list significant changes in the commit message
128 - bump the version in `pynvim/util.py` and `setup.py` (3 places in total)
129 2. Make a release on GitHub with the same commit/version tag and copy the message.
130 3. Run `scripts/disable_log_statements.sh`
131 4. Run `python setup.py sdist`
132 - diff the release tarball `dist/pynvim-x.y.z.tar.gz` against the previous one.
133 5. Run `twine upload -r pypi dist/pynvim-x.y.z.tar.gz`
134 - Assumes you have a pypi account with permissions.
135 6. Run `scripts/enable_log_statements.sh` or `git reset --hard` to restore the working dir.
55 import os
66 import sys
77
8 from .api import Nvim, NvimError
9 from .compat import IS_PYTHON3
10 from .msgpack_rpc import (ErrorResponse, child_session, socket_session,
11 stdio_session, tcp_session)
12 from .plugin import (Host, autocmd, command, decode, encoding, function,
13 plugin, rpc_export, shutdown_hook)
14 from .util import VERSION, Version
8 from pynvim.api import Nvim, NvimError
9 from pynvim.compat import IS_PYTHON3
10 from pynvim.msgpack_rpc import (ErrorResponse, child_session, socket_session,
11 stdio_session, tcp_session)
12 from pynvim.plugin import (Host, autocmd, command, decode, encoding, function,
13 plugin, rpc_export, shutdown_hook)
14 from pynvim.util import VERSION, Version
1515
1616
1717 __all__ = ('tcp_session', 'socket_session', 'stdio_session', 'child_session',
33 instances.
44 """
55
6 from .buffer import Buffer
7 from .common import decode_if_bytes, walk
8 from .nvim import Nvim, NvimError
9 from .tabpage import Tabpage
10 from .window import Window
6 from pynvim.api.buffer import Buffer
7 from pynvim.api.common import decode_if_bytes, walk
8 from pynvim.api.nvim import Nvim, NvimError
9 from pynvim.api.tabpage import Tabpage
10 from pynvim.api.window import Window
1111
1212
1313 __all__ = ('Nvim', 'Buffer', 'Window', 'Tabpage', 'NvimError',
00 """API for working with a Nvim Buffer."""
1 from .common import Remote
2 from ..compat import IS_PYTHON3, check_async
1 from pynvim.api.common import Remote
2 from pynvim.compat import IS_PYTHON3, check_async
33
44
55 __all__ = ('Buffer')
22
33 from msgpack import unpackb
44
5 from ..compat import unicode_errors_default
5 from pynvim.compat import unicode_errors_default
66
77 __all__ = ()
88
66
77 from msgpack import ExtType
88
9 from .buffer import Buffer
10 from .common import (NvimError, Remote, RemoteApi, RemoteMap, RemoteSequence,
11 decode_if_bytes, walk)
12 from .tabpage import Tabpage
13 from .window import Window
14 from ..compat import IS_PYTHON3
15 from ..util import Version, format_exc_skip
9 from pynvim.api.buffer import Buffer
10 from pynvim.api.common import (NvimError, Remote, RemoteApi, RemoteMap, RemoteSequence,
11 decode_if_bytes, walk)
12 from pynvim.api.tabpage import Tabpage
13 from pynvim.api.window import Window
14 from pynvim.compat import IS_PYTHON3
15 from pynvim.util import Version, format_exc_skip
1616
1717 __all__ = ('Nvim')
1818
419419 """
420420 try:
421421 self.command(quit_command)
422 except IOError:
422 except OSError:
423423 # sending a quit command will raise an IOError because the
424424 # connection is closed before a response is received. Safe to
425425 # ignore it.
00 """API for working with Nvim tabpages."""
1 from .common import Remote, RemoteSequence
1 from pynvim.api.common import Remote, RemoteSequence
22
33
44 __all__ = ('Tabpage')
00 """API for working with Nvim windows."""
1 from .common import Remote
1 from pynvim.api.common import Remote
22
33
44 __all__ = ('Window')
3333 unicode_errors_default = 'surrogateescape'
3434 else:
3535 find_module = original_find_module
36 unicode_errors_default = 'strict'
36 unicode_errors_default = 'ignore'
3737
3838 NUM_TYPES = (int, long, float)
3939
33 handling some Nvim particularities(server->client requests for example), the
44 code here should work with other msgpack-rpc servers.
55 """
6 from .async_session import AsyncSession
7 from .event_loop import EventLoop
8 from .msgpack_stream import MsgpackStream
9 from .session import ErrorResponse, Session
10 from ..util import get_client_info
6 from pynvim.msgpack_rpc.async_session import AsyncSession
7 from pynvim.msgpack_rpc.event_loop import EventLoop
8 from pynvim.msgpack_rpc.msgpack_stream import MsgpackStream
9 from pynvim.msgpack_rpc.session import ErrorResponse, Session
10 from pynvim.util import get_client_info
1111
1212
1313 __all__ = ('tcp_session', 'socket_session', 'stdio_session', 'child_session',
7979 self._handlers.get(msg[0], self._on_invalid_message)(msg)
8080 except Exception:
8181 err_str = format_exc(5)
82 warn(err_str)
82 pass # replaces next logging statement
83 #warn(err_str)
8384 self._msgpack_stream.send([1, 0, err_str, None])
8485
8586 def _on_request(self, msg):
8788 # - msg[1]: id
8889 # - msg[2]: method name
8990 # - msg[3]: arguments
90 debug('received request: %s, %s', msg[2], msg[3])
91 pass # replaces next logging statement
92 #debug('received request: %s, %s', msg[2], msg[3])
9193 self._request_cb(msg[2], msg[3], Response(self._msgpack_stream,
9294 msg[1]))
9395
9698 # - msg[1]: the id
9799 # - msg[2]: error(if any)
98100 # - msg[3]: result(if not errored)
99 debug('received response: %s, %s', msg[2], msg[3])
101 pass # replaces next logging statement
102 #debug('received response: %s, %s', msg[2], msg[3])
100103 self._pending_requests.pop(msg[1])(msg[2], msg[3])
101104
102105 def _on_notification(self, msg):
103106 # notification/event
104107 # - msg[1]: event name
105108 # - msg[2]: arguments
106 debug('received notification: %s, %s', msg[1], msg[2])
109 pass # replaces next logging statement
110 #debug('received notification: %s, %s', msg[1], msg[2])
107111 self._notification_cb(msg[1], msg[2])
108112
109113 def _on_invalid_message(self, msg):
110114 error = 'Received invalid message %s' % msg
111 warn(error)
115 pass # replaces next logging statement
116 #warn(error)
112117 self._msgpack_stream.send([1, 0, error, None])
113118
114119
134139 resp = [1, self._request_id, value, None]
135140 else:
136141 resp = [1, self._request_id, None, value]
137 debug('sending response to request %d: %s', self._request_id, resp)
142 pass # replaces next logging statement
143 #debug('sending response to request %d: %s', self._request_id, resp)
138144 self._msgpack_stream.send(resp)
22 Tries to use pyuv as a backend, falling back to the asyncio implementation.
33 """
44
5 from ...compat import IS_PYTHON3
5 from pynvim.compat import IS_PYTHON3
66
77 # on python3 we only support asyncio, as we expose it to plugins
88 if IS_PYTHON3:
9 from .asyncio import AsyncioEventLoop
9 from pynvim.msgpack_rpc.event_loop.asyncio import AsyncioEventLoop
1010 EventLoop = AsyncioEventLoop
1111 else:
1212 try:
1313 # libuv is fully implemented in C, use it when available
14 from .uv import UvEventLoop
14 from pynvim.msgpack_rpc.event_loop.uv import UvEventLoop
1515 EventLoop = UvEventLoop
1616 except ImportError:
1717 # asyncio(trollius on python 2) is pure python and should be more
1818 # portable across python implementations
19 from .asyncio import AsyncioEventLoop
19 from pynvim.msgpack_rpc.event_loop.asyncio import AsyncioEventLoop
2020 EventLoop = AsyncioEventLoop
2121
2222
2121 # Fallback to trollius
2222 import trollius as asyncio
2323
24 from .base import BaseEventLoop
24 from pynvim.msgpack_rpc.event_loop.base import BaseEventLoop
2525
2626 logger = logging.getLogger(__name__)
2727 debug, info, warn = (logger.debug, logger.info, logger.warning,)
101101 pipe = sys.stdin
102102 coroutine = self._loop.connect_read_pipe(self._fact, pipe)
103103 self._loop.run_until_complete(coroutine)
104 debug("native stdin connection successful")
104 pass # replaces next logging statement
105 #debug("native stdin connection successful")
105106
106107 # Make sure subprocesses don't clobber stdout,
107108 # send the output to stderr instead.
114115 pipe = os.fdopen(rename_stdout, 'wb')
115116 coroutine = self._loop.connect_write_pipe(self._fact, pipe)
116117 self._loop.run_until_complete(coroutine)
117 debug("native stdout connection successful")
118 pass # replaces next logging statement
119 #debug("native stdout connection successful")
118120
119121 def _connect_child(self, argv):
120122 if os.name != 'nt':
9494
9595 def connect_tcp(self, address, port):
9696 """Connect to tcp/ip `address`:`port`. Delegated to `_connect_tcp`."""
97 info('Connecting to TCP address: %s:%d', address, port)
97 pass # replaces next logging statement
98 #info('Connecting to TCP address: %s:%d', address, port)
9899 self._connect_tcp(address, port)
99100
100101 def connect_socket(self, path):
101102 """Connect to socket at `path`. Delegated to `_connect_socket`."""
102 info('Connecting to %s', path)
103 pass # replaces next logging statement
104 #info('Connecting to %s', path)
103105 self._connect_socket(path)
104106
105107 def connect_stdio(self):
106108 """Connect using stdin/stdout. Delegated to `_connect_stdio`."""
107 info('Preparing stdin/stdout for streaming data')
109 pass # replaces next logging statement
110 #info('Preparing stdin/stdout for streaming data')
108111 self._connect_stdio()
109112
110113 def connect_child(self, argv):
111114 """Connect a new Nvim instance. Delegated to `_connect_child`."""
112 info('Spawning a new nvim instance')
115 pass # replaces next logging statement
116 #info('Spawning a new nvim instance')
113117 self._connect_child(argv)
114118
115119 def send(self, data):
116120 """Queue `data` for sending to Nvim."""
117 debug("Sending '%s'", data)
121 pass # replaces next logging statement
122 #debug("Sending '%s'", data)
118123 self._send(data)
119124
120125 def threadsafe_call(self, fn):
139144 self._on_data = data_cb
140145 if threading.current_thread() == main_thread:
141146 self._setup_signals([signal.SIGINT, signal.SIGTERM])
142 debug('Entering event loop')
147 pass # replaces next logging statement
148 #debug('Entering event loop')
143149 self._run()
144 debug('Exited event loop')
150 pass # replaces next logging statement
151 #debug('Exited event loop')
145152 if threading.current_thread() == main_thread:
146153 self._teardown_signals()
147154 signal.signal(signal.SIGINT, default_int_handler)
150157 def stop(self):
151158 """Stop the event loop."""
152159 self._stop()
153 debug('Stopped event loop')
160 pass # replaces next logging statement
161 #debug('Stopped event loop')
154162
155163 def close(self):
156164 """Stop the event loop."""
157165 self._close()
158 debug('Closed event loop')
166 pass # replaces next logging statement
167 #debug('Closed event loop')
159168
160169 def _on_signal(self, signum):
161170 msg = 'Received {}'.format(self._signames[signum])
162 debug(msg)
171 pass # replaces next logging statement
172 #debug(msg)
163173 if signum == signal.SIGINT and self._transport_type == 'stdio':
164174 # When the transport is stdio, we are probably running as a Nvim
165175 # child process. In that case, we don't want to be killed by
172182 self.stop()
173183
174184 def _on_error(self, error):
175 debug(error)
176 self._error = IOError(error)
185 pass # replaces next logging statement
186 #debug(error)
187 self._error = OSError(error)
177188 self.stop()
178189
179190 def _on_interrupt(self):
33
44 import pyuv
55
6 from .base import BaseEventLoop
6 from pynvim.msgpack_rpc.event_loop.base import BaseEventLoop
77
88
99 class UvEventLoop(BaseEventLoop):
2222 if error:
2323 msg = 'Cannot connect to {}: {}'.format(
2424 self._connect_address, pyuv.errno.strerror(error))
25 self._connection_error = IOError(msg)
25 self._connection_error = OSError(msg)
2626 return
2727 self._read_stream = self._write_stream = stream
2828
4444 self._on_error('EOF')
4545
4646 def _disconnected(self, *args):
47 raise IOError('Not connected to Nvim')
47 raise OSError('Not connected to Nvim')
4848
4949 def _connect_tcp(self, address, port):
5050 stream = pyuv.TCP(self._loop)
22
33 from msgpack import Packer, Unpacker
44
5 from ..compat import unicode_errors_default
5 from pynvim.compat import unicode_errors_default
66
77 logger = logging.getLogger(__name__)
88 debug, info, warn = (logger.debug, logger.info, logger.warning,)
2020 """Wrap `event_loop` on a msgpack-aware interface."""
2121 self.loop = event_loop
2222 self._packer = Packer(unicode_errors=unicode_errors_default)
23 self._unpacker = Unpacker()
23 self._unpacker = Unpacker(unicode_errors=unicode_errors_default)
2424 self._message_cb = None
2525
2626 def threadsafe_call(self, fn):
2929
3030 def send(self, msg):
3131 """Queue `msg` for sending to Nvim."""
32 debug('sent %s', msg)
32 pass # replaces next logging statement
33 #debug('sent %s', msg)
3334 self.loop.send(self._packer.pack(msg))
3435
3536 def run(self, message_cb):
5455 self._unpacker.feed(data)
5556 while True:
5657 try:
57 debug('waiting for message...')
58 pass # replaces next logging statement
59 #debug('waiting for message...')
5860 msg = next(self._unpacker)
59 debug('received message: %s', msg)
61 pass # replaces next logging statement
62 #debug('received message: %s', msg)
6063 self._message_cb(msg)
6164 except StopIteration:
62 debug('unpacker needs more data...')
65 pass # replaces next logging statement
66 #debug('unpacker needs more data...')
6367 break
55
66 import greenlet
77
8 from ..compat import check_async
8 from pynvim.compat import check_async
99
1010 logger = logging.getLogger(__name__)
1111 error, debug, info, warn = (logger.error, logger.debug, logger.info,
3737 try:
3838 fn(*args, **kwargs)
3939 except Exception:
40 warn("error caught while excecuting async callback\n%s\n",
41 format_exc())
40 pass # replaces next logging statement
41 #warn("error caught while excecuting async callback\n%s\n",
42 #format_exc())
4243
4344 def greenlet_wrapper():
4445 gr = greenlet.greenlet(handler)
9495 v = self._blocking_request(method, args)
9596 if not v:
9697 # EOF
97 raise IOError('EOF')
98 raise OSError('EOF')
9899 err, rv = v
99100 if err:
100 info("'Received error: %s", err)
101 pass # replaces next logging statement
102 #info("'Received error: %s", err)
101103 raise self.error_wrapper(err)
102104 return rv
103105
126128 gr.switch()
127129
128130 if self._setup_exception:
129 error('Setup error: {}'.format(self._setup_exception))
131 pass # replaces next logging statement
132 #error('Setup error: {}'.format(self._setup_exception))
130133 raise self._setup_exception
131134
132135 # Process all pending requests and notifications
155158 parent = gr.parent
156159
157160 def response_cb(err, rv):
158 debug('response is available for greenlet %s, switching back', gr)
161 pass # replaces next logging statement
162 #debug('response is available for greenlet %s, switching back', gr)
159163 gr.switch(err, rv)
160164
161165 self._async_session.request(method, args, response_cb)
162 debug('yielding from greenlet %s to wait for response', gr)
166 pass # replaces next logging statement
167 #debug('yielding from greenlet %s to wait for response', gr)
163168 return parent.switch()
164169
165170 def _blocking_request(self, method, args):
192197 def handler():
193198 try:
194199 rv = self._request_cb(name, args)
195 debug('greenlet %s finished executing, '
196 + 'sending %s as response', gr, rv)
200 pass # replaces next logging statement
201 #debug('greenlet %s finished executing, '
202 #+ 'sending %s as response', gr, rv)
197203 response.send(rv)
198204 except ErrorResponse as err:
199 warn("error response from request '%s %s': %s", name,
200 args, format_exc())
205 pass # replaces next logging statement
206 #warn("error response from request '%s %s': %s", name,
207 #args, format_exc())
201208 response.send(err.args[0], error=True)
202209 except Exception as err:
203 warn("error caught while processing request '%s %s': %s", name,
204 args, format_exc())
210 pass # replaces next logging statement
211 #warn("error caught while processing request '%s %s': %s", name,
212 #args, format_exc())
205213 response.send(repr(err) + "\n" + format_exc(5), error=True)
206 debug('greenlet %s is now dying...', gr)
214 pass # replaces next logging statement
215 #debug('greenlet %s is now dying...', gr)
207216
208217 # Create a new greenlet to handle the request
209218 gr = greenlet.greenlet(handler)
210 debug('received rpc request, greenlet %s will handle it', gr)
219 pass # replaces next logging statement
220 #debug('received rpc request, greenlet %s will handle it', gr)
211221 gr.switch()
212222
213223 def _on_notification(self, name, args):
214224 def handler():
215225 try:
216226 self._notification_cb(name, args)
217 debug('greenlet %s finished executing', gr)
227 pass # replaces next logging statement
228 #debug('greenlet %s finished executing', gr)
218229 except Exception:
219 warn("error caught while processing notification '%s %s': %s",
220 name, args, format_exc())
221
222 debug('greenlet %s is now dying...', gr)
230 pass # replaces next logging statement
231 #warn("error caught while processing notification '%s %s': %s",
232 #name, args, format_exc())
233
234 pass # replaces next logging statement
235 #debug('greenlet %s is now dying...', gr)
223236
224237 gr = greenlet.greenlet(handler)
225 debug('received rpc notification, greenlet %s will handle it', gr)
238 pass # replaces next logging statement
239 #debug('received rpc notification, greenlet %s will handle it', gr)
226240 gr.switch()
227241
228242
00 """Nvim plugin/host subpackage."""
11
2 from .decorators import (autocmd, command, decode, encoding, function,
3 plugin, rpc_export, shutdown_hook)
4 from .host import Host
2 from pynvim.plugin.decorators import (autocmd, command, decode, encoding, function,
3 plugin, rpc_export, shutdown_hook)
4 from pynvim.plugin.host import Host
55
66
77 __all__ = ('Host', 'plugin', 'rpc_export', 'command', 'autocmd',
22 import inspect
33 import logging
44
5 from ..compat import IS_PYTHON3, unicode_errors_default
5 from pynvim.compat import IS_PYTHON3, unicode_errors_default
66
77 logger = logging.getLogger(__name__)
88 debug, info, warn = (logger.debug, logger.info, logger.warning,)
77 from functools import partial
88 from traceback import format_exc
99
10 from . import script_host
11 from ..api import decode_if_bytes, walk
12 from ..compat import IS_PYTHON3, find_module
13 from ..msgpack_rpc import ErrorResponse
14 from ..util import format_exc_skip, get_client_info
10 from pynvim.api import decode_if_bytes, walk
11 from pynvim.compat import IS_PYTHON3, find_module
12 from pynvim.msgpack_rpc import ErrorResponse
13 from pynvim.plugin import script_host
14 from pynvim.util import format_exc_skip, get_client_info
1515
1616 __all__ = ('Host')
1717
5858 errmsg = "{}: Async request caused an error:\n{}\n".format(
5959 self.name, decode_if_bytes(msg))
6060 self.nvim.err_write(errmsg, async_=True)
61 return errmsg
6162
6263 def start(self, plugins):
6364 """Start listening for msgpack-rpc requests and notifications."""
115116 handler = self._request_handlers.get(name, None)
116117 if not handler:
117118 msg = self._missing_handler_error(name, 'request')
118 error(msg)
119 pass # replaces next logging statement
120 #error(msg)
119121 raise ErrorResponse(msg)
120122
121 debug('calling request handler for "%s", args: "%s"', name, args)
123 pass # replaces next logging statement
124 #debug('calling request handler for "%s", args: "%s"', name, args)
122125 rv = handler(*args)
123 debug("request handler for '%s %s' returns: %s", name, args, rv)
126 pass # replaces next logging statement
127 #debug("request handler for '%s %s' returns: %s", name, args, rv)
124128 return rv
125129
126130 def _on_notification(self, name, args):
130134 handler = self._notification_handlers.get(name, None)
131135 if not handler:
132136 msg = self._missing_handler_error(name, 'notification')
133 error(msg)
137 pass # replaces next logging statement
138 #error(msg)
134139 self._on_async_err(msg + "\n")
135140 return
136141
137 debug('calling notification handler for "%s", args: "%s"', name, args)
142 pass # replaces next logging statement
143 #debug('calling notification handler for "%s", args: "%s"', name, args)
138144 handler(*args)
139145
140146 def _missing_handler_error(self, name, kind):
151157 for path in plugins:
152158 err = None
153159 if path in self._loaded:
154 error('{} is already loaded'.format(path))
160 pass # replaces next logging statement
161 #error('{} is already loaded'.format(path))
155162 continue
156163 try:
157164 if path == "script_host.py":
165172 self._discover_classes(module, handlers, path)
166173 self._discover_functions(module, handlers, path, False)
167174 if not handlers:
168 error('{} exports no handlers'.format(path))
175 pass # replaces next logging statement
176 #error('{} exports no handlers'.format(path))
169177 continue
170178 self._loaded[path] = {'handlers': handlers, 'module': module}
171179 except Exception as e:
172180 err = ('Encountered {} loading plugin at {}: {}\n{}'
173181 .format(type(e).__name__, path, e, format_exc(5)))
174 error(err)
182 pass # replaces next logging statement
183 #error(err)
175184 self._load_errors[path] = err
176185
177186 kind = ("script-host" if len(plugins) == 1 and has_script
178187 else "rplugin-host")
179 self.nvim.api.set_client_info(
180 *get_client_info(kind, 'host', host_method_spec),
181 async_=True)
188 info = get_client_info(kind, 'host', host_method_spec)
189 self.name = info[0]
190 self.nvim.api.set_client_info(*info, async_=True)
182191
183192 def _unload(self):
184193 for path, plugin in self._loaded.items():
33 import logging
44 import os
55 import sys
6
7 from .decorators import plugin, rpc_export
8 from ..api import Nvim, walk
9 from ..compat import IS_PYTHON3
10 from ..msgpack_rpc import ErrorResponse
11 from ..util import format_exc_skip
6 from types import ModuleType
7
8 from pynvim.api import Nvim, walk
9 from pynvim.compat import IS_PYTHON3
10 from pynvim.msgpack_rpc import ErrorResponse
11 from pynvim.plugin.decorators import plugin, rpc_export
12 from pynvim.util import format_exc_skip
1213
1314 __all__ = ('ScriptHost',)
1415
3637 """Initialize the legacy python-vim environment."""
3738 self.setup(nvim)
3839 # context where all code will run
39 self.module = imp.new_module('__main__')
40 self.module = ModuleType('__main__')
4041 nvim.script_context = self.module
4142 # it seems some plugins assume 'sys' is already imported, so do it now
4243 exec('import sys', self.module.__dict__)
4344 self.legacy_vim = LegacyVim.from_nvim(nvim)
4445 sys.modules['vim'] = self.legacy_vim
45
46 # mimic Vim by importing vim module by default.
47 exec('import vim', self.module.__dict__)
4648 # Handle DirChanged. #296
4749 nvim.command(
4850 'au DirChanged * call rpcnotify({}, "python_chdir", v:event.cwd)'
6365 forwarded to Nvim.
6466 """
6567 self.nvim = nvim
66 info('install import hook/path')
68 pass # replaces next logging statement
69 #info('install import hook/path')
6770 self.hook = path_hook(nvim)
6871 sys.path_hooks.append(self.hook)
6972 nvim.VIM_SPECIAL_PATH = '_vim_path_'
7073 sys.path.append(nvim.VIM_SPECIAL_PATH)
71 info('redirect sys.stdout and sys.stderr')
74 pass # replaces next logging statement
75 #info('redirect sys.stdout and sys.stderr')
7276 self.saved_stdout = sys.stdout
7377 self.saved_stderr = sys.stderr
7478 sys.stdout = RedirectStream(lambda data: nvim.out_write(data))
7781 def teardown(self):
7882 """Restore state modified from the `setup` call."""
7983 nvim = self.nvim
80 info('uninstall import hook/path')
84 pass # replaces next logging statement
85 #info('uninstall import hook/path')
8186 sys.path.remove(nvim.VIM_SPECIAL_PATH)
8287 sys.path_hooks.remove(self.hook)
83 info('restore sys.stdout and sys.stderr')
88 pass # replaces next logging statement
89 #info('restore sys.stdout and sys.stderr')
8490 sys.stdout = self.saved_stdout
8591 sys.stderr = self.saved_stderr
8692
3838 return (name, VERSION.__dict__, type_, method_spec, attributes)
3939
4040
41 VERSION = Version(major=0, minor=4, patch=0, prerelease='')
41 VERSION = Version(major=0, minor=4, patch=2, prerelease='')
00 Metadata-Version: 2.1
11 Name: pynvim
2 Version: 0.4.0
2 Version: 0.4.2
33 Summary: Python client to neovim
4 Home-page: http://github.com/neovim/python-client
4 Home-page: http://github.com/neovim/pynvim
55 Author: Thiago de Arruda
66 Author-email: tpadilha84@gmail.com
77 License: Apache
8 Download-URL: https://github.com/neovim/python-client/archive/0.4.0.tar.gz
8 Download-URL: https://github.com/neovim/pynvim/archive/0.4.2.tar.gz
99 Description: UNKNOWN
1010 Platform: UNKNOWN
1111 Provides-Extra: pyuv
0 greenlet
01 msgpack>=0.5.0
1 greenlet
22
33 [pyuv]
44 pyuv>=1.0.0
77 'msgpack>=0.5.0',
88 ]
99
10 needs_pytest = {'pytest', 'test', 'ptr'}.intersection(sys.argv)
11 pytest_runner = ['pytest-runner'] if needs_pytest else []
12
1013 setup_requires = [
11 'pytest-runner'
12 ]
14 ] + pytest_runner,
1315
1416 tests_require = [
1517 'pytest>=3.4.0',
3234 install_requires.append('greenlet')
3335
3436 setup(name='pynvim',
35 version='0.4.0',
37 version='0.4.2',
3638 description='Python client to neovim',
37 url='http://github.com/neovim/python-client',
38 download_url='https://github.com/neovim/python-client/archive/0.4.0.tar.gz',
39 url='http://github.com/neovim/pynvim',
40 download_url='https://github.com/neovim/pynvim/archive/0.4.2.tar.gz',
3941 author='Thiago de Arruda',
4042 author_email='tpadilha84@gmail.com',
4143 license='Apache',
1717 if child_argv is not None:
1818 editor = pynvim.attach('child', argv=json.loads(child_argv))
1919 else:
20 assert listen_address is None or listen_address != ''
2021 editor = pynvim.attach('socket', path=listen_address)
2122
2223 return editor
163163 def test_invalid_utf8(vim):
164164 vim.command('normal "=printf("%c", 0xFF)\np')
165165 assert vim.eval("char2nr(getline(1))") == 0xFF
166
167166 assert vim.current.buffer[:] == ['\udcff'] if IS_PYTHON3 else ['\xff']
167
168168 vim.current.line += 'x'
169 assert vim.eval("getline(1)", decode=False) == b'\xFFx'
169 assert vim.eval("getline(1)", decode=False) == '\udcffx' if IS_PYTHON3 else '\xffx'
170170 assert vim.current.buffer[:] == ['\udcffx'] if IS_PYTHON3 else ['\xffx']
171171
172172
2727 assert vim.eval('g:data') == 'xyz'
2828
2929
30 def test_async_error(vim):
31 # Invoke a bogus Ex command via notify (async).
32 vim.command("lolwut", async_=True)
33 event = vim.next_message()
34 assert event[1] == 'nvim_error_event'
35
36
3037 def test_broadcast(vim):
3138 vim.subscribe('event2')
3239 vim.command('call rpcnotify(0, "event1", 1, 2, 3)')
00 # -*- coding: utf-8 -*-
1 from pynvim.plugin.host import Host, host_method_spec
2 from pynvim.plugin.script_host import ScriptHost
13
2 from pynvim.plugin.host import Host, host_method_spec
4
5 def test_host_imports(vim):
6 h = ScriptHost(vim)
7 assert h.module.__dict__['vim']
8 assert h.module.__dict__['vim'] == h.legacy_vim
9 assert h.module.__dict__['sys']
310
411
512 def test_host_clientinfo(vim):
815 assert 'remote' == vim.api.get_chan_info(vim.channel_id)['client']['type']
916 h._load([])
1017 assert 'host' == vim.api.get_chan_info(vim.channel_id)['client']['type']
18
19
20 # Smoke test for Host._on_error_event(). #425
21 def test_host_async_error(vim):
22 h = Host(vim)
23 h._load([])
24 # Invoke a bogus Ex command via notify (async).
25 vim.command("lolwut", async_=True)
26 event = vim.next_message()
27 assert event[1] == 'nvim_error_event'
28 assert 'rplugin-host: Async request caused an error:\nboom\n' \
29 in h._on_error_event(None, 'boom')
225225 return a.nvim_buf_line_count(buf)
226226 end
227227
228 pynvimtest = {setbuf=setbuf,getbuf=getbuf}
228 pynvimtest = {setbuf=setbuf, getbuf=getbuf}
229229
230230 return "eggspam"
231231 """
234234 def test_lua(vim):
235235 assert vim.exec_lua(lua_code, 7) == "eggspam"
236236 assert vim.lua.pynvimtest_func(3) == 10
237 testmod = vim.lua.pynvimtest
237 lua_module = vim.lua.pynvimtest
238238 buf = vim.current.buffer
239 testmod.setbuf(buf, ["a", "b", "c", "d"], async_=True)
240 assert testmod.getbuf(buf) == 4
239 lua_module.setbuf(buf, ["a", "b", "c", "d"], async_=True)
240 assert lua_module.getbuf(buf) == 4