pyglet 2.1.dev2__py3-none-any.whl → 2.1.dev3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyglet/__init__.py +317 -219
- pyglet/__init__.pyi +22 -6
- pyglet/app/__init__.py +6 -8
- pyglet/app/base.py +86 -88
- pyglet/clock.py +93 -117
- pyglet/display/__init__.py +24 -29
- pyglet/display/base.py +44 -100
- pyglet/event.py +105 -98
- pyglet/experimental/hidraw.py +28 -87
- pyglet/experimental/particles.py +389 -0
- pyglet/extlibs/earcut.py +714 -0
- pyglet/font/__init__.py +54 -41
- pyglet/font/base.py +147 -133
- pyglet/font/directwrite.py +654 -597
- pyglet/font/fontconfig.py +109 -91
- pyglet/font/freetype.py +102 -71
- pyglet/font/freetype_lib.py +346 -306
- pyglet/font/quartz.py +42 -36
- pyglet/font/ttf.py +238 -239
- pyglet/font/user.py +166 -57
- pyglet/font/win32.py +32 -36
- pyglet/gl/base.py +131 -192
- pyglet/gl/wgl.py +175 -199
- pyglet/graphics/__init__.py +9 -2
- pyglet/graphics/shader.py +4 -1
- pyglet/graphics/vertexdomain.py +2 -4
- pyglet/gui/__init__.py +1 -0
- pyglet/gui/frame.py +68 -38
- pyglet/gui/ninepatch.py +269 -0
- pyglet/gui/widgets.py +137 -129
- pyglet/image/__init__.py +48 -10
- pyglet/image/animation.py +38 -77
- pyglet/image/atlas.py +74 -110
- pyglet/image/buffer.py +91 -50
- pyglet/input/__init__.py +27 -38
- pyglet/input/base.py +379 -427
- pyglet/input/controller.py +33 -37
- pyglet/input/linux/evdev.py +12 -64
- pyglet/input/win32/__init__.py +4 -4
- pyglet/input/win32/wintab.py +8 -10
- pyglet/libs/__init__.py +18 -0
- pyglet/libs/darwin/cocoapy/runtime.py +262 -31
- pyglet/libs/darwin/coreaudio.py +86 -19
- pyglet/libs/darwin/quartzkey.py +32 -13
- pyglet/libs/ioctl.py +129 -0
- pyglet/libs/x11/xlib.py +1480 -947
- pyglet/math.py +64 -65
- pyglet/media/__init__.py +22 -17
- pyglet/media/codecs/__init__.py +4 -1
- pyglet/media/player.py +34 -67
- pyglet/media/player_worker_thread.py +31 -21
- pyglet/media/synthesis.py +105 -81
- pyglet/model/__init__.py +106 -58
- pyglet/model/codecs/__init__.py +12 -3
- pyglet/resource.py +295 -363
- pyglet/shapes.py +892 -498
- pyglet/sprite.py +255 -260
- pyglet/text/__init__.py +218 -244
- pyglet/text/caret.py +45 -92
- pyglet/text/document.py +216 -210
- pyglet/text/formats/__init__.py +1 -4
- pyglet/text/formats/attributed.py +32 -29
- pyglet/text/formats/html.py +165 -165
- pyglet/text/formats/plaintext.py +10 -4
- pyglet/text/formats/structured.py +97 -85
- pyglet/text/layout/__init__.py +28 -16
- pyglet/text/layout/base.py +372 -383
- pyglet/text/layout/incremental.py +189 -258
- pyglet/text/layout/scrolling.py +77 -60
- pyglet/text/runlist.py +91 -84
- pyglet/window/__init__.py +440 -580
- pyglet/window/cocoa/__init__.py +66 -68
- pyglet/window/cocoa/pyglet_delegate.py +49 -36
- pyglet/window/cocoa/pyglet_textview.py +81 -69
- pyglet/window/cocoa/pyglet_view.py +75 -55
- pyglet/window/cocoa/pyglet_window.py +31 -18
- pyglet/window/cocoa/systemcursor.py +4 -2
- pyglet/window/event.py +57 -52
- pyglet/window/headless/__init__.py +39 -31
- pyglet/window/key.py +20 -33
- pyglet/window/mouse.py +48 -34
- pyglet/window/win32/__init__.py +373 -340
- pyglet/window/xlib/__init__.py +256 -221
- {pyglet-2.1.dev2.dist-info → pyglet-2.1.dev3.dist-info}/METADATA +1 -1
- {pyglet-2.1.dev2.dist-info → pyglet-2.1.dev3.dist-info}/RECORD +87 -83
- {pyglet-2.1.dev2.dist-info → pyglet-2.1.dev3.dist-info}/LICENSE +0 -0
- {pyglet-2.1.dev2.dist-info → pyglet-2.1.dev3.dist-info}/WHEEL +0 -0
pyglet/__init__.py
CHANGED
|
@@ -2,25 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
More information is available at http://www.pyglet.org
|
|
4
4
|
"""
|
|
5
|
+
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
import os
|
|
7
8
|
import sys
|
|
8
9
|
|
|
9
|
-
from
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import TYPE_CHECKING, Any, ItemsView
|
|
10
12
|
|
|
11
13
|
#: The release version
|
|
12
|
-
version = '2.1.
|
|
14
|
+
version = '2.1.dev3'
|
|
13
15
|
__version__ = version
|
|
14
16
|
|
|
15
17
|
MIN_PYTHON_VERSION = 3, 8
|
|
16
|
-
MIN_PYTHON_VERSION_STR =
|
|
18
|
+
MIN_PYTHON_VERSION_STR = ".".join([str(v) for v in MIN_PYTHON_VERSION])
|
|
17
19
|
|
|
18
20
|
if sys.version_info < MIN_PYTHON_VERSION:
|
|
19
|
-
|
|
21
|
+
msg = f"pyglet {version} requires Python {MIN_PYTHON_VERSION_STR} or newer."
|
|
22
|
+
raise Exception(msg)
|
|
20
23
|
|
|
21
|
-
if
|
|
22
|
-
|
|
23
|
-
_is_pyglet_doc_run = hasattr(sys, "is_pyglet_doc_run") and sys.is_pyglet_doc_run
|
|
24
|
+
if "sphinx" in sys.modules:
|
|
25
|
+
sys.is_pyglet_doc_run = True
|
|
24
26
|
|
|
25
27
|
# pyglet platform treats *BSD systems as Linux
|
|
26
28
|
compat_platform = sys.platform
|
|
@@ -28,158 +30,253 @@ if "bsd" in compat_platform:
|
|
|
28
30
|
compat_platform = "linux-compat"
|
|
29
31
|
|
|
30
32
|
_enable_optimisations = not __debug__
|
|
31
|
-
if getattr(sys,
|
|
33
|
+
if getattr(sys, "frozen", None):
|
|
32
34
|
_enable_optimisations = True
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
'
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class Options:
|
|
39
|
+
"""Dataclass for global pyglet options."""
|
|
40
|
+
|
|
41
|
+
audio: tuple[str] = ("xaudio2", "directsound", "openal", "pulse", "silent")
|
|
42
|
+
"""A :py:class:`~typing.Sequence` of valid audio modules names. They will
|
|
43
|
+
be tried from first to last until either a driver loads or no entries
|
|
44
|
+
remain. See :ref:`guide-audio-driver-order` for more information.
|
|
45
|
+
|
|
46
|
+
Valid driver names are:
|
|
47
|
+
|
|
48
|
+
* ``'xaudio2'``, the Windows Xaudio2 audio module (Windows only)
|
|
49
|
+
* ``'directsound'``, the Windows DirectSound audio module (Windows only)
|
|
50
|
+
* ``'pulse'``, the :ref:`guide-audio-driver-pulseaudio` module
|
|
51
|
+
(Linux only, otherwise nearly ubiquitous. Limited features; use
|
|
52
|
+
``'openal'`` for more.)
|
|
53
|
+
* ``'openal'``, the :ref:`guide-audio-driver-openal` audio module
|
|
54
|
+
(A library may need to be installed on Windows and Linux)
|
|
55
|
+
* ``'silent'``, no audio"""
|
|
56
|
+
|
|
57
|
+
debug_font: bool = False
|
|
58
|
+
"""If ``True``, will print more verbose information when :py:class:`~pyglet.font.base.Font`'s are loaded."""
|
|
59
|
+
|
|
60
|
+
debug_gl: bool = True
|
|
61
|
+
"""If ``True``, all calls to OpenGL functions are checked afterwards for
|
|
62
|
+
errors using ``glGetError``. This will severely impact performance,
|
|
63
|
+
but provides useful exceptions at the point of failure. By default,
|
|
64
|
+
this option is enabled if ``__debug__`` is enabled (i.e., if Python was not run
|
|
65
|
+
with the -O option). It is disabled by default when pyglet is "frozen", such as
|
|
66
|
+
within pyinstaller or nuitka."""
|
|
67
|
+
|
|
68
|
+
debug_gl_trace: bool = False
|
|
69
|
+
"""If ``True``, will print the names of OpenGL calls being executed. For example, ``glBlendFunc``"""
|
|
70
|
+
|
|
71
|
+
debug_gl_trace_args: bool = False
|
|
72
|
+
"""If ``True``, in addition to printing the names of OpenGL calls, it will also print the arguments passed
|
|
73
|
+
into those calls. For example, ``glBlendFunc(770, 771)``
|
|
74
|
+
|
|
75
|
+
.. note:: Requires ``debug_gl_trace`` to be enabled."""
|
|
76
|
+
|
|
77
|
+
debug_gl_shaders: bool = False
|
|
78
|
+
"""If ``True``, prints shader compilation information such as creation and deletion of shader's. Also includes
|
|
79
|
+
information on shader ID's, attributes, and uniforms."""
|
|
80
|
+
|
|
81
|
+
debug_graphics_batch: bool = False
|
|
82
|
+
"""If ``True``, prints batch information being drawn, including :py:class:`~pyglet.graphics.Group`'s, VertexDomains,
|
|
83
|
+
and :py:class:`~pyglet.image.Texture` information. This can be useful to see how many Group's are being
|
|
84
|
+
consolidated."""
|
|
85
|
+
|
|
86
|
+
debug_lib: bool = False
|
|
87
|
+
"""If ``True``, prints the path of each dynamic library loaded."""
|
|
88
|
+
|
|
89
|
+
debug_media: bool = False
|
|
90
|
+
"""If ``True``, prints more detailed media information for audio codecs and drivers. Will be very verbose."""
|
|
91
|
+
|
|
92
|
+
debug_texture: bool = False
|
|
93
|
+
"""If ``True``, prints information on :py:class:`~pyglet.image.Texture` size (in bytes) when they are allocated and
|
|
94
|
+
deleted."""
|
|
95
|
+
|
|
96
|
+
debug_trace: bool = False
|
|
97
|
+
debug_trace_args: bool = False
|
|
98
|
+
debug_trace_depth: int = 1
|
|
99
|
+
debug_trace_flush: bool = True
|
|
100
|
+
|
|
101
|
+
debug_win32: bool = False
|
|
102
|
+
"""If ``True``, prints error messages related to Windows library calls. Usually get's information from
|
|
103
|
+
``Kernel32.GetLastError``. This information is output to a file called ``debug_win32.log``."""
|
|
104
|
+
|
|
105
|
+
debug_input: bool = False
|
|
106
|
+
"""If ``True``, prints information on input devices such as controllers, tablets, and more."""
|
|
107
|
+
|
|
108
|
+
debug_x11: bool = False
|
|
109
|
+
"""If ``True``, prints information related to Linux X11 calls. This can potentially help narrow down driver or
|
|
110
|
+
operating system issues."""
|
|
111
|
+
|
|
112
|
+
shadow_window: bool = True
|
|
113
|
+
"""By default, pyglet creates a hidden window with a GL context when
|
|
114
|
+
pyglet.gl is imported. This allows resources to be loaded before
|
|
115
|
+
the application window is created, and permits GL objects to be
|
|
116
|
+
shared between windows even after they've been closed. You can
|
|
117
|
+
disable the creation of the shadow window by setting this option to
|
|
118
|
+
False.
|
|
119
|
+
|
|
120
|
+
Some OpenGL driver implementations may not support shared OpenGL
|
|
121
|
+
contexts and may require disabling the shadow window (and all resources
|
|
122
|
+
must be loaded after the window using them was created). Recommended
|
|
123
|
+
for advanced developers only.
|
|
124
|
+
|
|
125
|
+
.. versionadded:: 1.1"""
|
|
126
|
+
|
|
127
|
+
vsync: bool | None = None
|
|
128
|
+
"""If set to ``True`` or ``False``, this option takes overrides the
|
|
129
|
+
``vsync`` argument passed to :py:class:`~pyglet.window.Window`. This
|
|
130
|
+
allows forcing vsync on or off. If set to None (the default), the
|
|
131
|
+
as documented.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
xsync: bool = True
|
|
135
|
+
"""If ``True`` (the default), pyglet will attempt to synchronise the
|
|
136
|
+
drawing of double-buffered windows to the border updates of the X11
|
|
137
|
+
window manager. This improves the appearance of the window during
|
|
138
|
+
resize operations. This option only affects double-buffered windows on
|
|
139
|
+
X11 servers supporting the Xsync extension with a window manager that
|
|
140
|
+
implements the _NET_WM_SYNC_REQUEST protocol.
|
|
141
|
+
|
|
142
|
+
.. versionadded:: 1.1
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
xlib_fullscreen_override_redirect: bool = False
|
|
146
|
+
"""If ``True``, pass the xlib.CWOverrideRedirect flag when creating a fullscreen window.
|
|
147
|
+
This option is generally not necessary anymore and is considered deprecated.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
search_local_libs: bool = True
|
|
151
|
+
"""If ``False``, pyglet won't try to search for libraries in the script
|
|
152
|
+
directory and its ``lib`` subdirectory. This is useful to load a local
|
|
153
|
+
library instead of the system installed version."""
|
|
154
|
+
|
|
155
|
+
win32_gdi_font: bool = False
|
|
156
|
+
"""If ``True``, pyglet will fallback to the legacy ``GDIPlus`` font renderer for Windows. This may provide
|
|
157
|
+
better font compatibility for older fonts. The legacy renderer does not support shaping, colored fonts,
|
|
158
|
+
substitutions, or other OpenType features. It may also have issues with certain languages.
|
|
159
|
+
|
|
160
|
+
Due to those lack of features, it can potentially be more performant.
|
|
161
|
+
|
|
162
|
+
.. versionadded:: 2.0
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
headless: bool = False
|
|
166
|
+
"""If ``True``, visible Windows are not created and a running desktop environment is not required. This option
|
|
167
|
+
is useful when running pyglet on a headless server, or compute cluster. OpenGL drivers with ``EGL`` support are
|
|
168
|
+
required for this mode.
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
headless_device: int = 0
|
|
172
|
+
"""If using ``headless`` mode (``pyglet.options['headless'] = True``), this option allows you to set which
|
|
173
|
+
GPU to use. This is only useful on multi-GPU systems.
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
win32_disable_shaping: bool = False
|
|
177
|
+
"""If ``True``, will disable the shaping process for the default Windows font renderer to offer a performance
|
|
178
|
+
speed up. If your font is simple, monospaced, or you require no advanced OpenType features, this option may be
|
|
179
|
+
useful. You can try enabling this to see if there is any impact on clarity for your font. The advance will be
|
|
180
|
+
determined by the glyph width.
|
|
181
|
+
|
|
182
|
+
.. note:: Shaping is the process of determining which character glyphs to use and specific placements of those
|
|
183
|
+
glyphs when given a full string of characters.
|
|
184
|
+
|
|
185
|
+
.. versionadded:: 2.0
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
dw_legacy_naming: bool = False
|
|
189
|
+
"""If ``True``, will enable legacy naming support for the default Windows font renderer (``DirectWrite``).
|
|
190
|
+
Attempt to parse fonts by the passed name, to best match legacy RBIZ naming.
|
|
191
|
+
|
|
192
|
+
:see: https://learn.microsoft.com/en-us/windows/win32/directwrite/font-selection#rbiz-font-family-model
|
|
193
|
+
|
|
194
|
+
For example, this allows specifying ``"Arial Narrow"`` rather than ``"Arial"`` with a ``"condensed"`` stretch or
|
|
195
|
+
``"Arial Black"`` instead of ``"Arial"`` with a weight of ``black``. This may enhance naming compatibility
|
|
196
|
+
cross-platform for select fonts as older font renderers went by this naming scheme.
|
|
197
|
+
|
|
198
|
+
Starts by parsing the string for any known style names, and searches all font collections for a matching RBIZ name.
|
|
199
|
+
If a perfect match is not found, it will choose a second best match.
|
|
200
|
+
|
|
201
|
+
.. note:: Due to the high variation of styles and limited capability of some fonts, there is no guarantee the
|
|
202
|
+
second closest match will be exactly what the user wants.
|
|
203
|
+
|
|
204
|
+
.. note:: The ``debug_font`` option can provide information on what settings are being selected.
|
|
205
|
+
|
|
206
|
+
.. versionadded:: 2.0.3
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
win32_disable_xinput: bool = False
|
|
210
|
+
"""If ``True``, this will disable the ``XInput`` controller usage in Windows and fallback to ``DirectInput``. Can
|
|
211
|
+
be useful for debugging or special uses cases. A controller can only be controlled by either ``XInput`` or
|
|
212
|
+
``DirectInput``, not both.
|
|
213
|
+
|
|
214
|
+
.. versionadded:: 2.0
|
|
215
|
+
"""
|
|
216
|
+
|
|
217
|
+
com_mta: bool = False
|
|
218
|
+
"""If ``True``, this will enforce COM Multithreaded Apartment Mode for Windows applications. By default, pyglet
|
|
219
|
+
has opted to go for Single-Threaded Apartment (STA) for compatibility reasons. Many other third party libraries
|
|
220
|
+
used with Python explicitly set STA. However, Windows recommends MTA with a lot of their API's such as Windows
|
|
221
|
+
Media Foundation (WMF).
|
|
222
|
+
|
|
223
|
+
:see: https://learn.microsoft.com/en-us/windows/win32/cossdk/com--threading-models
|
|
224
|
+
|
|
225
|
+
.. versionadded:: 2.0.5
|
|
226
|
+
"""
|
|
227
|
+
|
|
228
|
+
osx_alt_loop: bool = False
|
|
229
|
+
"""If ``True``, this will enable an alternative loop for Mac OSX. This is enforced for all ARM64 architecture Mac's.
|
|
230
|
+
|
|
231
|
+
Due to various issues with the ctypes interface with Objective C, Python, and Mac ARM64 processors, the standard
|
|
232
|
+
event loop eventually starts breaking down to where inputs are either missed or delayed. Even on Intel based Mac's
|
|
233
|
+
other odd behavior can be seen with the standard event loop such as randomly crashing from events.
|
|
234
|
+
|
|
235
|
+
.. versionadded:: 2.0.5"""
|
|
236
|
+
|
|
237
|
+
scale_with_dpi: bool = False
|
|
238
|
+
"""For 'HiDPI' ('Retina') displays, scale Window creation size with desktop scaling. Defaults to ``False``.
|
|
239
|
+
|
|
240
|
+
For high pixel density displays, it is common for the desktop to have some form of application window scaling.
|
|
241
|
+
Setting this option to ``True`` will make pyglet aware of these settings when Windows are created. For instance,
|
|
242
|
+
if the desktop scaling factor is set to 150%, a Window created with a resolution of 1000x1000 will have an actual
|
|
243
|
+
framebuffer size of 1500x1500. Keep in mind that pyglet objects may not be scaled proportionately, so this is left
|
|
244
|
+
up to the developer. The :py:attr:`~pyglet.window.Window.scale` & :py:attr:`~pyglet.window.Window.dpi` attributes
|
|
245
|
+
can be queried as a reference when determining object creation. By default, windows are created with the actual
|
|
246
|
+
number of pixels requested.
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
def get(self, item: str, default: Any = None) -> Any:
|
|
250
|
+
return self.__dict__.get(item, default)
|
|
251
|
+
|
|
252
|
+
def items(self) -> ItemsView[str, Any]:
|
|
253
|
+
return self.__dict__.items()
|
|
254
|
+
|
|
255
|
+
def __getitem__(self, item: str) -> Any:
|
|
256
|
+
return self.__dict__[item]
|
|
257
|
+
|
|
258
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
259
|
+
assert key in self.__annotations__, f"Invalid option name: '{key}'"
|
|
260
|
+
assert type(value).__name__ == self.__annotations__[key], f"Invalid type: '{type(value)}' for '{key}'"
|
|
261
|
+
self.__dict__[key] = value
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
#: Instance of :py:class:`~pyglet.Options` used to set runtime options.
|
|
265
|
+
options = Options()
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
for _key, _type in options.__annotations__.items():
|
|
170
269
|
"""Check Environment Variables for pyglet options"""
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
options[_key] = _value
|
|
176
|
-
elif
|
|
177
|
-
options[_key] = _value in ('true', 'TRUE', 'True', '1')
|
|
178
|
-
elif _option_types[_key] is int:
|
|
270
|
+
if _value := os.environ.get(f"PYGLET_{_key.upper()}"):
|
|
271
|
+
if _type == 'tuple':
|
|
272
|
+
options[_key] = _value.split(",")
|
|
273
|
+
elif _type == 'bool':
|
|
274
|
+
options[_key] = _value in ("true", "TRUE", "True", "1")
|
|
275
|
+
elif _type == 'int':
|
|
179
276
|
options[_key] = int(_value)
|
|
180
277
|
|
|
181
278
|
|
|
182
|
-
if compat_platform ==
|
|
279
|
+
if compat_platform == "cygwin":
|
|
183
280
|
# This hack pretends that the posix-like ctypes provides windows
|
|
184
281
|
# functionality. COM does not work with this hack, so there is no
|
|
185
282
|
# DirectSound support.
|
|
@@ -193,27 +290,26 @@ if compat_platform == 'cygwin':
|
|
|
193
290
|
# Call tracing
|
|
194
291
|
# ------------
|
|
195
292
|
|
|
196
|
-
_trace_filename_abbreviations:
|
|
293
|
+
_trace_filename_abbreviations: dict[str, str] = {}
|
|
197
294
|
_trace_thread_count = 0
|
|
198
|
-
_trace_args = options[
|
|
199
|
-
_trace_depth = options[
|
|
200
|
-
_trace_flush = options[
|
|
295
|
+
_trace_args = options["debug_trace_args"]
|
|
296
|
+
_trace_depth = options["debug_trace_depth"]
|
|
297
|
+
_trace_flush = options["debug_trace_flush"]
|
|
201
298
|
|
|
202
299
|
|
|
203
300
|
def _trace_repr(value, size=40):
|
|
204
301
|
value = repr(value)
|
|
205
302
|
if len(value) > size:
|
|
206
|
-
value = value[:size // 2 - 2] +
|
|
303
|
+
value = value[:size // 2 - 2] + "..." + value[-size // 2 - 1:]
|
|
207
304
|
return value
|
|
208
305
|
|
|
209
306
|
|
|
210
307
|
def _trace_frame(thread, frame, indent):
|
|
211
|
-
|
|
212
308
|
if frame.f_code is lib._TraceFunction.__call__.__code__:
|
|
213
309
|
is_ctypes = True
|
|
214
|
-
func = frame.f_locals[
|
|
310
|
+
func = frame.f_locals["self"]._func
|
|
215
311
|
name = func.__name__
|
|
216
|
-
location =
|
|
312
|
+
location = "[ctypes]"
|
|
217
313
|
else:
|
|
218
314
|
is_ctypes = False
|
|
219
315
|
code = frame.f_code
|
|
@@ -225,7 +321,7 @@ def _trace_frame(thread, frame, indent):
|
|
|
225
321
|
filename = _trace_filename_abbreviations[path]
|
|
226
322
|
except KeyError:
|
|
227
323
|
# Trim path down
|
|
228
|
-
directory =
|
|
324
|
+
directory = ""
|
|
229
325
|
path, filename = os.path.split(path)
|
|
230
326
|
|
|
231
327
|
while len(directory + filename) < 30:
|
|
@@ -234,24 +330,24 @@ def _trace_frame(thread, frame, indent):
|
|
|
234
330
|
if not directory:
|
|
235
331
|
break
|
|
236
332
|
else:
|
|
237
|
-
filename = os.path.join(
|
|
333
|
+
filename = os.path.join("...", filename)
|
|
238
334
|
_trace_filename_abbreviations[path] = filename
|
|
239
335
|
|
|
240
|
-
location = f
|
|
336
|
+
location = f"({filename}:{line})"
|
|
241
337
|
|
|
242
338
|
if indent:
|
|
243
|
-
name = f
|
|
244
|
-
print(f
|
|
339
|
+
name = f"Called from {name}"
|
|
340
|
+
print(f"[{thread}] {indent}{name} {location}")
|
|
245
341
|
|
|
246
342
|
if _trace_args:
|
|
247
343
|
if is_ctypes:
|
|
248
|
-
args = [_trace_repr(arg) for arg in frame.f_locals[
|
|
344
|
+
args = [_trace_repr(arg) for arg in frame.f_locals["args"]]
|
|
249
345
|
print(f' {indent}args=({", ".join(args)})')
|
|
250
346
|
else:
|
|
251
347
|
for argname in code.co_varnames[:code.co_argcount]:
|
|
252
348
|
try:
|
|
253
349
|
argvalue = _trace_repr(frame.f_locals[argname])
|
|
254
|
-
print(f
|
|
350
|
+
print(f" {indent}{argname}={argvalue}")
|
|
255
351
|
except:
|
|
256
352
|
pass
|
|
257
353
|
|
|
@@ -261,18 +357,18 @@ def _trace_frame(thread, frame, indent):
|
|
|
261
357
|
|
|
262
358
|
def _thread_trace_func(thread):
|
|
263
359
|
def _trace_func(frame, event, arg):
|
|
264
|
-
if event ==
|
|
265
|
-
indent =
|
|
360
|
+
if event == "call":
|
|
361
|
+
indent = ""
|
|
266
362
|
for i in range(_trace_depth):
|
|
267
363
|
_trace_frame(thread, frame, indent)
|
|
268
|
-
indent +=
|
|
364
|
+
indent += " "
|
|
269
365
|
frame = frame.f_back
|
|
270
366
|
if not frame:
|
|
271
367
|
break
|
|
272
368
|
|
|
273
|
-
elif event ==
|
|
369
|
+
elif event == "exception":
|
|
274
370
|
(exception, value, traceback) = arg
|
|
275
|
-
print(
|
|
371
|
+
print("First chance exception raised:", repr(exception))
|
|
276
372
|
|
|
277
373
|
return _trace_func
|
|
278
374
|
|
|
@@ -290,7 +386,7 @@ class _ModuleProxy:
|
|
|
290
386
|
_module = None
|
|
291
387
|
|
|
292
388
|
def __init__(self, name: str):
|
|
293
|
-
self.__dict__[
|
|
389
|
+
self.__dict__["_module_name"] = name
|
|
294
390
|
|
|
295
391
|
def __getattr__(self, name):
|
|
296
392
|
try:
|
|
@@ -299,10 +395,10 @@ class _ModuleProxy:
|
|
|
299
395
|
if self._module is not None:
|
|
300
396
|
raise
|
|
301
397
|
|
|
302
|
-
import_name = f
|
|
398
|
+
import_name = f"pyglet.{self._module_name}"
|
|
303
399
|
__import__(import_name)
|
|
304
400
|
module = sys.modules[import_name]
|
|
305
|
-
object.__setattr__(self,
|
|
401
|
+
object.__setattr__(self, "_module", module)
|
|
306
402
|
globals()[self._module_name] = module
|
|
307
403
|
return getattr(module, name)
|
|
308
404
|
|
|
@@ -313,58 +409,60 @@ class _ModuleProxy:
|
|
|
313
409
|
if self._module is not None:
|
|
314
410
|
raise
|
|
315
411
|
|
|
316
|
-
import_name = f
|
|
412
|
+
import_name = f"pyglet.{self._module_name}"
|
|
317
413
|
__import__(import_name)
|
|
318
414
|
module = sys.modules[import_name]
|
|
319
|
-
object.__setattr__(self,
|
|
415
|
+
object.__setattr__(self, "_module", module)
|
|
320
416
|
globals()[self._module_name] = module
|
|
321
417
|
setattr(module, name, value)
|
|
322
418
|
|
|
323
419
|
|
|
324
420
|
# Lazily load all modules, except if performing type checking or code inspection.
|
|
325
421
|
if TYPE_CHECKING:
|
|
326
|
-
from . import
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
422
|
+
from . import (
|
|
423
|
+
app,
|
|
424
|
+
clock,
|
|
425
|
+
customtypes,
|
|
426
|
+
display,
|
|
427
|
+
event,
|
|
428
|
+
font,
|
|
429
|
+
gl,
|
|
430
|
+
graphics,
|
|
431
|
+
gui,
|
|
432
|
+
image,
|
|
433
|
+
input,
|
|
434
|
+
lib,
|
|
435
|
+
math,
|
|
436
|
+
media,
|
|
437
|
+
model,
|
|
438
|
+
resource,
|
|
439
|
+
shapes,
|
|
440
|
+
sprite,
|
|
441
|
+
text,
|
|
442
|
+
window,
|
|
443
|
+
)
|
|
346
444
|
else:
|
|
347
|
-
app = _ModuleProxy(
|
|
348
|
-
clock = _ModuleProxy(
|
|
349
|
-
customtypes = _ModuleProxy(
|
|
350
|
-
display = _ModuleProxy(
|
|
351
|
-
event = _ModuleProxy(
|
|
352
|
-
font = _ModuleProxy(
|
|
353
|
-
gl = _ModuleProxy(
|
|
354
|
-
graphics = _ModuleProxy(
|
|
355
|
-
gui = _ModuleProxy(
|
|
356
|
-
image = _ModuleProxy(
|
|
357
|
-
input = _ModuleProxy(
|
|
358
|
-
lib = _ModuleProxy(
|
|
359
|
-
math = _ModuleProxy(
|
|
360
|
-
media = _ModuleProxy(
|
|
361
|
-
model = _ModuleProxy(
|
|
362
|
-
resource = _ModuleProxy(
|
|
363
|
-
sprite = _ModuleProxy(
|
|
364
|
-
shapes = _ModuleProxy(
|
|
365
|
-
text = _ModuleProxy(
|
|
366
|
-
window = _ModuleProxy(
|
|
445
|
+
app = _ModuleProxy("app") # type: ignore
|
|
446
|
+
clock = _ModuleProxy("clock") # type: ignore
|
|
447
|
+
customtypes = _ModuleProxy("customtypes") # type: ignore
|
|
448
|
+
display = _ModuleProxy("display") # type: ignore
|
|
449
|
+
event = _ModuleProxy("event") # type: ignore
|
|
450
|
+
font = _ModuleProxy("font") # type: ignore
|
|
451
|
+
gl = _ModuleProxy("gl") # type: ignore
|
|
452
|
+
graphics = _ModuleProxy("graphics") # type: ignore
|
|
453
|
+
gui = _ModuleProxy("gui") # type: ignore
|
|
454
|
+
image = _ModuleProxy("image") # type: ignore
|
|
455
|
+
input = _ModuleProxy("input") # type: ignore
|
|
456
|
+
lib = _ModuleProxy("lib") # type: ignore
|
|
457
|
+
math = _ModuleProxy("math") # type: ignore
|
|
458
|
+
media = _ModuleProxy("media") # type: ignore
|
|
459
|
+
model = _ModuleProxy("model") # type: ignore
|
|
460
|
+
resource = _ModuleProxy("resource") # type: ignore
|
|
461
|
+
sprite = _ModuleProxy("sprite") # type: ignore
|
|
462
|
+
shapes = _ModuleProxy("shapes") # type: ignore
|
|
463
|
+
text = _ModuleProxy("text") # type: ignore
|
|
464
|
+
window = _ModuleProxy("window") # type: ignore
|
|
367
465
|
|
|
368
466
|
# Call after creating proxies:
|
|
369
|
-
if options
|
|
467
|
+
if options.debug_trace is True:
|
|
370
468
|
_install_trace()
|