Issue #23465: Implement PEP 486 - Make the Python Launcher aware of virtual environments (patch by Paul Moore)
This commit is contained in:
parent
b48af340b9
commit
76998fef2c
|
@ -404,6 +404,16 @@ If you see the following error, you do not have the launcher installed:
|
|||
Per-user installations of Python do not add the launcher to :envvar:`PATH`
|
||||
unless the option was selected on installation.
|
||||
|
||||
Virtual environments
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If the launcher is run with no explicit Python version specification, and a
|
||||
virtual environment (created with the standard library :mod:`venv` module or
|
||||
the external ``virtualenv`` tool) active, the launcher will run the virtual
|
||||
environment's interpreter rather than the global one. To run the global
|
||||
interpreter, either deactivate the virtual environment, or explicitly specify
|
||||
the global Python version.
|
||||
|
||||
From a script
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
|
@ -478,6 +488,16 @@ be used by the launcher without modification. If you are writing a new script
|
|||
on Windows which you hope will be useful on Unix, you should use one of the
|
||||
shebang lines starting with ``/usr``.
|
||||
|
||||
Any of the above virtual commands can be suffixed with an explicit version
|
||||
(either just the major version, or the major and minor version) - for example
|
||||
``/usr/bin/python2.7`` - which will cause that specific version to be located
|
||||
and used.
|
||||
|
||||
The ``/usr/bin/env`` form of shebang line has one further special property.
|
||||
Before looking for installed Python interpreters, this form will search the
|
||||
executable :envvar:`PATH` for a Python executable. This corresponds to the
|
||||
behaviour of the Unix ``env`` program, which performs a :envvar:`PATH` search.
|
||||
|
||||
Arguments in shebang lines
|
||||
--------------------------
|
||||
|
||||
|
|
|
@ -123,6 +123,18 @@ manually, and should make it more robust against asynchronous signal reception.
|
|||
:pep:`475` -- Retry system calls failing with EINTR
|
||||
|
||||
|
||||
PEP 486: Make the Python Launcher aware of virtual environments
|
||||
---------------------------------------------------------------
|
||||
|
||||
:pep:`486` makes the Windows launcher (see :pep:`397`) aware of an active
|
||||
virtual environment. When the default interpreter would be used and the
|
||||
``VIRTUAL_ENV`` environment variable is set, the interpreter in the virtual
|
||||
environment will be used.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:pep:`486` -- Make the Python Launcher aware of virtual environments
|
||||
|
||||
Other Language Changes
|
||||
======================
|
||||
|
||||
|
|
|
@ -77,6 +77,9 @@ Build
|
|||
Windows
|
||||
-------
|
||||
|
||||
- Issue #23465: Implement PEP 486 - Make the Python Launcher aware of virtual
|
||||
environments. Patch by Paul Moore.
|
||||
|
||||
- Issue #23437: Make user scripts directory versioned on Windows. Patch by Paul
|
||||
Moore.
|
||||
|
||||
|
|
|
@ -384,6 +384,31 @@ find_python_by_version(wchar_t const * wanted_ver)
|
|||
}
|
||||
|
||||
|
||||
static wchar_t *
|
||||
find_python_by_venv()
|
||||
{
|
||||
static wchar_t venv_python[MAX_PATH];
|
||||
wchar_t *virtual_env = get_env(L"VIRTUAL_ENV");
|
||||
DWORD attrs;
|
||||
|
||||
/* Check for VIRTUAL_ENV environment variable */
|
||||
if (virtual_env == NULL || virtual_env[0] == L'\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check for a python executable in the venv */
|
||||
debug(L"Checking for Python executable in virtual env '%ls'\n", virtual_env);
|
||||
_snwprintf_s(venv_python, MAX_PATH, _TRUNCATE,
|
||||
L"%ls\\Scripts\\%ls", virtual_env, PYTHON_EXECUTABLE);
|
||||
attrs = GetFileAttributesW(venv_python);
|
||||
if (attrs == INVALID_FILE_ATTRIBUTES) {
|
||||
debug(L"Python executable %ls missing from virtual env\n", venv_python);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return venv_python;
|
||||
}
|
||||
|
||||
static wchar_t appdata_ini_path[MAX_PATH];
|
||||
static wchar_t launcher_ini_path[MAX_PATH];
|
||||
|
||||
|
@ -1309,6 +1334,7 @@ process(int argc, wchar_t ** argv)
|
|||
{
|
||||
wchar_t * wp;
|
||||
wchar_t * command;
|
||||
wchar_t * executable;
|
||||
wchar_t * p;
|
||||
int rc = 0;
|
||||
size_t plen;
|
||||
|
@ -1453,6 +1479,7 @@ process(int argc, wchar_t ** argv)
|
|||
if (ip == NULL)
|
||||
error(RC_NO_PYTHON, L"Requested Python version (%ls) not \
|
||||
installed", &p[1]);
|
||||
executable = ip->executable;
|
||||
command += wcslen(p);
|
||||
command = skip_whitespace(command);
|
||||
}
|
||||
|
@ -1470,9 +1497,16 @@ installed", &p[1]);
|
|||
#endif
|
||||
|
||||
if (!valid) {
|
||||
ip = locate_python(L"");
|
||||
if (ip == NULL)
|
||||
error(RC_NO_PYTHON, L"Can't find a default Python.");
|
||||
/* Look for an active virtualenv */
|
||||
executable = find_python_by_venv();
|
||||
|
||||
/* If we didn't find one, look for the default Python */
|
||||
if (executable == NULL) {
|
||||
ip = locate_python(L"");
|
||||
if (ip == NULL)
|
||||
error(RC_NO_PYTHON, L"Can't find a default Python.");
|
||||
executable = ip->executable;
|
||||
}
|
||||
if ((argc == 2) && (!_wcsicmp(p, L"-h") || !_wcsicmp(p, L"--help"))) {
|
||||
#if defined(_M_X64)
|
||||
BOOL canDo64bit = TRUE;
|
||||
|
@ -1500,7 +1534,7 @@ Launcher arguments:\n\n\
|
|||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
invoke_child(ip->executable, NULL, command);
|
||||
invoke_child(executable, NULL, command);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue