Repository: pypa/setuptools

Issue:
Executable python application may fail depending on temp folder
Hi

I've analyzed a strange issue with python based windows executable built with pyinstaller. The executable could be built without an issue, but when the tool was started the following error occurs:

```
File "site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgres.py", line 13, in <module>
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "c:\hostedtoolcache\windows\python\3.7.6\x64\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 489, in exec_module
File "site-packages\pkg_resources\__init__.py", line 3251, in <module>
File "site-packages\pkg_resources\__init__.py", line 3235, in _call_aside
File "site-packages\pkg_resources\__init__.py", line 3264, in _initialize_master_working_set
File "site-packages\pkg_resources\__init__.py", line 574, in _build_master
File "site-packages\pkg_resources\__init__.py", line 567, in __init__
File "site-packages\pkg_resources\__init__.py", line 623, in add_entry
File "site-packages\pkg_resources\__init__.py", line 1983, in find_eggs_in_zip
File "site-packages\pkg_resources\__init__.py", line 1414, in has_metadata
File "site-packages\pkg_resources\__init__.py", line 1853, in _has
File "site-packages\pkg_resources\__init__.py", line 1716, in _zipinfo_name
AssertionError: C:\Users\A9447~1.EGG\EGG-INFO\PKG-INFO is not a subpath of C:\Users\A9447~1.EGG\AppData\Local\Temp\_MEI120962\base_library.zip\
[10872] Failed to execute script pyi_rth_pkgres
```

After a while I've found out that the same executable works properly on other workstations or even with other user accounts.
I guess I've found the root cause for my problem in the file "pkg_ressources.py" of the setuptools. In the function "_setup_prefix" is a test if a path ends with ".egg", what is the case in my situation for my temporairy folder (=> "C:\\Users\\A9447\~1.EGG"). This causes that a new invalid path was built and afterwards caused the assertion. "C:\Users\A9447~1.EGG" is the default temp folder for my user "a.eggenberger".

The quick solution was to set another user temp folder "C\\:Temp". This solved the behavior and it works as expected.

To avoid that other users with a lastname starting with "egg" the code in the _setup_prefix function should be improved.

Regards Adrian
Executable python application may fail depending on temp folder
Hi

I've analyzed a strange issue with python based windows executable built with pyinstaller. The executable could be built without an issue, but when the tool was started the following error occurs:

```
File "site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgres.py", line 13, in <module>
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "c:\hostedtoolcache\windows\python\3.7.6\x64\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 489, in exec_module
File "site-packages\pkg_resources\__init__.py", line 3251, in <module>
File "site-packages\pkg_resources\__init__.py", line 3235, in _call_aside
File "site-packages\pkg_resources\__init__.py", line 3264, in _initialize_master_working_set
File "site-packages\pkg_resources\__init__.py", line 574, in _build_master
File "site-packages\pkg_resources\__init__.py", line 567, in __init__
File "site-packages\pkg_resources\__init__.py", line 623, in add_entry
File "site-packages\pkg_resources\__init__.py", line 1983, in find_eggs_in_zip
File "site-packages\pkg_resources\__init__.py", line 1414, in has_metadata
File "site-packages\pkg_resources\__init__.py", line 1853, in _has
File "site-packages\pkg_resources\__init__.py", line 1716, in _zipinfo_name
AssertionError: C:\Users\A9447~1.EGG\EGG-INFO\PKG-INFO is not a subpath of C:\Users\A9447~1.EGG\AppData\Local\Temp\_MEI120962\base_library.zip\
[10872] Failed to execute script pyi_rth_pkgres
```

After a while I've found out that the same executable works properly on other workstations or even with other user accounts.
I guess I've found the root cause for my problem in the file "pkg_ressources.py" of the setuptools. In the function "_setup_prefix" is a test if a path ends with ".egg", what is the case in my situation for my temporairy folder (=> "C:\\Users\\A9447\~1.EGG"). This causes that a new invalid path was built and afterwards caused the assertion. "C:\Users\A9447~1.EGG" is the default temp folder for my user "a.eggenberger".

The quick solution was to set another user temp folder "C\\:Temp". This solved the behavior and it works as expected.

To avoid that other users with a lastname starting with "egg" the code in the _setup_prefix function should be improved.

Regards Adrian


Discussion:
This might be a contender for one of the most obscure bugs I've seen. Not only does it depend on the fact that your last name begins with "egg" but it also depends on the fact that the egg-prefixed name appears in the last segment of the pathname, and it depends on the fact that you're on Windows, which provides compatibility with the decades-old [8.3 convention](https://en.wikipedia.org/wiki/8.3_filename). I suspect there's another factor at play too that's causing the 8.3 filename to be used instead of the proper full filename.
"This might be a contender for one of the most obscure bugs I've seen."
=> I totally agree with that... :-)
This might be a contender for one of the most obscure bugs I've seen. Not only does it depend on the fact that your last name begins with "egg" but it also depends on the fact that the egg-prefixed name appears in the last segment of the pathname, and it depends on the fact that you're on Windows, which provides compatibility with the decades-old [8.3 convention](https://en.wikipedia.org/wiki/8.3_filename). I suspect there's another factor at play too that's causing the 8.3 filename to be used instead of the proper full filename.
"This might be a contender for one of the most obscure bugs I've seen."
=> I totally agree with that... :-)

Resolving patch:
diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py
--- a/pkg_resources/__init__.py
+++ b/pkg_resources/__init__.py
@@ -2057,7 +2057,10 @@ def find_on_path(importer, path_item, only=False):
         )
         return
 
-    entries = safe_listdir(path_item)
+    entries = (
+        os.path.join(path_item, child)
+        for child in safe_listdir(path_item)
+    )
 
     # for performance, before sorting by version,
     # screen entries for only those that will yield
@@ -2373,7 +2376,15 @@ def _is_egg_path(path):
     """
     Determine if given path appears to be an egg.
     """
-    return path.lower().endswith('.egg')
+    return _is_zip_egg(path) or _is_unpacked_egg(path)
+
+
+def _is_zip_egg(path):
+    return (
+        path.lower().endswith('.egg') and
+        os.path.isfile(path) and
+        zipfile.is_zipfile(path)
+    )
 
 
 def _is_unpacked_egg(path):
@@ -2381,7 +2392,7 @@ def _is_unpacked_egg(path):
     Determine if given path appears to be an unpacked egg.
     """
     return (
-        _is_egg_path(path) and
+        path.lower().endswith('.egg') and
         os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO'))
     )
 


Test patch: