7
7
8
8
# Prints warning without stack or line info
9
9
def 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
14
15
warnings .warn (msg , warntype )
15
- warnings .showwarning = original
16
+ warnings .formatwarning = original
16
17
17
18
# Use DLLs from pysdl2-dll, if installed and DLL path not explicitly set
18
19
try :
19
20
prepath = os .getenv ('PYSDL2_DLL_PATH' )
20
21
import sdl2dll
21
22
postpath = os .getenv ('PYSDL2_DLL_PATH' )
22
23
if prepath != postpath :
23
- msg = "UserWarning: Using SDL2 binaries from pysdl2-dll {0}"
24
+ msg = "Using SDL2 binaries from pysdl2-dll {0}"
24
25
prettywarn (msg .format (sdl2dll .__version__ ), UserWarning )
25
26
except ImportError :
26
27
pass
@@ -36,6 +37,48 @@ class SDL_version(Structure):
36
37
]
37
38
38
39
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
+
39
82
def _findlib (libnames , path = None ):
40
83
"""Finds SDL2 libraries and returns them in a list, with libraries found in the directory
41
84
optionally specified by 'path' being first (taking precedence) and libraries found in system
@@ -98,6 +141,7 @@ class DLL(object):
98
141
"""
99
142
def __init__ (self , libinfo , libnames , path = None ):
100
143
self ._dll = None
144
+ self ._deps = None
101
145
self ._libname = libinfo
102
146
self ._version = None
103
147
minversions = {
@@ -133,6 +177,8 @@ def __init__(self, libinfo, libnames, path=None):
133
177
if self ._dll is None :
134
178
raise RuntimeError ("found %s, but it's not usable for the library %s" %
135
179
(foundlibs , libinfo ))
180
+ if _using_ms_store_python ():
181
+ self ._deps = _preload_deps (libinfo , self ._libfile )
136
182
if path is not None and sys .platform in ("win32" ,) and \
137
183
path in self ._libfile :
138
184
os .environ ["PATH" ] = "%s;%s" % (path , os .environ ["PATH" ])
0 commit comments