-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
launcher.c: add support for Unicode sys.argv in cli/gui.exe Windows launchers #595
Conversation
…aunchers use the Windows Unicode API to retrieve the commandline arguments as wchar_t*, so we can pass them on unchanged to the wrapped python script. Also see: - https://bugs.python.org/issue2128 - https://hg.python.org/cpython/rev/22a74eaf6b22/
This all sounds good to me. I no longer actively develop on Windows, so I might struggle a bit with compiling the executables, but I'll try to do that. Out of curiosity, have you encountered this issue when running executables produced by distlib or |
No, I haven't tried distlib yet. I'll give it a try and let you know. Btw, I managed to compile
I also compiled it successfully using GCC 5.3.0 from mingw-w64, using the following commands:
|
So.. I just tried to plug the distlib-generated .exe launchers in setuptools' test suite, and tried running the unicode sys.argv unit tests above, and -- I'm happy and a little bit sad at the same time. Happy because they seem to be working; a bit sad because I spent a few days trying to fix this in setuptools, without knowing @vsajip had already fixed the issue in distlib... ;) Although the unicode argv works, two other tests in I'd really like this issue to be solved, whether in setuptools or through distlib. |
@anthrotype Thanks so much for the extended work on this. My guess is there's more work to be done than just copying the executables from distlib. I was actually thinking that distlib could be vendored into setuptools (the way that six and packaging are) and then it could replace all of the script handling logic (not just the windows executables). I'm happy to accept for a short-term solution to simply bundle the distlib executables or to accept this pull request above and implement the originally proposed solution, but of course it would be best to remove as much of this duplication as possible... I am worried about the failing test cases, as you mentioned. If we're to include the distlib executables, I'd like to know why those tests are failing. So short answer is - whatever you have time for, I appreciate the help. |
That sounds good to me, better to avoid duplication.
the problem is that the pre-compiled executables in distlib are meant to work with At least they need to be recompiled without This definition specifies the mode in which the launcher works:
As I mentioned yesterday, even when I recompile the distlib launcher without After tinkering with pointers, I eventually found a solution to the issue (see patch below).
As I'm not familiar enough with mercurial to send a pull request myself, it'd be nice if someone could have a look and send the patch to the bitbucket repository? 😁 diff -r a258e3bdd6f8 PC/launcher.c
--- a/PC/launcher.c Mon May 16 23:31:18 2016 +0100
+++ b/PC/launcher.c Fri May 27 12:46:01 2016 +0100
@@ -33,7 +33,7 @@
#pragma comment (lib, "Shlwapi.lib")
-#define APPENDED_ARCHIVE
+// #define APPENDED_ARCHIVE
#define MSGSIZE 1024
@@ -406,6 +406,8 @@
}
/* p points just past the executable. It must either be a NUL or whitespace. */
assert(*p != L'"', "Terminating quote without starting quote for executable in shebang line.");
+ /* if p is whitespace, make it NULL to truncate 'line', and advance */
+ if (*p && iswspace(*p)) *p++ = L'\0';
/* Now we can skip the whitespace, having checked that it's there. */
while(*p && iswspace(*p))
++p;
so after this patch I can replace the |
unlike setuptools, distlib does not have precompiled launchers for the ARM platform; only 32 and 64 bit, cli and gui. But I guess those should be easy to make. |
It's quite possible that Vinay accepts pull requests in the github mirror.
I don't think it will be acceptable to comment out that line - after all, pip uses the version with that variable defined. I'd like to setuptools to use the same. Can we adapt setuptools to append the script instead?
Again, maybe it makes sense for setuptools to generate scripts that are compatible with the launchers as written. Is that possible?
Yes, this issue should be filed with distlib. Would you like me to do that? |
Sure we can do that. So to clarify, you want setuptools to make the exe launchers the same way that distlib ScriptMaker does (by appending the shebang and source code), but without requiring to import from distlib (at least, temporarily)?
yeah, we could put quotes to work around that bug, but the bug still needs to be fixed upstream.
Yes please! Thanks. |
Yes.
Sounds good. |
…wed by interpreter args See pypa/setuptools#595 (comment)
ok, now that ARM launchers are gone, it should be easier to integrate distlib launchers in setuptools. Do you want me to close this PR and open a separate one, or shall I keep working on this branch? The simplest way to proceed is to modify the Another option would be to "vendor" distlib, like pip currently does, and use distlib's What do you prefer me to do? Besides, I noticed another difference between the way setuptools and distlib make their launchers: setuptools also adds an (external) manifest file for each .exe. The manifest is added only for 32 bit launchers, and according to the inline comment, it is meant
distlib, on the other hand, (or at least the way pip currently uses it) doesn't seem to add a manifest by default to the executables. |
Well, if |
I seem to recall that only one of the 32-bit or 64-bit executables needed the manifest. |
for the records, this is the distribute issue 143 that the comment I quoted above was referring to: |
so it appears the issue of undesired UAC elevation only affects executables detected as installers:
https://technet.microsoft.com/en-us/library/cc709628(WS.10).aspx I haven't read the full MS article, but I believe we should include the manifest at least for scripts that happen to contain one of those keywords. It's going to be an external xml file, because for embedding it inside the executable itself we need the |
OK, I run some tests and it appears that the distlib launchers do not need any external manifest file, even when the script name contains keywords like "install", or "setup". I made a minimalist I tested it on Python 2.7 and 3.5 32-bit with setuptools 23.0. When I install my test module from source distribution ( If I then delete or rename the manifest file, and try to run this executable (containing the "install" word in the name) under Windows 7, I get "permission denied". So for setuptools launchers, the manifest is required, at least when thos keywords are present in the script name. However, if I make a wheel first, and the I This time, even the executable has "install" in its name, It Just Works™ 😄 I presume it's the way the setuptools and the distlib launchers are compiled. For the first, the So, all in all, I think we can safely get rid of the manifest thing if we switch to distlib launchers. |
@anthrotype Thanks for the detailed analysis. That sounds good to me. |
The
It's present in all four launchers. |
@vsajip thanks for the confirmation! It wasn't clear to me. :) |
@jaraco I modified easy_install.py to use the distlib launchers, however now I'm not sure what to do with the current setuptools launcher executables (cli-32.exe, gui-32.exe, etc.) included as package_data in setuptools source. Shall I simply replace them with the pre-compiled distlib binaries, found here? And what names shall I use for these: the same distlib uses (t32.exe, t64.exe, w32.exe and w64.exe), or I should keep the current setuptools names (cli-32.exe, cli-64.exe, gui-32.exe, gui-64.exe)? I would prefer to use the distlib names to make it clearer they work differently from the old ones. And what about those copies of the 32 bit launchers which don't not have a "-32" suffix?
Shall I get rid of the two launchers above? The "msvc-build-launcher.cmd" itself should go, I think. It should probably be replaced by a copy of @vsajip simple_launcher source files. |
ah, and what about the |
Please have a look at this branch on my setuptools fork: I can force-push to this same PR branch, or open a new pull request if you like. |
Note that these updated sources will be copied to the |
Overall, my suggestion is that we re-use as much of distlib as possible. If it's possible, for example, to call into distlib (perhaps passing the script text) and let distlib produce the executables, that would be best.
Perhaps we should keep the old ones in place just in case other libraries are referencing them. We'll definitely mark them as deprecated and not use them internally.
I'd like not to copy anything into setuptools, but instead reference it from distlib. If making calls into distlib isn't suitable, and we need to reference these resources directly, then we should reference them from the distlib package. There might be some challenges with doing this using a vendored package, but if you want to simply assume that distlib is a requirement of setuptools for now, that would be fine.
Same as the other scripts - we'll leave them there for now for compatibility, and we'll remove all of them with one announced release.
Agreed. |
Let's consider that deprecated also, and remove it when removing the launcher executables.
Go ahead and force-push that here. Thanks. |
Thanks for the reply. |
If you run into any problems invoking |
I'm going to close this for now, but feel free to revive the effort at any time. |
I'm sorry, I could not find the time to work on this as I was busy with other stuff... |
I'm having exactly same issue. Really pity this was abandoned because CLI executables without support for unicode arguments are almost unusable. E.g. you can't even pass non-ASCII filename. |
Googling to find out why console scripts installed by conda on Windows (through setuptools 61.2.0 I guess, not distlib) lost out-of-codepage characters in the command line, I landed here. How about reopening this issue and merge the OP's PR to solve it in setuptools itself, too? |
I'm sorry, but it's simply untenable to maintain multiple copies of launchers. The launchers in Setuptools are deprecated. The path forward is one of the following:
|
Given #2825, would adding |
In Python 3 on Windows,
sys.argv
is created through the Windows Unicode API.That means command line arguments are retrieved as
wchar_t*
through the Windows-specificwmain
(for console programs) andwWinMain
(for gui programs) entry points.See https://bugs.python.org/issue2128
However, setuptools' "cli.exe" and "gui.exe" launchers, as defined in
launcher.c
, are still using the Windows ANSI API: i.e. the entry point ismain
, andargv
type ischar *
instead ofwchar_t*
, which means it's dependant on the current console's codepage.This prevents Windows Python 3 from accessing the Unicode command line arguments which are sent by Windows when running python scripts via the usual
python.exe
command. When run through launchers, thesys.argv
contains instead replacement strings like "?????", which is not nice.The fix proposed here is similar to the one which introduced support for Unicode sys.argv in Python 3: https://hg.python.org/cpython/rev/22a74eaf6b22/
Basically:
wchar_t *argv
wcslen
insteadof
strlen
,CreateProcessW
instead ofCreateProcessA
, etc.)Please let me know what you think.
Thank you.