-
-
Notifications
You must be signed in to change notification settings - Fork 476
Description
Describe the bug
sysconfig.get_path("purelib") returns site-packages folder instead of app_packages
Some libraries access sysconfig.get_path("purelib") to get the path of the folder, where the 3rd party libraries are installed. E.g. pydevd (see here) or debugpy (see here)
Currently sysconfig.get_paths() returns on Windows
{
'stdlib': '...\build\helloworld\windows\app\src\Lib',
'platstdlib': '...\build\helloworld\windows\app\src\Lib',
'purelib': '...\build\helloworld\windows\app\src\Lib\site-packages',
'platlib': '...\build\helloworld\windows\app\src\Lib\site-packages',
'include': '...\build\helloworld\windows\app\src\Include',
'platinclude': '...\build\helloworld\windows\app\src\Include',
'scripts': '...\build\helloworld\windows\app\src\Scripts',
'data': '...\build\helloworld\windows\app\src'
}
But ...\build\helloworld\windows\app\src\Lib\site-packages does not exists, because all libraries are inside ...\build\helloworld\windows\app\src\app_packages.
Steps to reproduce
- Create an example briefcase app
- Add
import sysconfig
print(sysconfig.get_path("purelib"))
- Run
briefcase run
Expected behavior
sysconfig.get_path("purelib") should return the path to the app_packages folder instead of the non existing site-packages folder.
Screenshots
No response
Environment
- Operating System: Windows 11
- Python version: 3.13
- Software versions:
- Briefcase: 0.3.24
Logs
Additional context
There has already been discussion about whether it makes sense to use the standard site-packages folder instead of a custom app_packages folder, and why it was rejected: #2195
I created a working sysconfig patch function that can may be used:
Details
def _patch_sysconfig():
import sysconfig
BRIEFCASE_SCHEME = "briefcase"
sysconfig._INSTALL_SCHEMES[BRIEFCASE_SCHEME] = {
"stdlib": "{installed_base}/Lib",
"platstdlib": "{base}/Lib",
"purelib": "{base}/app_packages",
"platlib": "{base}/app_packages",
"include": "{installed_base}/Include",
"platinclude": "{installed_base}/Include",
"scripts": "{base}/Scripts",
"data": "{base}",
}
__orig_get_paths = sysconfig.get_paths
__orig_get_path = sysconfig.get_path
def get_default_scheme():
return BRIEFCASE_SCHEME
def get_paths(*args, **kwargs):
if len(args) >= 1:
new_args = list(args)
if new_args[0] is None:
new_args[0] = BRIEFCASE_SCHEME
args = tuple(new_args)
elif "scheme" not in kwargs or kwargs.get("scheme") is None:
kwargs["scheme"] = BRIEFCASE_SCHEME
return __orig_get_paths(*args, **kwargs)
def get_path(*args, **kwargs):
if len(args) >= 2:
new_args = list(args)
if new_args[1] is None:
new_args[1] = BRIEFCASE_SCHEME
args = tuple(new_args)
elif "scheme" not in kwargs or kwargs.get("scheme") is None:
kwargs["scheme"] = BRIEFCASE_SCHEME
return __orig_get_path(*args, **kwargs)
sysconfig.get_default_scheme = get_default_scheme
sysconfig.get_paths = get_paths
sysconfig.get_path = get_path