Skip to content

Commit 5b8f972

Browse files
GadgetStevezooba
authored andcommitted
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
1 parent b01c574 commit 5b8f972

File tree

4 files changed

+133
-43
lines changed

4 files changed

+133
-43
lines changed

Doc/whatsnew/3.7.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,21 @@ Changes in the C API
365365
characters. (Contributed by Serhiy Storchaka in :issue:`30708`.)
366366

367367

368+
Windows Only
369+
------------
370+
- The python launcher, (py.exe), can accept 32 & 64 bit specifiers **without**
371+
having to specify a minor version as well. So ``py -3-32`` and ``py -3-64``
372+
become valid as well as ``py -3.7-32``, also the -*m*-64 and -*m.n*-64 forms
373+
are now accepted to force 64 bit python even if 32 bit would have otherwise
374+
been used. If the specified version is not available py.exe will error exit.
375+
(Contributed by Steve Barnes in :issue:`30291`.)
376+
377+
- The launcher can be run as "py -0" to produce a list of the installed pythons,
378+
*with default marked with an asterix*. Running "py -0p" will include the paths.
379+
If py is run with a version specifier that cannot be matched it will also print
380+
the *short form* list of available specifiers.
381+
(Contributed by Steve Barnes in :issue:`30362`.)
382+
368383
Removed
369384
=======
370385

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Adds list options (-0, -0p) to py.exe launcher. Contributed by Steve Barnes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Allow requiring 64-bit interpreters from py.exe using -64 suffix. Contributed
2+
by Steve (Gadget) Barnes.

PC/launcher.c

Lines changed: 115 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,89 @@ get_version_info(wchar_t * version_text, size_t size)
13711371
}
13721372
}
13731373

