-
-
Notifications
You must be signed in to change notification settings - Fork 13
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
Fix run on non-Windows environments #25
Conversation
Previously, the command was first executed once, and if that resulted in a certain WindowsError, then the command was retried in shell mode. The intention was to support Windows' file associations for file launch. However, this causes problems in non-Windows environments, as WindowsError exception is not defined. Trying to catch a WindowsError exception is unnecessary for file associations, as non-executable files are already run in shell mode on the first try. This change simplifies the logic, still supporting direct execution for executables and shell mode for shell builtins and Window's file launch. Fixes #18.
Shutil which gives more accurate results than distutils find_executable, e.g. it checks if the result is marked as an executable or not.
Thanks for the pr! The fallbacks and approaches we are using are there for a reason. That is to say, we have them in place because we have implemented and deployed the alternative approach and run into edge cases So, while I appreciate that this results in less code, the existing approach (which explains why it is in place) is quite necessary. Also, |
@techalchemy Can you elaborate what these edge cases are, so I can verify it behaves correctly after my changes. I tested this quite extensively with Python 2.7/3.7 and Mac OS/Windows. Running an executable, shell builtin or Windows app based on file associations works like before. Also, the behavior if the command fails to execute is now consistent between Windows and others, i.e. no exception is thrown but run returns the error message. |
We test against 2.7 through 3.7 including 3.4, 3.5 and 3.6, on windows, osx and linux, and there is a discussion about this here: pypa/pipenv#2882 We also test this in production systems across every user of pipenv, and run into those edge cases, which is how we know about them, and is also why we aren't likely to simply make a change because you did some testing locally :| The scale of the usage of these libraries is enormous, so just because it works for you doesn't mean it covers all of the edge cases. I appreciate your contribution, but you should start by assuming the approach we took has a reason behind it, and ask yourself what that reason is, or if you're not sure, ask us. It is a lot more productive than assuming our code is wrong and we had no reason. "It works on my machine" is unfortunately not usually good enough in cases like this one. |
@techalchemy Thanks for your responses! I understand your concern, but please let me point a few things before you make the decision. If I've understood correctly, the changes I've simplified here, which came mostly in commit 1232e7b, were motivated by an improvement done originally for pipenv (pypa/pipenv/pull/2727). The intention was to support Windows' file launch and not to raise OSError if execution failed. However, the original change in pipenv didn't use distutils.spawn.find_executable, but it used which/where system utility. On Windows, where returns all kinds of things, not just executables, as was noted in the pipenv PR comment. This was the reason why the original author had to execute the command first and catch WindowsError if it wasn't an executable after all. Also, the original change was in a code path specific to Windows. Now, when these changes were reproduced in vistir, the system_which was changed to distutils' find_executable, which only returns paths ending with .exe on Windows. Please see the relevant part in distutils' source. In other words, if you feed The one place where the current dual execution would make a difference is if the command actually ends with .exe, or looks like an executable in others systems, but would still not be a valid application. In this case the first execution would result in WindowsError, or more generally OSError. Then the next execution would be done in shell mode, producing a popup on Windows that the user would have to manually click and then returns an error string
That would also prevent the popup and result in a more descriptive error message. I changed to shutil.which, because it also checks if the file is executable on systems where it's possible. This works with distutils' find_executable as well, it'll just return more false positives. I hope you had the time to read this far. If you still think this doesn't make any sense, then I'll just go away.. :-) |
It does make sense to me as described, that is nice digging! Thanks for persisting. I’d accept a PR for that for sure |
Fixes #18.