bpo-30362 : Add list options to launcher. (#1578)

* bpo-30362 Add list options to launcher.

* bpo-30362 Add list options to help message.

* To avoid possible later conflict with python replaced flags with --launcher-list and --launcher-list-paths

* bpo-30362 Changed flag to -0 as suggested on review.

* bpo-30362: Modified to default to not path for -0, -0p to dispaly path and append * to default

* bpo-30362: Modified to display list on required version not found.

* bpo-30362 add --list and --list-paths added back in following review by paul.moore

* bpo-30362 Cleaner handing of -0 & -0p by not calling exit directly per review by @zooba

* bpo-30362: Tidy up and add news & what's new

Removed commented out line of code in PC/launcher.c.
Added the results of using blurb to add details of bpo-30362 & bpo-30291.
Updated Doc/whatsnew/3.7.rst to add a Windows only section covering both tickets.

* bpo-30362 Resolve conflict in Doc/whatsnew/3.7.rst

* bpo-30362:Address Whitespace Issue in Doc\whatsnew\3.7.rst

* Shorten NEWS message for bpo-30362

* Shorten NEWS item for bpo-30291
This commit is contained in:
Steve (Gadget) Barnes 2017-06-28 20:14:52 +01:00 committed by Steve Dower
parent b01c574ad6
commit 5b8f972e09
4 changed files with 132 additions and 42 deletions

View file

@ -365,6 +365,21 @@ Changes in the C API
characters. (Contributed by Serhiy Storchaka in :issue:`30708`.)
Windows Only
------------
- The python launcher, (py.exe), can accept 32 & 64 bit specifiers **without**
having to specify a minor version as well. So ``py -3-32`` and ``py -3-64``
become valid as well as ``py -3.7-32``, also the -*m*-64 and -*m.n*-64 forms
are now accepted to force 64 bit python even if 32 bit would have otherwise
been used. If the specified version is not available py.exe will error exit.
(Contributed by Steve Barnes in :issue:`30291`.)
- The launcher can be run as "py -0" to produce a list of the installed pythons,
*with default marked with an asterix*. Running "py -0p" will include the paths.
If py is run with a version specifier that cannot be matched it will also print
the *short form* list of available specifiers.
(Contributed by Steve Barnes in :issue:`30362`.)
Removed
=======

View file

@ -0,0 +1 @@
Adds list options (-0, -0p) to py.exe launcher. Contributed by Steve Barnes.

View file

@ -0,0 +1,2 @@
Allow requiring 64-bit interpreters from py.exe using -64 suffix. Contributed
by Steve (Gadget) Barnes.

View file

@ -1371,6 +1371,89 @@ get_version_info(wchar_t * version_text, size_t size)
}
}
static void
show_help_text(wchar_t ** argv)
{
wchar_t version_text [MAX_PATH];
#if defined(_M_X64)
BOOL canDo64bit = TRUE;
#else
/* If we are a 32bit process on a 64bit Windows, first hit the 64bit keys. */
BOOL canDo64bit = FALSE;
IsWow64Process(GetCurrentProcess(), &canDo64bit);
#endif
get_version_info(version_text, MAX_PATH);
fwprintf(stdout, L"\
Python Launcher for Windows Version %ls\n\n", version_text);
fwprintf(stdout, L"\
usage:\n\
%ls [launcher-args] [python-args] script [script-args]\n\n", argv[0]);
fputws(L"\
Launcher arguments:\n\n\
-2 : Launch the latest Python 2.x version\n\
-3 : Launch the latest Python 3.x version\n\
-X.Y : Launch the specified Python version\n", stdout);
if (canDo64bit) {
fputws(L"\
The above all default to 64 bit if a matching 64 bit python is present.\n\
-X.Y-32: Launch the specified 32bit Python version\n\
-X-32 : Launch the latest 32bit Python X version\n\
-X.Y-64: Launch the specified 64bit Python version\n\
-X-64 : Launch the latest 64bit Python X version", stdout);
}
fputws(L"\n-0 --list : List the available pythons", stdout);
fputws(L"\n-0p --list-paths : List with paths", stdout);
fputws(L"\n\nThe following help text is from Python:\n\n", stdout);
fflush(stdout);
}
static BOOL
show_python_list(wchar_t ** argv)
{
/*
* Display options -0
*/
INSTALLED_PYTHON * result = NULL;
INSTALLED_PYTHON * ip = installed_pythons; /* List of installed pythons */
INSTALLED_PYTHON * defpy = locate_python(L"", FALSE);
size_t i = 0;
wchar_t *p = argv[1];
wchar_t *fmt = L"\n -%ls-%d"; /* print VER-BITS */
wchar_t *defind = L" *"; /* Default indicator */
/*
* Output informational messages to stderr to keep output
* clean for use in pipes, etc.
*/
fwprintf(stderr,
L"Installed Pythons found by %s Launcher for Windows", argv[0]);
if (!_wcsicmp(p, L"-0p") || !_wcsicmp(p, L"--list-paths")) /* Show path? */
fmt = L"\n -%ls-%d\t%ls"; /* print VER-BITS path */
if (num_installed_pythons == 0) /* We have somehow got here without searching for pythons */
locate_all_pythons(); /* Find them, Populates installed_pythons */
if (num_installed_pythons == 0) /* No pythons found */
fwprintf(stderr, L"\nNo Installed Pythons Found!");
else
{
for (i = 0; i < num_installed_pythons; i++, ip++) {
fwprintf(stdout, fmt, ip->version, ip->bits, ip->executable);
/* If there is a default indicate it */
if ((defpy != NULL) && !_wcsicmp(ip->executable, defpy->executable))
fwprintf(stderr, defind);
}
}
if ((defpy == NULL) && (num_installed_pythons > 0))
/* We have pythons but none is the default */
fwprintf(stderr, L"\n\nCan't find a Default Python.\n\n");
else
fwprintf(stderr, L"\n\n"); /* End with a blank line */
return(FALSE); /* If this has been called we cannot continue */
}
static int
process(int argc, wchar_t ** argv)
{
@ -1380,12 +1463,12 @@ process(int argc, wchar_t ** argv)
wchar_t * p;
int rc = 0;
size_t plen;
size_t slen;
INSTALLED_PYTHON * ip;
BOOL valid;
DWORD size, attrs;
HRESULT hr;
wchar_t message[MSGSIZE];
wchar_t version_text [MAX_PATH];
void * version_data;
VS_FIXEDFILEINFO * file_info;
UINT block_size;
@ -1516,12 +1599,22 @@ process(int argc, wchar_t ** argv)
else {
p = argv[1];
plen = wcslen(p);
valid = (*p == L'-') && validate_version(&p[1]);
if (argc == 2) {
slen = wcslen(L"-0");
if(!wcsncmp(p, L"-0", slen)) /* Starts with -0 */
valid = show_python_list(argv); /* Check for -0 FIRST */
}
valid = valid && (*p == L'-') && validate_version(&p[1]);
if (valid) {
ip = locate_python(&p[1], FALSE);
if (ip == NULL)
{
fwprintf(stdout, \
L"Python %ls not found!\n", &p[1]);
valid = show_python_list(argv);
error(RC_NO_PYTHON, L"Requested Python version (%ls) not \
installed", &p[1]);
installed, use -0 for available pythons", &p[1]);
}
executable = ip->executable;
command += wcslen(p);
command = skip_whitespace(command);
@ -1540,49 +1633,28 @@ installed", &p[1]);
#endif
if (!valid) {
/* Look for an active virtualenv */
executable = find_python_by_venv();
if ((argc == 2) && (!_wcsicmp(p, L"-h") || !_wcsicmp(p, L"--help")))
show_help_text(argv);
if ((argc == 2) && (!_wcsicmp(p, L"-0") || !_wcsicmp(p, L"-0p")))
executable = NULL; /* Info call only */
else
{
/* 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"", FALSE);
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;
#else
/* If we are a 32bit process on a 64bit Windows, first hit the 64bit keys. */
BOOL canDo64bit = FALSE;
IsWow64Process(GetCurrentProcess(), &canDo64bit);
#endif
get_version_info(version_text, MAX_PATH);
fwprintf(stdout, L"\
Python Launcher for Windows Version %ls\n\n", version_text);
fwprintf(stdout, L"\
usage:\n\
%ls [launcher-args] [python-args] script [script-args]\n\n", argv[0]);
fputws(L"\
Launcher arguments:\n\n\
-2 : Launch the latest Python 2.x version\n\
-3 : Launch the latest Python 3.x version\n\
-X.Y : Launch the specified Python version\n", stdout);
if (canDo64bit) {
fputws(L"\
The above all default to 64 bit if a matching 64 bit python is present.\n\
-X.Y-32: Launch the specified 32bit Python version\n\
-X-32 : Launch the latest 32bit Python X version\n\
-X.Y-64: Launch the specified 64bit Python version\n\
-X-64 : Launch the latest 64bit Python X version", stdout);
/* If we didn't find one, look for the default Python */
if (executable == NULL) {
ip = locate_python(L"", FALSE);
if (ip == NULL)
error(RC_NO_PYTHON, L"Can't find a default Python.");
executable = ip->executable;
}
fputws(L"\n\nThe following help text is from Python:\n\n", stdout);
fflush(stdout);
}
}
invoke_child(executable, NULL, command);
if (executable != NULL)
invoke_child(executable, NULL, command);
else
rc = RC_NO_PYTHON;
return rc;
}