Merge pull request #128 from gaborbernat/master

Allow querying non-host python intepreters
This commit is contained in:
Vineet Naik 2020-09-22 15:38:18 +05:30 committed by GitHub
commit e01462c25d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 112 additions and 26 deletions

View File

@ -25,16 +25,27 @@ jobs:
- pypy3 - pypy3
- pypy2 - pypy2
steps: steps:
- name: Setup graphviz
uses: ts-graphviz/setup-graphviz@v1
- name: Setup python for tox
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install tox
run: python -m pip install tox
- name: Setup python for test ${{ matrix.py }} - name: Setup python for test ${{ matrix.py }}
uses: actions/setup-python@v2 uses: actions/setup-python@v2
with: with:
python-version: ${{ matrix.py }} python-version: ${{ matrix.py }}
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Setup graphviz - name: Pick tox environment to run
uses: ts-graphviz/setup-graphviz@v1 run: |
- name: Install dev requirements import platform
run: pip install -r dev-requirements.txt import sys
- name: Install project major, minor, impl = sys.version_info[0], sys.version_info[1], platform.python_implementation()
run: pip install .[graphviz] print('::set-env name=TOXENV::' + ("py" if impl == "CPython" else "pypy") + ("{}{}".format(major, minor) if impl == "CPython" else ("3" if major == 3 else "")))
shell: python
- name: Setup test suite
run: tox -vv --notest
- name: Run test suite - name: Run test suite
run: pytest -v tests run: tox --skip-pkg-install

View File

@ -1,6 +0,0 @@
pytest
pytest-cov
jinja2
ipython
flake8
mock;python_version<"3"

View File

@ -1,12 +1,15 @@
from __future__ import print_function from __future__ import print_function
import os import os
import inspect
import sys import sys
import subprocess
from itertools import chain from itertools import chain
from collections import defaultdict, deque from collections import defaultdict, deque
import argparse import argparse
from operator import attrgetter from operator import attrgetter
import json import json
from importlib import import_module from importlib import import_module
import tempfile
try: try:
from collections import OrderedDict from collections import OrderedDict
@ -711,6 +714,9 @@ def get_parser():
version='{0}'.format(__version__)) version='{0}'.format(__version__))
parser.add_argument('-f', '--freeze', action='store_true', parser.add_argument('-f', '--freeze', action='store_true',
help='Print names so as to write freeze files') help='Print names so as to write freeze files')
parser.add_argument('--python', default=sys.executable,
help='Python to use to look for packages in it (default: where'
' installed)')
parser.add_argument('-a', '--all', action='store_true', parser.add_argument('-a', '--all', action='store_true',
help='list all deps at top level') help='list all deps at top level')
parser.add_argument('-l', '--local-only', parser.add_argument('-l', '--local-only',
@ -775,9 +781,43 @@ def _get_args():
return parser.parse_args() return parser.parse_args()
def handle_non_host_target(args):
of_python = os.path.abspath(args.python)
# if target is not current python re-invoke it under the actual host
if of_python != os.path.abspath(sys.executable):
# there's no way to guarantee that graphviz is available, so refuse
if args.output_format:
print("graphviz functionality is not supported when querying"
" non-host python", file=sys.stderr)
raise SystemExit(1)
argv = sys.argv[1:] # remove current python executable
for py_at, value in enumerate(argv):
if value == "--python":
del argv[py_at]
del argv[py_at]
elif value.startswith("--python"):
del argv[py_at]
# feed the file as argument, instead of file
# to avoid adding the file path to sys.path, that can affect result
file_path = inspect.getsourcefile(sys.modules[__name__])
with open(file_path, 'rt') as file_handler:
content = file_handler.read()
cmd = [of_python, "-c", content]
cmd.extend(argv)
# invoke from an empty folder to avoid cwd altering sys.path
cwd = tempfile.mkdtemp()
try:
return subprocess.call(cmd, cwd=cwd)
finally:
os.removedirs(cwd)
return None
def main(): def main():
args = _get_args() args = _get_args()
result = handle_non_host_target(args)
if result is not None:
return result
pkgs = get_installed_distributions(local_only=args.local_only, pkgs = get_installed_distributions(local_only=args.local_only,
user_only=args.user_only) user_only=args.user_only)

View File

@ -1,4 +1,5 @@
from contextlib import contextmanager from contextlib import contextmanager
import platform
import sys import sys
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
try: try:
@ -7,6 +8,7 @@ except ImportError:
import mock import mock
import pytest import pytest
import virtualenv
import pipdeptree as p import pipdeptree as p
@ -520,3 +522,33 @@ def test_parser_svg():
args = parser.parse_args(['--graph-output', 'svg']) args = parser.parse_args(['--graph-output', 'svg'])
assert args.output_format == 'svg' assert args.output_format == 'svg'
assert not args.json assert not args.json
@pytest.mark.parametrize("args_joined", [True, False])
def test_custom_interpreter(tmp_path, monkeypatch, capfd, args_joined):
result = virtualenv.cli_run([str(tmp_path), "--activators", ""])
cmd = [sys.executable]
cmd += ["--python={}".format(result.creator.exe)] if args_joined else ["--python", str(result.creator.exe)]
monkeypatch.setattr(sys, "argv", cmd)
p.main()
out, _ = capfd.readouterr()
found = {i.split("==")[0] for i in out.splitlines()}
implementation = platform.python_implementation()
if implementation == "CPython":
expected = {"pip", "setuptools", "wheel"}
elif implementation == "PyPy":
expected = {"cffi", "greenlet", "pip", "readline", "setuptools", "wheel"}
else:
raise ValueError(implementation)
assert found == expected, out
monkeypatch.setattr(sys, "argv", cmd + ["--graph-output", "something"])
with pytest.raises(SystemExit) as context:
p.main()
out, err = capfd.readouterr()
assert context.value.code == 1
assert not out
assert err == "graphviz functionality is not supported when querying" " non-host python\n"

23
tox.ini
View File

@ -1,17 +1,26 @@
# Tox (http://tox.testrun.org/) is a tool for running tests # http://tox.readthedocs.org/ - sets up and runs the test suite based on a declarative configuration
# in multiple virtualenvs. This configuration file will run the
# test suite on all supported python versions. To use it, "pip install tox"
# and then run "tox" from this directory.
[tox] [tox]
envlist = py27, py34, py35, py36, py37, py38 envlist =
py39
py38
py37
py36
py35
py34
py27
pypy3
pypy2
[testenv] [testenv]
description = run test suite under {basepython}
commands = commands =
pytest {posargs:-vv} pytest {posargs:-vv}
deps = deps =
tox>=3.0.0
graphviz graphviz
pip>=8.0.2 pip>=8.0.2
pytest pytest
pytest-cov pytest-cov
virtualenv>=20,<21
mock;python_version<"3"
extras =
graphviz