1374+
static void
1375+
show_help_text(wchar_t ** argv)
1376+
{
1377+
wchar_t version_text [MAX_PATH];
1378+
#if defined(_M_X64)
1379+
BOOL canDo64bit = TRUE;
1380+
#else
1381+
/* If we are a 32bit process on a 64bit Windows, first hit the 64bit keys. */
1382+
BOOL canDo64bit = FALSE;
1383+
IsWow64Process(GetCurrentProcess(), &canDo64bit);
1384+
#endif
1385+
1386+
get_version_info(version_text, MAX_PATH);
1387+
fwprintf(stdout, L"\
1388+
Python Launcher for Windows Version %ls\n\n", version_text);
1389+
fwprintf(stdout, L"\
1390+
usage:\n\
1391+
%ls [launcher-args] [python-args] script [script-args]\n\n", argv[0]);
1392+
fputws(L"\
1393+
Launcher arguments:\n\n\
1394+
-2 : Launch the latest Python 2.x version\n\
1395+
-3 : Launch the latest Python 3.x version\n\
1396+
-X.Y : Launch the specified Python version\n", stdout);
1397+
if (canDo64bit) {
1398+
fputws(L"\
1399+
The above all default to 64 bit if a matching 64 bit python is present.\n\
1400+
-X.Y-32: Launch the specified 32bit Python version\n\
1401+
-X-32 : Launch the latest 32bit Python X version\n\
1402+
-X.Y-64: Launch the specified 64bit Python version\n\
1403+
-X-64 : Launch the latest 64bit Python X version", stdout);
1404+
}
1405+
fputws(L"\n-0 --list : List the available pythons", stdout);
1406+
fputws(L"\n-0p --list-paths : List with paths", stdout);
1407+
fputws(L"\n\nThe following help text is from Python:\n\n", stdout);
1408+
fflush(stdout);
1409+
}
1410+
1411+
static BOOL
1412+
show_python_list(wchar_t ** argv)
1413+
{
1414+
/*
1415+
* Display options -0
1416+
*/
1417+
INSTALLED_PYTHON * result = NULL;
1418+
INSTALLED_PYTHON * ip = installed_pythons; /* List of installed pythons */
1419+
INSTALLED_PYTHON * defpy = locate_python(L"", FALSE);
1420+
size_t i = 0;
1421+
wchar_t *p = argv[1];
1422+
wchar_t *fmt = L"\n -%ls-%d"; /* print VER-BITS */
1423+
wchar_t *defind = L" *"; /* Default indicator */
1424+
1425+
/*
1426+
* Output informational messages to stderr to keep output
1427+
* clean for use in pipes, etc.
1428+
*/
1429+
fwprintf(stderr,
1430+
L"Installed Pythons found by %s Launcher for Windows", argv[0]);
1431+
if (!_wcsicmp(p, L"-0p") || !_wcsicmp(p, L"--list-paths")) /* Show path? */
1432+
fmt = L"\n -%ls-%d\t%ls"; /* print VER-BITS path */
1433+
1434+
if (num_installed_pythons == 0) /* We have somehow got here without searching for pythons */
1435+
locate_all_pythons(); /* Find them, Populates installed_pythons */
1436+
1437+
if (num_installed_pythons == 0) /* No pythons found */
1438+
fwprintf(stderr, L"\nNo Installed Pythons Found!");
1439+
else
1440+
{
1441+
for (i = 0; i < num_installed_pythons; i++, ip++) {
1442+
fwprintf(stdout, fmt, ip->version, ip->bits, ip->executable);
1443+
/* If there is a default indicate it */
1444+
if ((defpy != NULL) && !_wcsicmp(ip->executable, defpy->executable))
1445+
fwprintf(stderr, defind);
1446+
}
1447+
}
1448+
1449+
if ((defpy == NULL) && (num_installed_pythons > 0))
1450+
/* We have pythons but none is the default */
1451+
fwprintf(stderr, L"\n\nCan't find a Default Python.\n\n");
1452+
else
1453+
fwprintf(stderr, L"\n\n"); /* End with a blank line */
1454+
return(FALSE); /* If this has been called we cannot continue */
1455+
}
1456+
13741457
static int
13751458
process(int argc, wchar_t ** argv)
13761459
{
@@ -1380,12 +1463,12 @@ process(int argc, wchar_t ** argv)
13801463
wchar_t * p;
13811464
int rc = 0;
13821465
size_t plen;
1466+
size_t slen;
13831467
INSTALLED_PYTHON * ip;
13841468
BOOL valid;
13851469
DWORD size, attrs;
13861470
HRESULT hr;
13871471
wchar_t message[MSGSIZE];
1388-
wchar_t version_text [MAX_PATH];
13891472
void * version_data;
13901473
VS_FIXEDFILEINFO * file_info;
13911474
UINT block_size;
@@ -1516,12 +1599,22 @@ process(int argc, wchar_t ** argv)
15161599
else {
15171600
p = argv[1];
15181601
plen = wcslen(p);
1519-
valid = (*p == L'-') && validate_version(&p[1]);
1602+
if (argc == 2) {
1603+
slen = wcslen(L"-0");
1604+
if(!wcsncmp(p, L"-0", slen)) /* Starts with -0 */
1605+
valid = show_python_list(argv); /* Check for -0 FIRST */
1606+
}
1607+
valid = valid && (*p == L'-') && validate_version(&p[1]);
15201608
if (valid) {
15211609
ip = locate_python(&p[1], FALSE);
15221610
if (ip == NULL)
1611+
{
1612+
fwprintf(stdout, \
1613+
L"Python %ls not found!\n", &p[1]);
1614+
valid = show_python_list(argv);
15231615
error(RC_NO_PYTHON, L"Requested Python version (%ls) not \
1524-
installed", &p[1]);
1616+
installed, use -0 for available pythons", &p[1]);
1617+
}
15251618
executable = ip->executable;
15261619
command += wcslen(p);
15271620
command = skip_whitespace(command);
@@ -1540,49 +1633,28 @@ installed", &p[1]);
15401633
#endif
15411634

15421635
if (!valid) {
1543-
/* Look for an active virtualenv */
1544-
executable = find_python_by_venv();
1545-
1546-
/* If we didn't find one, look for the default Python */
1547-
if (executable == NULL) {
1548-
ip = locate_python(L"", FALSE);
1549-
if (ip == NULL)
1550-
error(RC_NO_PYTHON, L"Can't find a default Python.");
1551-
executable = ip->executable;
1552-
}
1553-
if ((argc == 2) && (!_wcsicmp(p, L"-h") || !_wcsicmp(p, L"--help"))) {
1554-
#if defined(_M_X64)
1555-
BOOL canDo64bit = TRUE;
1556-
#else
1557-
/* If we are a 32bit process on a 64bit Windows, first hit the 64bit keys. */
1558-
BOOL canDo64bit = FALSE;
1559-
IsWow64Process(GetCurrentProcess(), &canDo64bit);
1560-
#endif
1561-
1562-
get_version_info(version_text, MAX_PATH);
1563-
fwprintf(stdout, L"\
1564-
Python Launcher for Windows Version %ls\n\n", version_text);
1565-
fwprintf(stdout, L"\
1566-
usage:\n\
1567-
%ls [launcher-args] [python-args] script [script-args]\n\n", argv[0]);
1568-
fputws(L"\
1569-
Launcher arguments:\n\n\
1570-
-2 : Launch the latest Python 2.x version\n\
1571-
-3 : Launch the latest Python 3.x version\n\
1572-
-X.Y : Launch the specified Python version\n", stdout);
1573-
if (canDo64bit) {
1574-
fputws(L"\
1575-
The above all default to 64 bit if a matching 64 bit python is present.\n\
1576-
-X.Y-32: Launch the specified 32bit Python version\n\
1577-
-X-32 : Launch the latest 32bit Python X version\n\
1578-
-X.Y-64: Launch the specified 64bit Python version\n\
1579-
-X-64 : Launch the latest 64bit Python X version", stdout);
1636+
if ((argc == 2) && (!_wcsicmp(p, L"-h") || !_wcsicmp(p, L"--help")))
1637+
show_help_text(argv);
1638+
if ((argc == 2) && (!_wcsicmp(p, L"-0") || !_wcsicmp(p, L"-0p")))
1639+
executable = NULL; /* Info call only */
1640+
else
1641+
{
1642+
/* Look for an active virtualenv */
1643+
executable = find_python_by_venv();
1644+
1645+
/* If we didn't find one, look for the default Python */
1646+
if (executable == NULL) {
1647+
ip = locate_python(L"", FALSE);
1648+
if (ip == NULL)
1649+
error(RC_NO_PYTHON, L"Can't find a default Python.");
1650+
executable = ip->executable;
15801651
}
1581-
fputws(L"\n\nThe following help text is from Python:\n\n", stdout);
1582-
fflush(stdout);
15831652
}
15841653
}
1585-
invoke_child(executable, NULL, command);
1654+
if (executable != NULL)
1655+
invoke_child(executable, NULL, command);
1656+
else
1657+
rc = RC_NO_PYTHON;
15861658
return rc;
15871659
}
15881660

0 commit comments

Comments
 (0)