diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c480cd2d..956a5d6e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,4 +1,10 @@ -1.7.0 (08-08-2019) +1.7.1 (2019-08-28) +------------------ + +* `#108 `__: Revert ``linecache`` optimization introduced in ``1.7.0`` which + broke remote execution. + +1.7.0 (2019-08-08) ------------------ * `#102 `__: Show paths in stack traces diff --git a/execnet/gateway.py b/execnet/gateway.py index 5a636213..8e2c1de0 100644 --- a/execnet/gateway.py +++ b/execnet/gateway.py @@ -4,6 +4,7 @@ (c) 2004-2013, Holger Krekel and others """ import inspect +import linecache import os import sys import textwrap @@ -111,10 +112,8 @@ def remote_exec(self, source, **kwargs): file_name = None if isinstance(source, types.ModuleType): file_name = inspect.getsourcefile(source) - if not file_name: - source = inspect.getsource(source) - else: - source = None + linecache.updatecache(file_name) + source = inspect.getsource(source) elif isinstance(source, types.FunctionType): call_name = source.__name__ file_name = inspect.getsourcefile(source) diff --git a/execnet/gateway_base.py b/execnet/gateway_base.py index 5e101411..21f408f7 100644 --- a/execnet/gateway_base.py +++ b/execnet/gateway_base.py @@ -14,7 +14,6 @@ """ from __future__ import with_statement -import linecache import os import struct import sys @@ -1077,9 +1076,6 @@ def executetask(self, item): name = name.encode("ascii") newkwargs[name] = value kwargs = newkwargs - if source is None: - assert file_name, file_name - source = "".join(linecache.updatecache(file_name)) loc = {"channel": channel, "__name__": "__channelexec__"} self._trace("execution starts[%s]: %s" % (channel.id, repr(source)[:50])) channel._executing = True diff --git a/testing/test_gateway.py b/testing/test_gateway.py index 13ec8cef..fc1cf6ae 100644 --- a/testing/test_gateway.py +++ b/testing/test_gateway.py @@ -122,6 +122,37 @@ def test_remote_exec_module(self, tmpdir, gw): name = channel.receive() assert name == 2 + def test_remote_exec_module_is_removed(self, gw, tmpdir, monkeypatch): + remotetest = tmpdir.join("remote.py") + remotetest.write( + dedent( + """ + def remote(): + return True + + if __name__ == '__channelexec__': + for item in channel: # noqa + channel.send(eval(item)) # noqa + + """ + ) + ) + + monkeypatch.syspath_prepend(tmpdir) + import remote + + ch = gw.remote_exec(remote) + # simulate sending the code to a remote location that does not have + # access to the source + tmpdir.remove() + ch.send("remote()") + try: + result = ch.receive() + finally: + ch.close() + + assert result is True + def test_remote_exec_module_with_traceback(self, gw, tmpdir, monkeypatch): remotetest = tmpdir.join("remotetest.py") remotetest.write(