77
88# Prints warning without stack or line info
99def prettywarn (msg , warntype ):
10- original = warnings .showwarning
11- def _warning (message , category , filename , lineno , file = None , line = None ):
12- print (message )
13- warnings .showwarning = _warning
10+ """Prints a suppressable warning without stack or line info."""
11+ original = warnings .formatwarning
12+ def _pretty_fmt (message , category , filename , lineno , line = None ):
13+ return "{0}: {1}\n " .format (category .__name__ , message )
14+ warnings .formatwarning = _pretty_fmt
1415 warnings .warn (msg , warntype )
15- warnings .showwarning = original
16+ warnings .formatwarning = original
1617
1718# Use DLLs from pysdl2-dll, if installed and DLL path not explicitly set
1819try :
1920 prepath = os .getenv ('PYSDL2_DLL_PATH' )
2021 import sdl2dll
2122 postpath = os .getenv ('PYSDL2_DLL_PATH' )
2223 if prepath != postpath :
23- msg = "UserWarning: Using SDL2 binaries from pysdl2-dll {0}"
24+ msg = "Using SDL2 binaries from pysdl2-dll {0}"
2425 prettywarn (msg .format (sdl2dll .__version__ ), UserWarning )
2526except ImportError :
2627 pass
@@ -36,6 +37,48 @@ class SDL_version(Structure):
3637 ]
3738
3839
40+ def _using_ms_store_python ():
41+ """Checks if the Python interpreter was installed from the Microsoft Store."""
42+ return 'WindowsApps\\ PythonSoftwareFoundation.' in sys .executable
43+
44+
45+ def _preload_deps (libname , dllpath ):
46+ """Preloads all DLLs that SDL2 and its extensions link to (e.g. libFLAC).
47+
48+ This is required for Python installed from the Microsoft Store, which has
49+ strict DLL loading rules but will allow loading of DLLs that have already
50+ been loaded by the current process.
51+ """
52+ deps = {
53+ "SDL2" : [],
54+ "SDL2_ttf" : ["freetype" ],
55+ "SDL2_image" : ["zlib" , "jpeg" , "png16" , "tiff" , "webp" ],
56+ "SDL2_mixer" : ["modplug" , "mpg123" , "ogg" , "vorbis" , "vorbisfile" ,
57+ "opus" , "opusfile" , "FLAC" ],
58+ "SDL2_gfx" : []
59+ }
60+ preloaded = {}
61+ dlldir = os .path .abspath (os .path .join (dllpath , os .pardir ))
62+ all_dlls = [f for f in os .listdir (dlldir ) if f .split ("." )[- 1 ] == "dll" ]
63+ for name in deps [libname ]:
64+ dllname = name if name == "zlib" else "lib{0}-" .format (name )
65+ for dll in all_dlls :
66+ if dll .startswith (dllname ):
67+ try :
68+ filepath = os .path .join (dlldir , dll )
69+ preloaded [name ] = CDLL (filepath )
70+ except OSError :
71+ pass
72+ break
73+
74+ if len (preloaded ) < len (deps [libname ]):
75+ e = ("Unable to preload all dependencies for {0}. This module may not "
76+ "work correctly." )
77+ prettywarn (e .format (libname ), RuntimeWarning )
78+
79+ return preloaded
80+
81+
3982def _findlib (libnames , path = None ):
4083 """Finds SDL2 libraries and returns them in a list, with libraries found in the directory
4184 optionally specified by 'path' being first (taking precedence) and libraries found in system
@@ -98,6 +141,7 @@ class DLL(object):
98141 """
99142 def __init__ (self , libinfo , libnames , path = None ):
100143 self ._dll = None
144+ self ._deps = None
101145 self ._libname = libinfo
102146 self ._version = None
103147 minversions = {
@@ -133,6 +177,8 @@ def __init__(self, libinfo, libnames, path=None):
133177 if self ._dll is None :
134178 raise RuntimeError ("found %s, but it's not usable for the library %s" %
135179 (foundlibs , libinfo ))
180+ if _using_ms_store_python ():
181+ self ._deps = _preload_deps (libinfo , self ._libfile )
136182 if path is not None and sys .platform in ("win32" ,) and \
137183 path in self ._libfile :
138184 os .environ ["PATH" ] = "%s;%s" % (path , os .environ ["PATH" ])
0 commit comments