diff --git a/CHANGELOG.md b/CHANGELOG.md index ee808dd2b..b06fd4442 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [UNRELEASED] -No user facing changes. +- Python automatic dependency installation will no longer fail for projects using Poetry that specify `virtualenvs.options.no-pip = true` in their `poetry.toml`. [#1431](https://github.com/github/codeql-action/pull/1431). ## 2.1.38 - 12 Jan 2023 diff --git a/python-setup/find_site_packages.py b/python-setup/find_site_packages.py new file mode 100644 index 000000000..a473ce66a --- /dev/null +++ b/python-setup/find_site_packages.py @@ -0,0 +1,28 @@ +""" +Print the path to the site-packages directory for the current Python environment. +""" + +try: + import pip + import os + print(os.path.dirname(os.path.dirname(pip.__file__))) +except ImportError: + import sys + print("could not import pip", file=sys.stderr) + # if you use poetry with `virtualenvs.options.no-pip = true` you might end up with a + # virtualenv without pip, so the above trick doesn't actually work. See + # https://python-poetry.org/docs/configuration/#virtualenvsoptionsno-pip + # + # A possible option is to install `pip` into the virtualenv created by poetry + # (`poetry add pip`), but it turns out that doesn't always work :( for the test + # poetry/requests-3, I was not allowed to install pip! So I did not pursue this + # option further. + # + # Instead, local testing shows that first entry of `site.getsitepackages()` has the + # right path, whereas `site.getusersitepackages()` is about the system python (very + # confusing). + # + # We can't use the environment variable POETRY_VIRTUALENVS_OPTIONS_NO_PIP because it + # does not work, see https://github.com/python-poetry/poetry/issues/5906 + import site + print(site.getsitepackages()[0]) diff --git a/python-setup/tests/from_python_exe.py b/python-setup/tests/from_python_exe.py index 19702cf37..d5bf1624f 100755 --- a/python-setup/tests/from_python_exe.py +++ b/python-setup/tests/from_python_exe.py @@ -9,8 +9,7 @@ def get_details(path_to_python_exe: str) -> Tuple[str, str]: import_path = subprocess.check_output( [ path_to_python_exe, - "-c", - "import os; import pip; print(os.path.dirname(os.path.dirname(pip.__file__)))", + os.path.join(os.path.dirname(__file__), "find_site_packages.py") ], stdin=subprocess.DEVNULL, ) diff --git a/python-setup/tests/poetry/requests-3/poetry.toml b/python-setup/tests/poetry/requests-3/poetry.toml index ab1033bd3..afbc8b90c 100644 --- a/python-setup/tests/poetry/requests-3/poetry.toml +++ b/python-setup/tests/poetry/requests-3/poetry.toml @@ -1,2 +1,5 @@ [virtualenvs] in-project = true + +[virtualenvs.options] +no-pip = true diff --git a/src/analyze.ts b/src/analyze.ts index 00a72f21a..629ea2e4d 100644 --- a/src/analyze.ts +++ b/src/analyze.ts @@ -88,6 +88,8 @@ async function setupPythonExtractor(logger: Logger) { return; } + const scriptsFolder = path.resolve(__dirname, "../python-setup"); + let output = ""; const options = { listeners: { @@ -100,8 +102,7 @@ async function setupPythonExtractor(logger: Logger) { await new toolrunner.ToolRunner( codeqlPython, [ - "-c", - "import os; import pip; print(os.path.dirname(os.path.dirname(pip.__file__)))", + path.join(scriptsFolder, "find_site_packages.py"), ], options ).exec();