summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBernát Gábor <bgabor8@bloomberg.net>2021-02-09 09:30:36 +0000
committerGitHub <noreply@github.com>2021-02-09 09:30:36 +0000
commit36cdadba810c20c0b7af89029d7c1f0fa25cc12d (patch)
treefb1c1f64e0b135b0afccd6e4980f44a801e05273 /src
parent726271deba8242e76ee4dcacc6cc12190696bf25 (diff)
downloadtox-git-36cdadba810c20c0b7af89029d7c1f0fa25cc12d.tar.gz
Support running python 2 targets (#1900)
Diffstat (limited to 'src')
-rw-r--r--src/tox/execute/pep517_backend.py2
-rw-r--r--src/tox/tox_env/python/virtual_env/api.py3
-rw-r--r--src/tox/util/pep517/backend.py45
-rw-r--r--src/tox/util/pep517/backend.pyi1
4 files changed, 38 insertions, 13 deletions
diff --git a/src/tox/execute/pep517_backend.py b/src/tox/execute/pep517_backend.py
index a9ccbc08..d865bfaf 100644
--- a/src/tox/execute/pep517_backend.py
+++ b/src/tox/execute/pep517_backend.py
@@ -1,4 +1,5 @@
"""A executor that reuses a single subprocess for all backend calls (saving on python startup/import overhead)"""
+import time
from pathlib import Path
from subprocess import TimeoutExpired
from threading import Lock
@@ -62,6 +63,7 @@ class LocalSubProcessPep517Executor(Execute):
)
self._exc = ToxBackendFailed(failure)
raise self._exc
+ time.sleep(0.01) # wait a short while for the output to populate
return self._local_execute
@staticmethod
diff --git a/src/tox/tox_env/python/virtual_env/api.py b/src/tox/tox_env/python/virtual_env/api.py
index f3f8e98e..bdf55a55 100644
--- a/src/tox/tox_env/python/virtual_env/api.py
+++ b/src/tox/tox_env/python/virtual_env/api.py
@@ -98,7 +98,8 @@ class VirtualEnv(Python, ABC):
return cmd
def default_install_command(self, conf: Config, env_name: Optional[str]) -> Command: # noqa
- cmd = Command(["python", "-I", "-m", "pip", "install", "{opts}", "{packages}"])
+ isolated_flag = "-E" if self.base_python.version_info.major == 2 else "-I"
+ cmd = Command(["python", isolated_flag, "-m", "pip", "install", "{opts}", "{packages}"])
return self.post_process_install_command(cmd)
def setup(self) -> None:
diff --git a/src/tox/util/pep517/backend.py b/src/tox/util/pep517/backend.py
index b17d9c17..a4f2db70 100644
--- a/src/tox/util/pep517/backend.py
+++ b/src/tox/util/pep517/backend.py
@@ -1,5 +1,8 @@
"""Handles communication on the backend side between frontend and backend"""
+from __future__ import print_function, unicode_literals
+
import json
+import os
import sys
import traceback
@@ -20,11 +23,11 @@ class BackendProxy:
def __call__(self, name, *args, **kwargs):
on_object = self if name.startswith("_") else self.backend
if not hasattr(on_object, name):
- raise MissingCommand(f"{on_object!r} has no attribute {name!r}")
+ raise MissingCommand("{!r} has no attribute {!r}".format(on_object, name))
return getattr(on_object, name)(*args, **kwargs)
def __str__(self):
- return f"{self.__class__.__name__}(backend={self.backend})"
+ return "{}(backend={})".format(self.__class__.__name__, self.backend)
def _exit(self): # noqa
return 0
@@ -37,27 +40,29 @@ def flush():
def run(argv):
reuse_process = argv[0].lower() == "true"
+
try:
backend_proxy = BackendProxy(argv[1], None if len(argv) == 2 else argv[2])
except BaseException:
print("failed to start backend", file=sys.stderr)
- flush()
raise
- print(f"started backend {backend_proxy}", file=sys.stdout)
+ else:
+ print("started backend {}".format(backend_proxy), file=sys.stdout)
+ finally:
+ flush() # pragma: no branch
while True:
- try:
- message = input().strip()
- except EOFError: # pragma: no cover # when the stdout is closed without exit
- break # pragma: no cover
- if not message:
+ content = read_line()
+ if not content:
continue
flush() # flush any output generated before
try:
- parsed_message = json.loads(message)
+ if sys.version_info[0] == 2: # pragma: no branch # python 2 does not support loading from bytearray
+ content = content.decode() # pragma: no cover
+ parsed_message = json.loads(content)
result_file = parsed_message["result"]
except Exception: # noqa
# ignore messages that are not valid JSON and contain a valid result path
- print(f"Backend: incorrect request to backend: {message}", file=sys.stderr)
+ print("Backend: incorrect request to backend: {}".format(content), file=sys.stderr)
flush()
else:
result = {}
@@ -83,12 +88,28 @@ def run(argv):
except Exception: # noqa
traceback.print_exc()
finally:
- print(f"Backend: Wrote response {result} to {result_file}") # used as done marker by frontend
+ # used as done marker by frontend
+ print("Backend: Wrote response {} to {}".format(result, result_file))
flush() # pragma: no branch
if reuse_process is False: # pragma: no branch # no test for reuse process in root test env
break
return 0
+def read_line():
+ # for some reason input() seems to break (hangs forever) so instead we read byte by byte the unbuffered stream
+ content = bytearray()
+ while True:
+ try:
+ char = os.read(0, 1)
+ except EOFError: # pragma: no cover # when the stdout is closed without exit
+ break # pragma: no cover
+ if char == b"\n": # pragma: no cover
+ break
+ if char != b"\r": # pragma: win32 cover
+ content += char
+ return content
+
+
if __name__ == "__main__":
sys.exit(run(sys.argv[1:]))
diff --git a/src/tox/util/pep517/backend.pyi b/src/tox/util/pep517/backend.pyi
index df773d4d..315d9afe 100644
--- a/src/tox/util/pep517/backend.pyi
+++ b/src/tox/util/pep517/backend.pyi
@@ -13,4 +13,5 @@ class BackendProxy:
def _exit(self) -> None: ...
def run(argv: Sequence[str]) -> int: ...
+def read_line() -> bytearray: ...
def flush() -> None: ...