]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-30362 : Add list options to launcher. (#1578)
authorSteve (Gadget) Barnes <gadgetsteve@hotmail.com>
Wed, 28 Jun 2017 19:14:52 +0000 (20:14 +0100)
committerSteve Dower <steve.dower@microsoft.com>
Wed, 28 Jun 2017 19:14:52 +0000 (12:14 -0700)
* 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

Doc/whatsnew/3.7.rst
Misc/NEWS.d/next/Windows/2017-06-28-03-08-22.bpo-30362.XxeVMB.rst [new file with mode: 0644]
Misc/NEWS.d/next/Windows/2017-06-28-03-20-48.bpo-30291.zBpOl6.rst [new file with mode: 0644]
PC/launcher.c

index e34268e08246821c8e454ce4e4ecd8264e19aca1..c75d7692a4d8be709778729c4bd082cc79fa4268 100644 (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
 =======
 
diff --git a/Misc/NEWS.d/next/Windows/2017-06-28-03-08-22.bpo-30362.XxeVMB.rst b/Misc/NEWS.d/next/Windows/2017-06-28-03-08-22.bpo-30362.XxeVMB.rst
new file mode 100644 (file)
index 0000000..fb24ec5
--- /dev/null
@@ -0,0 +1 @@
+Adds list options (-0, -0p) to py.exe launcher. Contributed by Steve Barnes.
diff --git a/Misc/NEWS.d/next/Windows/2017-06-28-03-20-48.bpo-30291.zBpOl6.rst b/Misc/NEWS.d/next/Windows/2017-06-28-03-20-48.bpo-30291.zBpOl6.rst
new file mode 100644 (file)
index 0000000..2869823
--- /dev/null
@@ -0,0 +1,2 @@
+Allow requiring 64-bit interpreters from py.exe using -64 suffix. Contributed
+by Steve (Gadget) Barnes.
index 25fa4ca9c211b982fbac8f98fa543af3faefaa6f..0733df7563f121de39bb2398433e08c8c7af87ac 100644 (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 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 ((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;
             }
-            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;
 }