diff --git a/buildconfig/stubs/gen_stubs.py b/buildconfig/stubs/gen_stubs.py index 488ba2cfc7..23500cb4b1 100644 --- a/buildconfig/stubs/gen_stubs.py +++ b/buildconfig/stubs/gen_stubs.py @@ -1,6 +1,6 @@ """ buildconfig/stubs/gen_stubs.py -A script to auto-generate locals.pyi, constants.pyi and __init__.pyi typestubs +A script to auto-generate locals.pyi, constants.pyi, debug.pyi and __init__.pyi typestubs """ import pathlib @@ -106,6 +106,7 @@ def get_all(mod: Any): except KeyError: pygame_all_imports[f".{k}"] = val + # misc stubs that must be added to __init__.pyi misc_stubs = """""" @@ -144,6 +145,11 @@ def get_all(mod: Any): f.write(f" {item} as {item},\n") f.write(")\n") +# write debug.pyi file +debug_file = pathlib.Path(__file__).parent / "pygame" / "debug.pyi" +with open(init_file, "r") as i, open(debug_file, "w") as f: + f.write(i.read()) + # write locals.pyi file locals_file = pathlib.Path(__file__).parent / "pygame" / "locals.pyi" with open(locals_file, "w") as f: diff --git a/buildconfig/stubs/pygame/__init__.pyi b/buildconfig/stubs/pygame/__init__.pyi index a8ecdd7f25..2f8b8a7e1a 100644 --- a/buildconfig/stubs/pygame/__init__.pyi +++ b/buildconfig/stubs/pygame/__init__.pyi @@ -1,5 +1,5 @@ # buildconfig/stubs/gen_stubs.py -# A script to auto-generate locals.pyi, constants.pyi and __init__.pyi typestubs +# A script to auto-generate locals.pyi, constants.pyi, debug.pyi and __init__.pyi typestubs # IMPORTANT NOTE: Do not edit this file by hand! from pygame import ( @@ -66,10 +66,13 @@ from .base import ( get_init as get_init, get_sdl_byteorder as get_sdl_byteorder, get_sdl_version as get_sdl_version, + get_warnings_filter as get_warnings_filter, init as init, quit as quit, register_quit as register_quit, set_error as set_error, + set_warnings_filter as set_warnings_filter, + warn as warn, ) from .rwobject import ( diff --git a/buildconfig/stubs/pygame/base.pyi b/buildconfig/stubs/pygame/base.pyi index 4aa5d42149..d70f8d0f85 100644 --- a/buildconfig/stubs/pygame/base.pyi +++ b/buildconfig/stubs/pygame/base.pyi @@ -1,4 +1,4 @@ -from typing import Any, Tuple, Callable +from typing import Any, Tuple, Callable, Type __version__: str @@ -19,3 +19,6 @@ def register_quit(callable: Callable[[], Any], /) -> None: ... # undocumented part of pygame API, kept here to make stubtest happy def get_array_interface(arg: Any, /) -> dict: ... +def warn(message: str, urgency: int, level: int = 1, category: Type[Warning] = UserWarning): ... +def get_warnings_filter() -> int: ... +def set_warnings_filter(val: int, /): ... diff --git a/buildconfig/stubs/pygame/constants.pyi b/buildconfig/stubs/pygame/constants.pyi index 3d793e3c50..4bb1790326 100644 --- a/buildconfig/stubs/pygame/constants.pyi +++ b/buildconfig/stubs/pygame/constants.pyi @@ -1,5 +1,5 @@ # buildconfig/stubs/gen_stubs.py -# A script to auto-generate locals.pyi, constants.pyi and __init__.pyi typestubs +# A script to auto-generate locals.pyi, constants.pyi, debug.pyi and __init__.pyi typestubs # IMPORTANT NOTE: Do not edit this file by hand! ACTIVEEVENT: int diff --git a/buildconfig/stubs/pygame/debug.pyi b/buildconfig/stubs/pygame/debug.pyi new file mode 100644 index 0000000000..2f8b8a7e1a --- /dev/null +++ b/buildconfig/stubs/pygame/debug.pyi @@ -0,0 +1,655 @@ +# buildconfig/stubs/gen_stubs.py +# A script to auto-generate locals.pyi, constants.pyi, debug.pyi and __init__.pyi typestubs +# IMPORTANT NOTE: Do not edit this file by hand! + +from pygame import ( + display as display, + draw as draw, + event as event, + font as font, + image as image, + key as key, + mixer as mixer, + mouse as mouse, + time as time, + cursors as cursors, + joystick as joystick, + math as math, + mask as mask, + pixelcopy as pixelcopy, + sndarray as sndarray, + sprite as sprite, + surfarray as surfarray, + transform as transform, + scrap as scrap, + version as version, + base as base, + bufferproxy as bufferproxy, + color as color, + colordict as colordict, + mixer_music as mixer_music, + pixelarray as pixelarray, + rect as rect, + rwobject as rwobject, + surface as surface, + surflock as surflock, + sysfont as sysfont, + _debug as _debug, + system as system, + geometry as geometry, + window as window, + typing as typing, +) + +from .rect import Rect as Rect, FRect as FRect +from .surface import Surface as Surface, SurfaceType as SurfaceType +from .color import Color as Color +from .pixelarray import PixelArray as PixelArray +from .math import Vector2 as Vector2, Vector3 as Vector3 +from .cursors import Cursor as Cursor +from .bufferproxy import BufferProxy as BufferProxy +from .mask import Mask as Mask +from ._debug import print_debug_info as print_debug_info +from .event import Event as Event +from .font import Font as Font +from .mixer import Sound as Sound, Channel as Channel +from .time import Clock as Clock +from .joystick import Joystick as Joystick +from .window import Window as Window +from .base import ( + __version__ as __version__, + BufferError as BufferError, + HAVE_NEWBUF as HAVE_NEWBUF, + error as error, + get_array_interface as get_array_interface, + get_error as get_error, + get_init as get_init, + get_sdl_byteorder as get_sdl_byteorder, + get_sdl_version as get_sdl_version, + get_warnings_filter as get_warnings_filter, + init as init, + quit as quit, + register_quit as register_quit, + set_error as set_error, + set_warnings_filter as set_warnings_filter, + warn as warn, +) + +from .rwobject import ( + encode_file_path as encode_file_path, + encode_string as encode_string, +) + +from .version import SDL as SDL, rev as rev, ver as ver, vernum as vernum +from .constants import ( + ACTIVEEVENT as ACTIVEEVENT, + ANYFORMAT as ANYFORMAT, + APPACTIVE as APPACTIVE, + APPINPUTFOCUS as APPINPUTFOCUS, + APPMOUSEFOCUS as APPMOUSEFOCUS, + APP_DIDENTERBACKGROUND as APP_DIDENTERBACKGROUND, + APP_DIDENTERFOREGROUND as APP_DIDENTERFOREGROUND, + APP_LOWMEMORY as APP_LOWMEMORY, + APP_TERMINATING as APP_TERMINATING, + APP_WILLENTERBACKGROUND as APP_WILLENTERBACKGROUND, + APP_WILLENTERFOREGROUND as APP_WILLENTERFOREGROUND, + ASYNCBLIT as ASYNCBLIT, + AUDIODEVICEADDED as AUDIODEVICEADDED, + AUDIODEVICEREMOVED as AUDIODEVICEREMOVED, + AUDIO_ALLOW_ANY_CHANGE as AUDIO_ALLOW_ANY_CHANGE, + AUDIO_ALLOW_CHANNELS_CHANGE as AUDIO_ALLOW_CHANNELS_CHANGE, + AUDIO_ALLOW_FORMAT_CHANGE as AUDIO_ALLOW_FORMAT_CHANGE, + AUDIO_ALLOW_FREQUENCY_CHANGE as AUDIO_ALLOW_FREQUENCY_CHANGE, + AUDIO_S16 as AUDIO_S16, + AUDIO_S16LSB as AUDIO_S16LSB, + AUDIO_S16MSB as AUDIO_S16MSB, + AUDIO_S16SYS as AUDIO_S16SYS, + AUDIO_S8 as AUDIO_S8, + AUDIO_U16 as AUDIO_U16, + AUDIO_U16LSB as AUDIO_U16LSB, + AUDIO_U16MSB as AUDIO_U16MSB, + AUDIO_U16SYS as AUDIO_U16SYS, + AUDIO_U8 as AUDIO_U8, + BIG_ENDIAN as BIG_ENDIAN, + BLENDMODE_ADD as BLENDMODE_ADD, + BLENDMODE_BLEND as BLENDMODE_BLEND, + BLENDMODE_MOD as BLENDMODE_MOD, + BLENDMODE_NONE as BLENDMODE_NONE, + BLEND_ADD as BLEND_ADD, + BLEND_ALPHA_SDL2 as BLEND_ALPHA_SDL2, + BLEND_MAX as BLEND_MAX, + BLEND_MIN as BLEND_MIN, + BLEND_MULT as BLEND_MULT, + BLEND_PREMULTIPLIED as BLEND_PREMULTIPLIED, + BLEND_RGBA_ADD as BLEND_RGBA_ADD, + BLEND_RGBA_MAX as BLEND_RGBA_MAX, + BLEND_RGBA_MIN as BLEND_RGBA_MIN, + BLEND_RGBA_MULT as BLEND_RGBA_MULT, + BLEND_RGBA_SUB as BLEND_RGBA_SUB, + BLEND_RGB_ADD as BLEND_RGB_ADD, + BLEND_RGB_MAX as BLEND_RGB_MAX, + BLEND_RGB_MIN as BLEND_RGB_MIN, + BLEND_RGB_MULT as BLEND_RGB_MULT, + BLEND_RGB_SUB as BLEND_RGB_SUB, + BLEND_SUB as BLEND_SUB, + BUTTON_LEFT as BUTTON_LEFT, + BUTTON_MIDDLE as BUTTON_MIDDLE, + BUTTON_RIGHT as BUTTON_RIGHT, + BUTTON_WHEELDOWN as BUTTON_WHEELDOWN, + BUTTON_WHEELUP as BUTTON_WHEELUP, + BUTTON_X1 as BUTTON_X1, + BUTTON_X2 as BUTTON_X2, + CLIPBOARDUPDATE as CLIPBOARDUPDATE, + CONTROLLERAXISMOTION as CONTROLLERAXISMOTION, + CONTROLLERBUTTONDOWN as CONTROLLERBUTTONDOWN, + CONTROLLERBUTTONUP as CONTROLLERBUTTONUP, + CONTROLLERDEVICEADDED as CONTROLLERDEVICEADDED, + CONTROLLERDEVICEREMAPPED as CONTROLLERDEVICEREMAPPED, + CONTROLLERDEVICEREMOVED as CONTROLLERDEVICEREMOVED, + CONTROLLERSENSORUPDATE as CONTROLLERSENSORUPDATE, + CONTROLLERTOUCHPADDOWN as CONTROLLERTOUCHPADDOWN, + CONTROLLERTOUCHPADMOTION as CONTROLLERTOUCHPADMOTION, + CONTROLLERTOUCHPADUP as CONTROLLERTOUCHPADUP, + CONTROLLER_AXIS_INVALID as CONTROLLER_AXIS_INVALID, + CONTROLLER_AXIS_LEFTX as CONTROLLER_AXIS_LEFTX, + CONTROLLER_AXIS_LEFTY as CONTROLLER_AXIS_LEFTY, + CONTROLLER_AXIS_MAX as CONTROLLER_AXIS_MAX, + CONTROLLER_AXIS_RIGHTX as CONTROLLER_AXIS_RIGHTX, + CONTROLLER_AXIS_RIGHTY as CONTROLLER_AXIS_RIGHTY, + CONTROLLER_AXIS_TRIGGERLEFT as CONTROLLER_AXIS_TRIGGERLEFT, + CONTROLLER_AXIS_TRIGGERRIGHT as CONTROLLER_AXIS_TRIGGERRIGHT, + CONTROLLER_BUTTON_A as CONTROLLER_BUTTON_A, + CONTROLLER_BUTTON_B as CONTROLLER_BUTTON_B, + CONTROLLER_BUTTON_BACK as CONTROLLER_BUTTON_BACK, + CONTROLLER_BUTTON_DPAD_DOWN as CONTROLLER_BUTTON_DPAD_DOWN, + CONTROLLER_BUTTON_DPAD_LEFT as CONTROLLER_BUTTON_DPAD_LEFT, + CONTROLLER_BUTTON_DPAD_RIGHT as CONTROLLER_BUTTON_DPAD_RIGHT, + CONTROLLER_BUTTON_DPAD_UP as CONTROLLER_BUTTON_DPAD_UP, + CONTROLLER_BUTTON_GUIDE as CONTROLLER_BUTTON_GUIDE, + CONTROLLER_BUTTON_INVALID as CONTROLLER_BUTTON_INVALID, + CONTROLLER_BUTTON_LEFTSHOULDER as CONTROLLER_BUTTON_LEFTSHOULDER, + CONTROLLER_BUTTON_LEFTSTICK as CONTROLLER_BUTTON_LEFTSTICK, + CONTROLLER_BUTTON_MAX as CONTROLLER_BUTTON_MAX, + CONTROLLER_BUTTON_RIGHTSHOULDER as CONTROLLER_BUTTON_RIGHTSHOULDER, + CONTROLLER_BUTTON_RIGHTSTICK as CONTROLLER_BUTTON_RIGHTSTICK, + CONTROLLER_BUTTON_START as CONTROLLER_BUTTON_START, + CONTROLLER_BUTTON_X as CONTROLLER_BUTTON_X, + CONTROLLER_BUTTON_Y as CONTROLLER_BUTTON_Y, + DIRECTION_BTT as DIRECTION_BTT, + DIRECTION_LTR as DIRECTION_LTR, + DIRECTION_RTL as DIRECTION_RTL, + DIRECTION_TTB as DIRECTION_TTB, + DOUBLEBUF as DOUBLEBUF, + DROPBEGIN as DROPBEGIN, + DROPCOMPLETE as DROPCOMPLETE, + DROPFILE as DROPFILE, + DROPTEXT as DROPTEXT, + FINGERDOWN as FINGERDOWN, + FINGERMOTION as FINGERMOTION, + FINGERUP as FINGERUP, + FLASH_BRIEFLY as FLASH_BRIEFLY, + FLASH_CANCEL as FLASH_CANCEL, + FLASH_UNTIL_FOCUSED as FLASH_UNTIL_FOCUSED, + FONT_CENTER as FONT_CENTER, + FONT_LEFT as FONT_LEFT, + FONT_RIGHT as FONT_RIGHT, + FULLSCREEN as FULLSCREEN, + GL_ACCELERATED_VISUAL as GL_ACCELERATED_VISUAL, + GL_ACCUM_ALPHA_SIZE as GL_ACCUM_ALPHA_SIZE, + GL_ACCUM_BLUE_SIZE as GL_ACCUM_BLUE_SIZE, + GL_ACCUM_GREEN_SIZE as GL_ACCUM_GREEN_SIZE, + GL_ACCUM_RED_SIZE as GL_ACCUM_RED_SIZE, + GL_ALPHA_SIZE as GL_ALPHA_SIZE, + GL_BLUE_SIZE as GL_BLUE_SIZE, + GL_BUFFER_SIZE as GL_BUFFER_SIZE, + GL_CONTEXT_DEBUG_FLAG as GL_CONTEXT_DEBUG_FLAG, + GL_CONTEXT_FLAGS as GL_CONTEXT_FLAGS, + GL_CONTEXT_FORWARD_COMPATIBLE_FLAG as GL_CONTEXT_FORWARD_COMPATIBLE_FLAG, + GL_CONTEXT_MAJOR_VERSION as GL_CONTEXT_MAJOR_VERSION, + GL_CONTEXT_MINOR_VERSION as GL_CONTEXT_MINOR_VERSION, + GL_CONTEXT_PROFILE_COMPATIBILITY as GL_CONTEXT_PROFILE_COMPATIBILITY, + GL_CONTEXT_PROFILE_CORE as GL_CONTEXT_PROFILE_CORE, + GL_CONTEXT_PROFILE_ES as GL_CONTEXT_PROFILE_ES, + GL_CONTEXT_PROFILE_MASK as GL_CONTEXT_PROFILE_MASK, + GL_CONTEXT_RELEASE_BEHAVIOR as GL_CONTEXT_RELEASE_BEHAVIOR, + GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH as GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH, + GL_CONTEXT_RELEASE_BEHAVIOR_NONE as GL_CONTEXT_RELEASE_BEHAVIOR_NONE, + GL_CONTEXT_RESET_ISOLATION_FLAG as GL_CONTEXT_RESET_ISOLATION_FLAG, + GL_CONTEXT_ROBUST_ACCESS_FLAG as GL_CONTEXT_ROBUST_ACCESS_FLAG, + GL_DEPTH_SIZE as GL_DEPTH_SIZE, + GL_DOUBLEBUFFER as GL_DOUBLEBUFFER, + GL_FRAMEBUFFER_SRGB_CAPABLE as GL_FRAMEBUFFER_SRGB_CAPABLE, + GL_GREEN_SIZE as GL_GREEN_SIZE, + GL_MULTISAMPLEBUFFERS as GL_MULTISAMPLEBUFFERS, + GL_MULTISAMPLESAMPLES as GL_MULTISAMPLESAMPLES, + GL_RED_SIZE as GL_RED_SIZE, + GL_SHARE_WITH_CURRENT_CONTEXT as GL_SHARE_WITH_CURRENT_CONTEXT, + GL_STENCIL_SIZE as GL_STENCIL_SIZE, + GL_STEREO as GL_STEREO, + GL_SWAP_CONTROL as GL_SWAP_CONTROL, + HAT_CENTERED as HAT_CENTERED, + HAT_DOWN as HAT_DOWN, + HAT_LEFT as HAT_LEFT, + HAT_LEFTDOWN as HAT_LEFTDOWN, + HAT_LEFTUP as HAT_LEFTUP, + HAT_RIGHT as HAT_RIGHT, + HAT_RIGHTDOWN as HAT_RIGHTDOWN, + HAT_RIGHTUP as HAT_RIGHTUP, + HAT_UP as HAT_UP, + HIDDEN as HIDDEN, + HWACCEL as HWACCEL, + HWPALETTE as HWPALETTE, + HWSURFACE as HWSURFACE, + IS_CE as IS_CE, + JOYAXISMOTION as JOYAXISMOTION, + JOYBALLMOTION as JOYBALLMOTION, + JOYBUTTONDOWN as JOYBUTTONDOWN, + JOYBUTTONUP as JOYBUTTONUP, + JOYDEVICEADDED as JOYDEVICEADDED, + JOYDEVICEREMOVED as JOYDEVICEREMOVED, + JOYHATMOTION as JOYHATMOTION, + KEYDOWN as KEYDOWN, + KEYMAPCHANGED as KEYMAPCHANGED, + KEYUP as KEYUP, + KMOD_ALT as KMOD_ALT, + KMOD_CAPS as KMOD_CAPS, + KMOD_CTRL as KMOD_CTRL, + KMOD_GUI as KMOD_GUI, + KMOD_LALT as KMOD_LALT, + KMOD_LCTRL as KMOD_LCTRL, + KMOD_LGUI as KMOD_LGUI, + KMOD_LMETA as KMOD_LMETA, + KMOD_LSHIFT as KMOD_LSHIFT, + KMOD_META as KMOD_META, + KMOD_MODE as KMOD_MODE, + KMOD_NONE as KMOD_NONE, + KMOD_NUM as KMOD_NUM, + KMOD_RALT as KMOD_RALT, + KMOD_RCTRL as KMOD_RCTRL, + KMOD_RGUI as KMOD_RGUI, + KMOD_RMETA as KMOD_RMETA, + KMOD_RSHIFT as KMOD_RSHIFT, + KMOD_SHIFT as KMOD_SHIFT, + KSCAN_0 as KSCAN_0, + KSCAN_1 as KSCAN_1, + KSCAN_2 as KSCAN_2, + KSCAN_3 as KSCAN_3, + KSCAN_4 as KSCAN_4, + KSCAN_5 as KSCAN_5, + KSCAN_6 as KSCAN_6, + KSCAN_7 as KSCAN_7, + KSCAN_8 as KSCAN_8, + KSCAN_9 as KSCAN_9, + KSCAN_A as KSCAN_A, + KSCAN_AC_BACK as KSCAN_AC_BACK, + KSCAN_APOSTROPHE as KSCAN_APOSTROPHE, + KSCAN_B as KSCAN_B, + KSCAN_BACKSLASH as KSCAN_BACKSLASH, + KSCAN_BACKSPACE as KSCAN_BACKSPACE, + KSCAN_BREAK as KSCAN_BREAK, + KSCAN_C as KSCAN_C, + KSCAN_CAPSLOCK as KSCAN_CAPSLOCK, + KSCAN_CLEAR as KSCAN_CLEAR, + KSCAN_COMMA as KSCAN_COMMA, + KSCAN_CURRENCYSUBUNIT as KSCAN_CURRENCYSUBUNIT, + KSCAN_CURRENCYUNIT as KSCAN_CURRENCYUNIT, + KSCAN_D as KSCAN_D, + KSCAN_DELETE as KSCAN_DELETE, + KSCAN_DOWN as KSCAN_DOWN, + KSCAN_E as KSCAN_E, + KSCAN_END as KSCAN_END, + KSCAN_EQUALS as KSCAN_EQUALS, + KSCAN_ESCAPE as KSCAN_ESCAPE, + KSCAN_EURO as KSCAN_EURO, + KSCAN_F as KSCAN_F, + KSCAN_F1 as KSCAN_F1, + KSCAN_F10 as KSCAN_F10, + KSCAN_F11 as KSCAN_F11, + KSCAN_F12 as KSCAN_F12, + KSCAN_F13 as KSCAN_F13, + KSCAN_F14 as KSCAN_F14, + KSCAN_F15 as KSCAN_F15, + KSCAN_F2 as KSCAN_F2, + KSCAN_F3 as KSCAN_F3, + KSCAN_F4 as KSCAN_F4, + KSCAN_F5 as KSCAN_F5, + KSCAN_F6 as KSCAN_F6, + KSCAN_F7 as KSCAN_F7, + KSCAN_F8 as KSCAN_F8, + KSCAN_F9 as KSCAN_F9, + KSCAN_G as KSCAN_G, + KSCAN_GRAVE as KSCAN_GRAVE, + KSCAN_H as KSCAN_H, + KSCAN_HELP as KSCAN_HELP, + KSCAN_HOME as KSCAN_HOME, + KSCAN_I as KSCAN_I, + KSCAN_INSERT as KSCAN_INSERT, + KSCAN_INTERNATIONAL1 as KSCAN_INTERNATIONAL1, + KSCAN_INTERNATIONAL2 as KSCAN_INTERNATIONAL2, + KSCAN_INTERNATIONAL3 as KSCAN_INTERNATIONAL3, + KSCAN_INTERNATIONAL4 as KSCAN_INTERNATIONAL4, + KSCAN_INTERNATIONAL5 as KSCAN_INTERNATIONAL5, + KSCAN_INTERNATIONAL6 as KSCAN_INTERNATIONAL6, + KSCAN_INTERNATIONAL7 as KSCAN_INTERNATIONAL7, + KSCAN_INTERNATIONAL8 as KSCAN_INTERNATIONAL8, + KSCAN_INTERNATIONAL9 as KSCAN_INTERNATIONAL9, + KSCAN_J as KSCAN_J, + KSCAN_K as KSCAN_K, + KSCAN_KP0 as KSCAN_KP0, + KSCAN_KP1 as KSCAN_KP1, + KSCAN_KP2 as KSCAN_KP2, + KSCAN_KP3 as KSCAN_KP3, + KSCAN_KP4 as KSCAN_KP4, + KSCAN_KP5 as KSCAN_KP5, + KSCAN_KP6 as KSCAN_KP6, + KSCAN_KP7 as KSCAN_KP7, + KSCAN_KP8 as KSCAN_KP8, + KSCAN_KP9 as KSCAN_KP9, + KSCAN_KP_0 as KSCAN_KP_0, + KSCAN_KP_1 as KSCAN_KP_1, + KSCAN_KP_2 as KSCAN_KP_2, + KSCAN_KP_3 as KSCAN_KP_3, + KSCAN_KP_4 as KSCAN_KP_4, + KSCAN_KP_5 as KSCAN_KP_5, + KSCAN_KP_6 as KSCAN_KP_6, + KSCAN_KP_7 as KSCAN_KP_7, + KSCAN_KP_8 as KSCAN_KP_8, + KSCAN_KP_9 as KSCAN_KP_9, + KSCAN_KP_DIVIDE as KSCAN_KP_DIVIDE, + KSCAN_KP_ENTER as KSCAN_KP_ENTER, + KSCAN_KP_EQUALS as KSCAN_KP_EQUALS, + KSCAN_KP_MINUS as KSCAN_KP_MINUS, + KSCAN_KP_MULTIPLY as KSCAN_KP_MULTIPLY, + KSCAN_KP_PERIOD as KSCAN_KP_PERIOD, + KSCAN_KP_PLUS as KSCAN_KP_PLUS, + KSCAN_L as KSCAN_L, + KSCAN_LALT as KSCAN_LALT, + KSCAN_LANG1 as KSCAN_LANG1, + KSCAN_LANG2 as KSCAN_LANG2, + KSCAN_LANG3 as KSCAN_LANG3, + KSCAN_LANG4 as KSCAN_LANG4, + KSCAN_LANG5 as KSCAN_LANG5, + KSCAN_LANG6 as KSCAN_LANG6, + KSCAN_LANG7 as KSCAN_LANG7, + KSCAN_LANG8 as KSCAN_LANG8, + KSCAN_LANG9 as KSCAN_LANG9, + KSCAN_LCTRL as KSCAN_LCTRL, + KSCAN_LEFT as KSCAN_LEFT, + KSCAN_LEFTBRACKET as KSCAN_LEFTBRACKET, + KSCAN_LGUI as KSCAN_LGUI, + KSCAN_LMETA as KSCAN_LMETA, + KSCAN_LSHIFT as KSCAN_LSHIFT, + KSCAN_LSUPER as KSCAN_LSUPER, + KSCAN_M as KSCAN_M, + KSCAN_MENU as KSCAN_MENU, + KSCAN_MINUS as KSCAN_MINUS, + KSCAN_MODE as KSCAN_MODE, + KSCAN_N as KSCAN_N, + KSCAN_NONUSBACKSLASH as KSCAN_NONUSBACKSLASH, + KSCAN_NONUSHASH as KSCAN_NONUSHASH, + KSCAN_NUMLOCK as KSCAN_NUMLOCK, + KSCAN_NUMLOCKCLEAR as KSCAN_NUMLOCKCLEAR, + KSCAN_O as KSCAN_O, + KSCAN_P as KSCAN_P, + KSCAN_PAGEDOWN as KSCAN_PAGEDOWN, + KSCAN_PAGEUP as KSCAN_PAGEUP, + KSCAN_PAUSE as KSCAN_PAUSE, + KSCAN_PERIOD as KSCAN_PERIOD, + KSCAN_POWER as KSCAN_POWER, + KSCAN_PRINT as KSCAN_PRINT, + KSCAN_PRINTSCREEN as KSCAN_PRINTSCREEN, + KSCAN_Q as KSCAN_Q, + KSCAN_R as KSCAN_R, + KSCAN_RALT as KSCAN_RALT, + KSCAN_RCTRL as KSCAN_RCTRL, + KSCAN_RETURN as KSCAN_RETURN, + KSCAN_RGUI as KSCAN_RGUI, + KSCAN_RIGHT as KSCAN_RIGHT, + KSCAN_RIGHTBRACKET as KSCAN_RIGHTBRACKET, + KSCAN_RMETA as KSCAN_RMETA, + KSCAN_RSHIFT as KSCAN_RSHIFT, + KSCAN_RSUPER as KSCAN_RSUPER, + KSCAN_S as KSCAN_S, + KSCAN_SCROLLLOCK as KSCAN_SCROLLLOCK, + KSCAN_SCROLLOCK as KSCAN_SCROLLOCK, + KSCAN_SEMICOLON as KSCAN_SEMICOLON, + KSCAN_SLASH as KSCAN_SLASH, + KSCAN_SPACE as KSCAN_SPACE, + KSCAN_SYSREQ as KSCAN_SYSREQ, + KSCAN_T as KSCAN_T, + KSCAN_TAB as KSCAN_TAB, + KSCAN_U as KSCAN_U, + KSCAN_UNKNOWN as KSCAN_UNKNOWN, + KSCAN_UP as KSCAN_UP, + KSCAN_V as KSCAN_V, + KSCAN_W as KSCAN_W, + KSCAN_X as KSCAN_X, + KSCAN_Y as KSCAN_Y, + KSCAN_Z as KSCAN_Z, + K_0 as K_0, + K_1 as K_1, + K_2 as K_2, + K_3 as K_3, + K_4 as K_4, + K_5 as K_5, + K_6 as K_6, + K_7 as K_7, + K_8 as K_8, + K_9 as K_9, + K_AC_BACK as K_AC_BACK, + K_AMPERSAND as K_AMPERSAND, + K_ASTERISK as K_ASTERISK, + K_AT as K_AT, + K_BACKQUOTE as K_BACKQUOTE, + K_BACKSLASH as K_BACKSLASH, + K_BACKSPACE as K_BACKSPACE, + K_BREAK as K_BREAK, + K_CAPSLOCK as K_CAPSLOCK, + K_CARET as K_CARET, + K_CLEAR as K_CLEAR, + K_COLON as K_COLON, + K_COMMA as K_COMMA, + K_CURRENCYSUBUNIT as K_CURRENCYSUBUNIT, + K_CURRENCYUNIT as K_CURRENCYUNIT, + K_DELETE as K_DELETE, + K_DOLLAR as K_DOLLAR, + K_DOWN as K_DOWN, + K_END as K_END, + K_EQUALS as K_EQUALS, + K_ESCAPE as K_ESCAPE, + K_EURO as K_EURO, + K_EXCLAIM as K_EXCLAIM, + K_F1 as K_F1, + K_F10 as K_F10, + K_F11 as K_F11, + K_F12 as K_F12, + K_F13 as K_F13, + K_F14 as K_F14, + K_F15 as K_F15, + K_F2 as K_F2, + K_F3 as K_F3, + K_F4 as K_F4, + K_F5 as K_F5, + K_F6 as K_F6, + K_F7 as K_F7, + K_F8 as K_F8, + K_F9 as K_F9, + K_GREATER as K_GREATER, + K_HASH as K_HASH, + K_HELP as K_HELP, + K_HOME as K_HOME, + K_INSERT as K_INSERT, + K_KP0 as K_KP0, + K_KP1 as K_KP1, + K_KP2 as K_KP2, + K_KP3 as K_KP3, + K_KP4 as K_KP4, + K_KP5 as K_KP5, + K_KP6 as K_KP6, + K_KP7 as K_KP7, + K_KP8 as K_KP8, + K_KP9 as K_KP9, + K_KP_0 as K_KP_0, + K_KP_1 as K_KP_1, + K_KP_2 as K_KP_2, + K_KP_3 as K_KP_3, + K_KP_4 as K_KP_4, + K_KP_5 as K_KP_5, + K_KP_6 as K_KP_6, + K_KP_7 as K_KP_7, + K_KP_8 as K_KP_8, + K_KP_9 as K_KP_9, + K_KP_DIVIDE as K_KP_DIVIDE, + K_KP_ENTER as K_KP_ENTER, + K_KP_EQUALS as K_KP_EQUALS, + K_KP_MINUS as K_KP_MINUS, + K_KP_MULTIPLY as K_KP_MULTIPLY, + K_KP_PERIOD as K_KP_PERIOD, + K_KP_PLUS as K_KP_PLUS, + K_LALT as K_LALT, + K_LCTRL as K_LCTRL, + K_LEFT as K_LEFT, + K_LEFTBRACKET as K_LEFTBRACKET, + K_LEFTPAREN as K_LEFTPAREN, + K_LESS as K_LESS, + K_LGUI as K_LGUI, + K_LMETA as K_LMETA, + K_LSHIFT as K_LSHIFT, + K_LSUPER as K_LSUPER, + K_MENU as K_MENU, + K_MINUS as K_MINUS, + K_MODE as K_MODE, + K_NUMLOCK as K_NUMLOCK, + K_NUMLOCKCLEAR as K_NUMLOCKCLEAR, + K_PAGEDOWN as K_PAGEDOWN, + K_PAGEUP as K_PAGEUP, + K_PAUSE as K_PAUSE, + K_PERCENT as K_PERCENT, + K_PERIOD as K_PERIOD, + K_PLUS as K_PLUS, + K_POWER as K_POWER, + K_PRINT as K_PRINT, + K_PRINTSCREEN as K_PRINTSCREEN, + K_QUESTION as K_QUESTION, + K_QUOTE as K_QUOTE, + K_QUOTEDBL as K_QUOTEDBL, + K_RALT as K_RALT, + K_RCTRL as K_RCTRL, + K_RETURN as K_RETURN, + K_RGUI as K_RGUI, + K_RIGHT as K_RIGHT, + K_RIGHTBRACKET as K_RIGHTBRACKET, + K_RIGHTPAREN as K_RIGHTPAREN, + K_RMETA as K_RMETA, + K_RSHIFT as K_RSHIFT, + K_RSUPER as K_RSUPER, + K_SCROLLLOCK as K_SCROLLLOCK, + K_SCROLLOCK as K_SCROLLOCK, + K_SEMICOLON as K_SEMICOLON, + K_SLASH as K_SLASH, + K_SPACE as K_SPACE, + K_SYSREQ as K_SYSREQ, + K_TAB as K_TAB, + K_UNDERSCORE as K_UNDERSCORE, + K_UNKNOWN as K_UNKNOWN, + K_UP as K_UP, + K_a as K_a, + K_b as K_b, + K_c as K_c, + K_d as K_d, + K_e as K_e, + K_f as K_f, + K_g as K_g, + K_h as K_h, + K_i as K_i, + K_j as K_j, + K_k as K_k, + K_l as K_l, + K_m as K_m, + K_n as K_n, + K_o as K_o, + K_p as K_p, + K_q as K_q, + K_r as K_r, + K_s as K_s, + K_t as K_t, + K_u as K_u, + K_v as K_v, + K_w as K_w, + K_x as K_x, + K_y as K_y, + K_z as K_z, + LIL_ENDIAN as LIL_ENDIAN, + LOCALECHANGED as LOCALECHANGED, + MIDIIN as MIDIIN, + MIDIOUT as MIDIOUT, + MOUSEBUTTONDOWN as MOUSEBUTTONDOWN, + MOUSEBUTTONUP as MOUSEBUTTONUP, + MOUSEMOTION as MOUSEMOTION, + MOUSEWHEEL as MOUSEWHEEL, + MULTIGESTURE as MULTIGESTURE, + NOEVENT as NOEVENT, + NOFRAME as NOFRAME, + NULL_VIDEODRIVER as NULL_VIDEODRIVER, + NUMEVENTS as NUMEVENTS, + OPENGL as OPENGL, + OPENGLBLIT as OPENGLBLIT, + PREALLOC as PREALLOC, + QUIT as QUIT, + RENDER_DEVICE_RESET as RENDER_DEVICE_RESET, + RENDER_TARGETS_RESET as RENDER_TARGETS_RESET, + RESIZABLE as RESIZABLE, + RLEACCEL as RLEACCEL, + RLEACCELOK as RLEACCELOK, + SCALED as SCALED, + SCRAP_BMP as SCRAP_BMP, + SCRAP_CLIPBOARD as SCRAP_CLIPBOARD, + SCRAP_PBM as SCRAP_PBM, + SCRAP_PPM as SCRAP_PPM, + SCRAP_SELECTION as SCRAP_SELECTION, + SCRAP_TEXT as SCRAP_TEXT, + SHOWN as SHOWN, + SRCALPHA as SRCALPHA, + SRCCOLORKEY as SRCCOLORKEY, + SWSURFACE as SWSURFACE, + SYSTEM_CURSOR_ARROW as SYSTEM_CURSOR_ARROW, + SYSTEM_CURSOR_CROSSHAIR as SYSTEM_CURSOR_CROSSHAIR, + SYSTEM_CURSOR_HAND as SYSTEM_CURSOR_HAND, + SYSTEM_CURSOR_IBEAM as SYSTEM_CURSOR_IBEAM, + SYSTEM_CURSOR_NO as SYSTEM_CURSOR_NO, + SYSTEM_CURSOR_SIZEALL as SYSTEM_CURSOR_SIZEALL, + SYSTEM_CURSOR_SIZENESW as SYSTEM_CURSOR_SIZENESW, + SYSTEM_CURSOR_SIZENS as SYSTEM_CURSOR_SIZENS, + SYSTEM_CURSOR_SIZENWSE as SYSTEM_CURSOR_SIZENWSE, + SYSTEM_CURSOR_SIZEWE as SYSTEM_CURSOR_SIZEWE, + SYSTEM_CURSOR_WAIT as SYSTEM_CURSOR_WAIT, + SYSTEM_CURSOR_WAITARROW as SYSTEM_CURSOR_WAITARROW, + SYSWMEVENT as SYSWMEVENT, + TEXTEDITING as TEXTEDITING, + TEXTINPUT as TEXTINPUT, + TIMER_RESOLUTION as TIMER_RESOLUTION, + USEREVENT as USEREVENT, + USEREVENT_DROPFILE as USEREVENT_DROPFILE, + VIDEOEXPOSE as VIDEOEXPOSE, + VIDEORESIZE as VIDEORESIZE, + WINDOWCLOSE as WINDOWCLOSE, + WINDOWDISPLAYCHANGED as WINDOWDISPLAYCHANGED, + WINDOWENTER as WINDOWENTER, + WINDOWEXPOSED as WINDOWEXPOSED, + WINDOWFOCUSGAINED as WINDOWFOCUSGAINED, + WINDOWFOCUSLOST as WINDOWFOCUSLOST, + WINDOWHIDDEN as WINDOWHIDDEN, + WINDOWHITTEST as WINDOWHITTEST, + WINDOWICCPROFCHANGED as WINDOWICCPROFCHANGED, + WINDOWLEAVE as WINDOWLEAVE, + WINDOWMAXIMIZED as WINDOWMAXIMIZED, + WINDOWMINIMIZED as WINDOWMINIMIZED, + WINDOWMOVED as WINDOWMOVED, + WINDOWPOS_CENTERED as WINDOWPOS_CENTERED, + WINDOWPOS_UNDEFINED as WINDOWPOS_UNDEFINED, + WINDOWRESIZED as WINDOWRESIZED, + WINDOWRESTORED as WINDOWRESTORED, + WINDOWSHOWN as WINDOWSHOWN, + WINDOWSIZECHANGED as WINDOWSIZECHANGED, + WINDOWTAKEFOCUS as WINDOWTAKEFOCUS, +) diff --git a/buildconfig/stubs/pygame/locals.pyi b/buildconfig/stubs/pygame/locals.pyi index ef822c62d6..6b1059f299 100644 --- a/buildconfig/stubs/pygame/locals.pyi +++ b/buildconfig/stubs/pygame/locals.pyi @@ -1,5 +1,5 @@ # buildconfig/stubs/gen_stubs.py -# A script to auto-generate locals.pyi, constants.pyi and __init__.pyi typestubs +# A script to auto-generate locals.pyi, constants.pyi, debug.pyi and __init__.pyi typestubs # IMPORTANT NOTE: Do not edit this file by hand! ACTIVEEVENT: int diff --git a/docs/reST/c_api/base.rst b/docs/reST/c_api/base.rst index 9c20197f5f..da808b6996 100644 --- a/docs/reST/c_api/base.rst +++ b/docs/reST/c_api/base.rst @@ -177,3 +177,13 @@ C header: src_c/include/pygame.h The previous surface object, if any, is invalidated. Argument *screen* may be *NULL*. This functions is called by pygame.display.set_mode(). + +.. c:function:: int pgWarn(PyObject *category, const char *message, Py_ssize_t stack_level, int urgency) + + Create a warning with a given urgency, besides that it is used the same as ``PyErr_WarnEx``. + + Urgency: + + * **0**: Something rather unwanted happened, immediate attention is needed, as the code might not work properly. + * **1**: Mostly for deprecations, used if something might need attention of the user in the future. + * **2**: Nothing very important, can be ignored, but probably holds useful information if user does something wrong / something unexpected might happen. diff --git a/docs/reST/ref/pygame.rst b/docs/reST/ref/pygame.rst index b6266f687d..755d54fb13 100644 --- a/docs/reST/ref/pygame.rst +++ b/docs/reST/ref/pygame.rst @@ -224,6 +224,32 @@ object instead of the module, which can be used to test for availability. .. ## pygame.print_debug_info ## +.. function:: warn + + | :sl:`throws a warning` + | :sg:`warn(message, urgency, level=1, category=UserWarning)` + + Throws a warning with a given urgency. See documentation for :c:func:`pgWarn` for more information on urgency system. + + Category accepts any subclass of a built-in class ``Warning`` and is a type of generated warning. + Same as in `warnings.warn() `_. + + .. note:: + This function is mostly used internally, but might be also useful for extensions. + Arg ``level`` denotes how much to trace back in the call stack. If it is equal to 0, that means that the caller wil be blamed. + Beware, that the default value is 1, meaning the caller of a function with ``pygame.warn(...)`` will be blamed: :: + + >>> def my_func(): + ... pygame.warn("Warning!", urgency=0) + ... + >>> my_func() + :1: UserWarning: Warning! (urgent: 0) + >>> def my_func2(): + ... pygame.warn("Warning!", urgency=0, level=0) + :2: UserWarning: Warning! (urgent: 0) + + .. # pygame.warn "" + :mod:`pygame.version` ===================== @@ -559,3 +585,32 @@ where this is set to 0 by default. This hint only affects the windows platform, other platforms can control DPI awareness via a Window creation keyword parameter called "allow_high_dpi". + + +:mod:`pygame.debug` +===================== + +.. module:: pygame.debug + :synopsis: small plug-in for enabling debugging information + +| :sl:`small plug-in for enabling debugging information` + +This is a simple plug-in that can be used as a drop-in repleacement for ``import pygame`` and imports alike. +Example usage: :: + + import pygame.debug as pg # works the same as "import pygame as pg" + + window = pg.display.set_mode((100, 100)) + + while True: + for event in pg.event.get(): + if event.type == pg.QUIT: + pg.quit() + quit() + + pg.display.flip() + +Doing this will enable more detailed warnings and will print additional debug information. +(Side note: this will automatically call ``pygame.init()`` to make debug information more complete, but this shouldn't have any side effects.) + +======= diff --git a/src_c/_freetype.c b/src_c/_freetype.c index f4da7757fd..2dd151d3ec 100644 --- a/src_c/_freetype.c +++ b/src_c/_freetype.c @@ -2235,11 +2235,10 @@ _ft_get_init(PyObject *self, PyObject *_null) static PyObject * _ft_was_init(PyObject *self, PyObject *_null) { - if (PyErr_WarnEx( - PyExc_DeprecationWarning, - "was_init has been deprecated and may be removed in a future " - "version. Use the equivalent get_init function instead", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "was_init has been deprecated and may be removed in a future " + "version. Use the equivalent get_init function instead", + 1, 1) == -1) { return NULL; } return _ft_get_init(self, _null); diff --git a/src_c/_pygame.h b/src_c/_pygame.h index e87986d776..650522e460 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -533,7 +533,7 @@ typedef enum { #define PYGAMEAPI_PIXELARRAY_NUMSLOTS 2 #define PYGAMEAPI_COLOR_NUMSLOTS 5 #define PYGAMEAPI_MATH_NUMSLOTS 2 -#define PYGAMEAPI_BASE_NUMSLOTS 29 +#define PYGAMEAPI_BASE_NUMSLOTS 30 #define PYGAMEAPI_EVENT_NUMSLOTS 10 #define PYGAMEAPI_WINDOW_NUMSLOTS 1 #define PYGAMEAPI_GEOMETRY_NUMSLOTS 1 diff --git a/src_c/alphablit.c b/src_c/alphablit.c index e975218fda..c530aa0e66 100644 --- a/src_c/alphablit.c +++ b/src_c/alphablit.c @@ -22,7 +22,6 @@ pete@shinners.org */ -#define NO_PYGAME_C_API #include "_surface.h" #include "simd_shared.h" #include "simd_blitters.h" @@ -2901,16 +2900,15 @@ premul_surf_color_by_alpha_non_simd(SDL_Surface *src, SDL_Surface *dst) } } -#define _PG_WARN_SIMD(s) \ - if (pg_##s##_at_runtime_but_uncompiled()) { \ - if (PyErr_WarnEx( \ - PyExc_RuntimeWarning, \ - "Your system is " #s " capable but pygame was not " \ - "built with support for it. The performance of some " \ - "of your blits could be adversely affected", \ - 1) < 0) { \ - return -1; \ - } \ +#define _PG_WARN_SIMD(s) \ + if (pg_##s##_at_runtime_but_uncompiled()) { \ + if (pgWarn(PyExc_RuntimeWarning, \ + "Your system is " #s " capable but pygame was not " \ + "built with support for it. The performance of some " \ + "of your blits could be adversely affected", \ + 1, 0) < 0) { \ + return -1; \ + } \ } /* On error, returns -1 with python error set. */ diff --git a/src_c/base.c b/src_c/base.c index 573bca3aa2..4c610b5af4 100644 --- a/src_c/base.c +++ b/src_c/base.c @@ -82,6 +82,7 @@ static int pg_sdl_was_init = 0; SDL_Window *pg_default_window = NULL; pgSurfaceObject *pg_default_screen = NULL; static char *pg_env_blend_alpha_SDL2 = NULL; +static int pg_warn_filter = 0; static void pg_install_parachute(void); @@ -172,6 +173,9 @@ static void pg_SetDefaultWindowSurface(pgSurfaceObject *); static char * pg_EnvShouldBlendAlphaSDL2(void); +static int +pgWarn(PyObject *category, const char *message, Py_ssize_t stack_level, + int urgency); /* compare compiled to linked, raise python error on incompatibility */ static int @@ -2102,6 +2106,102 @@ pg_EnvShouldBlendAlphaSDL2(void) return pg_env_blend_alpha_SDL2; } +static inline int +intSizeAsStr(int num) +{ + if (num == 0) { + // printf("i s=1, zero"); + return 1; + } + else if (num < 0) { + // printf("i s=%i, neg", ceil(log10(-num + 1)) + 1); + return (int)ceil(log10(-num + 1)) + 1; + } + return (int)ceil(log10(num + 1)); +} + +static int +pgWarn(PyObject *category, const char *message, Py_ssize_t stack_level, + int urgency) +{ + if (pg_warn_filter < urgency) + return 0; + + const char *extra; + + switch (urgency) { + case 0: + extra = "urgent: "; + break; + case 1: + extra = "mild: "; + break; + case 2: + extra = "note: "; + break; + default: + extra = ""; + } + + // 12 3 4 + // "message (extra{urgency})\0" + size_t str_size = + strlen(message) + strlen(extra) + intSizeAsStr(urgency) + 4; + + char *formatted = malloc(str_size); + if (formatted == NULL) { + PyErr_SetString(PyExc_MemoryError, + "cannot allocate memory to format warning message"); + return -1; + } + + PyOS_snprintf(formatted, str_size, "%s (%s%i)", message, extra, urgency); + + int ret = PyErr_WarnEx(category, formatted, stack_level); + free(formatted); + return ret; +} + +static PyObject * +pg_warn(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *category = NULL; + const char *message; + Py_ssize_t stack_level = -1; + int urgency; + char *kw_names[] = {"message", "urgency", "level", "category", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si|nO", kw_names, &message, + &urgency, &stack_level, &category)) + return NULL; + + if (category == NULL) + category = PyExc_UserWarning; + + if (stack_level < 0) + stack_level = 1; + + if (pgWarn(category, message, stack_level + 1, urgency) < 0) + return NULL; + + Py_RETURN_NONE; +} + +static PyObject * +pg_get_warnings_filter(PyObject *self) +{ + return PyLong_FromLong(pg_warn_filter); +} + +static PyObject * +pg_set_warnings_filter(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "i", &pg_warn_filter)) + return NULL; + + Py_RETURN_NONE; +} + /*error signal handlers(replacing SDL parachute)*/ static void pygame_parachute(int sig) @@ -2218,6 +2318,14 @@ static PyMethodDef _base_methods[] = { {"get_array_interface", (PyCFunction)pg_get_array_interface, METH_O, "return an array struct interface as an interface dictionary"}, + {"warn", (PyCFunction)pg_warn, METH_VARARGS | METH_KEYWORDS, + "throw a warning with a given severity which is only used for filtering"}, + {"get_warnings_filter", (PyCFunction)pg_get_warnings_filter, METH_NOARGS, + "get value of a warning filter by severity (smaller number - more " + "important)"}, + {"set_warnings_filter", (PyCFunction)pg_set_warnings_filter, METH_VARARGS, + "set value of a warning filter by severity (smaller number - more " + "important)"}, {NULL, NULL, 0, NULL}}; #if defined(BUILD_STATIC) && defined(NO_PYGAME_C_API) @@ -2314,8 +2422,9 @@ MODINIT_DEFINE(base) c_api[26] = pg_TwoDoublesFromFastcallArgs; c_api[27] = pg_GetDefaultConvertFormat; c_api[28] = pg_SetDefaultConvertFormat; + c_api[29] = pgWarn; -#define FILLED_SLOTS 29 +#define FILLED_SLOTS 30 #if PYGAMEAPI_BASE_NUMSLOTS != FILLED_SLOTS #error export slot count mismatch diff --git a/src_c/color.c b/src_c/color.c index 80761a4b0d..47bc7a753d 100644 --- a/src_c/color.c +++ b/src_c/color.c @@ -1014,11 +1014,11 @@ _color_set_hsva(pgColorObject *color, PyObject *value, void *closure) } if (PySequence_Size(value) > 4) { - if (PyErr_WarnEx( + if (pgWarn( PyExc_DeprecationWarning, "Passing sequences of size larger than 4 is deprecated, doing " "this will error in a future version", - 1) == -1) { + 1, 1) == -1) { return -1; } } @@ -1189,11 +1189,11 @@ _color_set_hsla(pgColorObject *color, PyObject *value, void *closure) } if (PySequence_Size(value) > 4) { - if (PyErr_WarnEx( + if (pgWarn( PyExc_DeprecationWarning, "Passing sequences of size larger than 4 is deprecated, doing " "this will error in a future version", - 1) == -1) { + 1, 1) == -1) { return -1; } } @@ -1364,11 +1364,11 @@ _color_set_i1i2i3(pgColorObject *color, PyObject *value, void *closure) } if (PySequence_Size(value) > 3) { - if (PyErr_WarnEx( + if (pgWarn( PyExc_DeprecationWarning, "Passing sequences of size larger than 3 is deprecated, doing " "this will error in a future version", - 1) == -1) { + 1, 1) == -1) { return -1; } } @@ -1446,11 +1446,11 @@ _color_set_cmy(pgColorObject *color, PyObject *value, void *closure) } if (PySequence_Size(value) > 3) { - if (PyErr_WarnEx( + if (pgWarn( PyExc_DeprecationWarning, "Passing sequences of size larger than 3 is deprecated, doing " "this will error in a future version", - 1) == -1) { + 1, 1) == -1) { return -1; } } @@ -1516,11 +1516,11 @@ _color_set_normalized(pgColorObject *color, PyObject *value, void *closure) } if (PySequence_Size(value) > 4) { - if (PyErr_WarnEx( + if (pgWarn( PyExc_DeprecationWarning, "Passing sequences of size larger than 4 is deprecated, doing " "this will error in a future version", - 1) == -1) { + 1, 1) == -1) { return -1; } } @@ -1759,9 +1759,8 @@ _color_set_length(pgColorObject *color, PyObject *args) { int clength; - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.Color.set_length deprecated since 2.1.3", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.Color.set_length deprecated since 2.1.3", 1, 1) == -1) { return NULL; } diff --git a/src_c/display.c b/src_c/display.c index af7e268cbc..abc8827517 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -893,9 +893,9 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) state->unscaled_render = vsync && !(flags & (PGS_SCALED | PGS_OPENGL)); if (state->scaled_gl) { - if (PyErr_WarnEx(PyExc_FutureWarning, - "SCALED|OPENGL is experimental and subject to change", - 1) != 0) + if (pgWarn(PyExc_FutureWarning, + "SCALED|OPENGL is experimental and subject to change", 1, + 2) != 0) return NULL; } @@ -1253,9 +1253,8 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) goto DESTROY_WINDOW; } if (!(info.flags & SDL_RENDERER_ACCELERATED)) { - if (PyErr_WarnEx(PyExc_Warning, - "no fast renderer available", - 1) != 0) { + if (pgWarn(PyExc_Warning, "no fast renderer available", + 1, 2) != 0) { _display_state_cleanup(state); goto DESTROY_WINDOW; } @@ -1337,9 +1336,8 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) SDL_SetWindowIcon(win, pgSurface_AsSurface(state->icon)); if (depth != 0 && PG_SURF_BitsPerPixel(surface->surf) != depth) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "The depth argument is deprecated, and is ignored", - 1)) { + if (pgWarn(PyExc_DeprecationWarning, + "The depth argument is deprecated, and is ignored", 1, 0)) { return NULL; } } @@ -1371,7 +1369,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) "window size on platform. Using (%d, %d) instead."; snprintf(buffer, sizeof(buffer), format_string, surface->surf->w, surface->surf->h); - if (PyErr_WarnEx(PyExc_RuntimeWarning, buffer, 1) != 0) { + if (pgWarn(PyExc_RuntimeWarning, buffer, 1, 1) != 0) { return NULL; } } @@ -1914,9 +1912,9 @@ pg_set_palette(PyObject *self, PyObject *args) static PyObject * pg_set_gamma(PyObject *self, PyObject *arg) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.display.set_gamma deprecated since 2.1.4", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.display.set_gamma deprecated since 2.1.4", 1, + 1) == -1) { return NULL; } @@ -2006,9 +2004,9 @@ pg_convert_to_uint16(PyObject *python_array, Uint16 *c_uint16_array) static PyObject * pg_set_gamma_ramp(PyObject *self, PyObject *arg) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.display.set_gamma_ramp deprecated since 2.1.4", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.display.set_gamma_ramp deprecated since 2.1.4", 1, + 1) == -1) { return NULL; } @@ -2351,9 +2349,9 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) #if defined(SDL_SYSWM_KMSDRM) case SDL_SYSWM_KMSDRM: #endif - if (PyErr_WarnEx(PyExc_Warning, - "cannot leave FULLSCREEN on this platform", - 1) != 0) { + if (pgWarn(PyExc_Warning, + "cannot leave FULLSCREEN on this platform", 1, + 0) != 0) { return NULL; } return PyLong_FromLong(-1); @@ -2486,9 +2484,8 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) * This is only relevant in the non-GL case. */ int wx = SDL_WINDOWPOS_UNDEFINED_DISPLAY(window_display); int wy = SDL_WINDOWPOS_UNDEFINED_DISPLAY(window_display); - if (PyErr_WarnEx(PyExc_Warning, - "re-creating window in toggle_fullscreen", - 1) != 0) { + if (pgWarn(PyExc_Warning, + "re-creating window in toggle_fullscreen", 1, 2) != 0) { return NULL; } flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; @@ -2552,10 +2549,9 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } if (r_info.flags & SDL_RENDERER_SOFTWARE && wm_info.subsystem == SDL_SYSWM_X11) { - if (PyErr_WarnEx( - PyExc_Warning, - "recreating software renderer in toggle_fullscreen", - 1) != 0) { + if (pgWarn(PyExc_Warning, + "recreating software renderer in toggle_fullscreen", + 1, 2) != 0) { return NULL; } /* display surface lost? only on x11? */ @@ -2610,9 +2606,8 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) /* This only happens AFTER other options have been exhausted. * with GL, Renderer, or the correct window size, toggling works. * Only entering a hard fullscreen state is unsupported. */ - if (PyErr_WarnEx(PyExc_Warning, - "skipping toggle_fullscreen on wayland", - 1) != 0) { + if (pgWarn(PyExc_Warning, "skipping toggle_fullscreen on wayland", + 1, 0) != 0) { return NULL; } return PyLong_FromLong(-1); @@ -2636,9 +2631,9 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } display_surface->surf = SDL_GetWindowSurface(win); pg_SetDefaultWindow(win); - if (PyErr_WarnEx(PyExc_Warning, - "re-creating window in toggle_fullscreen", - 1) != 0) { + if (pgWarn(PyExc_Warning, + "re-creating window in toggle_fullscreen", 1, + 2) != 0) { return NULL; } return PyLong_FromLong(-1); diff --git a/src_c/doc/pygame_doc.h b/src_c/doc/pygame_doc.h index 299effdfeb..c1677f9cae 100644 --- a/src_c/doc/pygame_doc.h +++ b/src_c/doc/pygame_doc.h @@ -13,8 +13,10 @@ #define DOC_ENCODESTRING "encode_string([obj [, encoding [, errors [, etype]]]]) -> bytes or None\nEncode a Unicode or bytes object" #define DOC_ENCODEFILEPATH "encode_file_path([obj [, etype]]) -> bytes or None\nEncode a Unicode or bytes object as a file system path" #define DOC_PRINTDEBUGINFO "print_debug_info(filename=None) -> None\nretrieves useful information for debugging and issue-reporting purposes" +#define DOC_WARN "warn(message, urgency, level=1, category=UserWarning)\nthrows a warning" #define DOC_VERSION "small module containing version information" #define DOC_VERSION_VER "ver = '1.2'\nversion number as a string" #define DOC_VERSION_VERNUM "vernum = (1, 5, 3)\ntupled integers of the version" #define DOC_VERSION_REV "rev = 'a6f89747b551+'\nrepository revision of the build" #define DOC_VERSION_SDL "SDL = '(2, 26, 5)'\ntupled integers of the SDL library version" +#define DOC_DEBUG "small plug-in for enabling debugging information" diff --git a/src_c/draw.c b/src_c/draw.c index 06a8149ef0..7434dde9ea 100644 --- a/src_c/draw.c +++ b/src_c/draw.c @@ -127,11 +127,11 @@ aaline(PyObject *self, PyObject *arg, PyObject *kwargs) } if (blend != NULL) { - if (PyErr_WarnEx( + if (pgWarn( PyExc_DeprecationWarning, "blend argument is deprecated and has no functionality and " "will be completely removed in a future version of pygame-ce", - 1) == -1) { + 1, 1) == -1) { return NULL; } } @@ -273,11 +273,11 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) } if (blend != NULL) { - if (PyErr_WarnEx( + if (pgWarn( PyExc_DeprecationWarning, "blend argument is deprecated and has no functionality and " "will be completely removed in a future version of pygame-ce", - 1) == -1) { + 1, 1) == -1) { return NULL; } } diff --git a/src_c/image.c b/src_c/image.c index 90f52f0988..5040272ca5 100644 --- a/src_c/image.c +++ b/src_c/image.c @@ -1320,9 +1320,8 @@ image_frombytes(PyObject *self, PyObject *arg, PyObject *kwds) PyObject * image_tostring(PyObject *self, PyObject *arg, PyObject *kwarg) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.image.tostring deprecated since 2.3.0", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.image.tostring deprecated since 2.3.0", 1, 1) == -1) { return NULL; } @@ -1332,9 +1331,8 @@ image_tostring(PyObject *self, PyObject *arg, PyObject *kwarg) PyObject * image_fromstring(PyObject *self, PyObject *arg, PyObject *kwarg) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.image.fromstring deprecated since 2.3.0", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.image.fromstring deprecated since 2.3.0", 1, 1) == -1) { return NULL; } diff --git a/src_c/include/_pygame.h b/src_c/include/_pygame.h index 5ff4882dfb..01f6110921 100644 --- a/src_c/include/_pygame.h +++ b/src_c/include/_pygame.h @@ -189,6 +189,10 @@ typedef struct pg_bufferinfo_s { #define pg_SetDefaultConvertFormat \ (*(SDL_PixelFormat * (*)(Uint32)) PYGAMEAPI_GET_SLOT(base, 28)) +#define pgWarn \ + (*(int (*)(PyObject *, const char *, Py_ssize_t, int))PYGAMEAPI_GET_SLOT( \ + base, 29)) + #define import_pygame_base() IMPORT_PYGAME_MODULE(base) #endif /* ~PYGAMEAPI_BASE_INTERNAL */ diff --git a/src_c/joystick.c b/src_c/joystick.c index 806dfd0b77..41dabd3fb8 100644 --- a/src_c/joystick.c +++ b/src_c/joystick.c @@ -118,12 +118,11 @@ get_count(PyObject *self, PyObject *_null) static PyObject * joy_init(PyObject *self, PyObject *_null) { - if (PyErr_WarnEx( - PyExc_DeprecationWarning, - "pygame.joystick.Joystick.init() is deprecated since 2.4.0. " - "Bear in mind in future it will not be possible to " - "reinitialise a closed Joystick object.", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.joystick.Joystick.init() is deprecated since 2.4.0. " + "Bear in mind in future it will not be possible to " + "reinitialise a closed Joystick object.", + 1, 1) == -1) { return NULL; } @@ -162,12 +161,11 @@ joy_get_init(PyObject *self, PyObject *_null) static PyObject * joy_get_id(PyObject *self, PyObject *_null) { - if (PyErr_WarnEx( - PyExc_DeprecationWarning, - "pygame.joystick.Joystick.get_id() is deprecated since 2.4.0. " - "The original device index is not useful in pygame 2. " - "Use get_instance_id() instead.", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.joystick.Joystick.get_id() is deprecated since 2.4.0. " + "The original device index is not useful in pygame 2. " + "Use get_instance_id() instead.", + 1, 1) == -1) { return NULL; } diff --git a/src_c/key.c b/src_c/key.c index 44ea2457c2..2f6899aefe 100644 --- a/src_c/key.c +++ b/src_c/key.c @@ -463,10 +463,10 @@ key_code(PyObject *self, PyObject *args, PyObject *kwargs) /* in the future, this should be an error. For now it's a warning to not * break existing code */ if (!SDL_WasInit(SDL_INIT_VIDEO)) { - if (PyErr_WarnEx(PyExc_Warning, - "pygame.init() has not been called. This function " - "may return incorrect results", - 1) != 0) { + if (pgWarn(PyExc_Warning, + "pygame.init() has not been called. This function " + "may return incorrect results", + 1, 0) != 0) { return NULL; } } diff --git a/src_c/math.c b/src_c/math.c index 24c04365ca..8babf2dc18 100644 --- a/src_c/math.c +++ b/src_c/math.c @@ -30,7 +30,6 @@ #endif #define PYGAMEAPI_MATH_INTERNAL -#define NO_PYGAME_C_API #include "doc/math_doc.h" #include "pygame.h" @@ -2382,11 +2381,11 @@ vector2_rotate_rad_ip(pgVector *self, PyObject *angleObject) static PyObject * vector2_rotate_ip_rad(pgVector *self, PyObject *angleObject) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "vector2_rotate_rad_ip() now has all the functionality " - "of vector2_rotate_ip_rad(), so vector2_rotate_ip_rad() " - "will be deprecated in pygame 2.1.1", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "vector2_rotate_rad_ip() now has all the functionality " + "of vector2_rotate_ip_rad(), so vector2_rotate_ip_rad() " + "will be deprecated in pygame 2.1.1", + 1, 1) == -1) { return NULL; } return vector2_rotate_rad_ip(self, angleObject); @@ -2893,11 +2892,11 @@ vector3_rotate_rad_ip(pgVector *self, PyObject *args) static PyObject * vector3_rotate_ip_rad(pgVector *self, PyObject *angleObject) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "vector3_rotate_rad_ip() now has all the functionality " - "of vector3_rotate_ip_rad(), so vector3_rotate_ip_rad() " - "will be deprecated in pygame 2.1.1", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "vector3_rotate_rad_ip() now has all the functionality " + "of vector3_rotate_ip_rad(), so vector3_rotate_ip_rad() " + "will be deprecated in pygame 2.1.1", + 1, 1) == -1) { return NULL; } return vector3_rotate_rad_ip(self, angleObject); @@ -3004,12 +3003,11 @@ vector3_rotate_x_rad_ip(pgVector *self, PyObject *angleObject) static PyObject * vector3_rotate_x_ip_rad(pgVector *self, PyObject *angleObject) { - if (PyErr_WarnEx( - PyExc_DeprecationWarning, - "vector3_rotate_x_rad_ip() now has all the functionality of " - "vector3_rotate_x_ip_rad(), so vector3_rotate_x_ip_rad() will " - "be deprecated in pygame 2.1.1", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "vector3_rotate_x_rad_ip() now has all the functionality of " + "vector3_rotate_x_ip_rad(), so vector3_rotate_x_ip_rad() will " + "be deprecated in pygame 2.1.1", + 1, 1) == -1) { return NULL; } return vector3_rotate_x_rad_ip(self, angleObject); @@ -3109,12 +3107,11 @@ vector3_rotate_y_rad_ip(pgVector *self, PyObject *angleObject) static PyObject * vector3_rotate_y_ip_rad(pgVector *self, PyObject *angleObject) { - if (PyErr_WarnEx( - PyExc_DeprecationWarning, - "vector3_rotate_y_rad_ip() now has all the functionality of " - "vector3_rotate_y_ip_rad(), so vector3_rotate_y_ip_rad() will " - "be deprecated in pygame 2.1.1", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "vector3_rotate_y_rad_ip() now has all the functionality of " + "vector3_rotate_y_ip_rad(), so vector3_rotate_y_ip_rad() will " + "be deprecated in pygame 2.1.1", + 1, 1) == -1) { return NULL; } return vector3_rotate_x_rad_ip(self, angleObject); @@ -3215,12 +3212,11 @@ vector3_rotate_z_rad_ip(pgVector *self, PyObject *angleObject) static PyObject * vector3_rotate_z_ip_rad(pgVector *self, PyObject *angleObject) { - if (PyErr_WarnEx( - PyExc_DeprecationWarning, - "vector3_rotate_z_rad_ip() now has all the functionality of " - "vector3_rotate_z_ip_rad(), so vector3_rotate_z_ip_rad() will " - "be deprecated in pygame 2.1.1", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "vector3_rotate_z_rad_ip() now has all the functionality of " + "vector3_rotate_z_ip_rad(), so vector3_rotate_z_ip_rad() will " + "be deprecated in pygame 2.1.1", + 1, 1) == -1) { return NULL; } return vector3_rotate_x_rad_ip(self, angleObject); @@ -4375,11 +4371,11 @@ math_smoothstep(PyObject *self, PyObject *const *args, Py_ssize_t nargs) static PyObject * math_enable_swizzling(pgVector *self, PyObject *_null) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.math.enable_swizzling() is deprecated, " - "and its functionality is removed. This function will be " - "removed in a later version.", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.math.enable_swizzling() is deprecated, " + "and its functionality is removed. This function will be " + "removed in a later version.", + 1, 1) == -1) { return NULL; } Py_RETURN_NONE; @@ -4388,11 +4384,11 @@ math_enable_swizzling(pgVector *self, PyObject *_null) static PyObject * math_disable_swizzling(pgVector *self, PyObject *_null) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.math.disable_swizzling() is deprecated, " - "and its functionality is removed. This function will be " - "removed in a later version.", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.math.disable_swizzling() is deprecated, " + "and its functionality is removed. This function will be " + "removed in a later version.", + 1, 1) == -1) { return NULL; } Py_RETURN_NONE; diff --git a/src_c/mouse.c b/src_c/mouse.c index c6af99056e..68b7ef95d8 100644 --- a/src_c/mouse.c +++ b/src_c/mouse.c @@ -433,11 +433,11 @@ mouse_set_system_cursor(PyObject *self, PyObject *args) { int constant; - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "set_cursor() now has all the functionality of " - "set_system_cursor(), so set_system_cursor() will be " - "deprecated in pygame 2.2", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "set_cursor() now has all the functionality of " + "set_system_cursor(), so set_system_cursor() will be " + "deprecated in pygame 2.2", + 1, 1) == -1) { return NULL; } diff --git a/src_c/scrap.c b/src_c/scrap.c index b34cb6b06e..b8922a2fc7 100644 --- a/src_c/scrap.c +++ b/src_c/scrap.c @@ -100,8 +100,8 @@ _scrap_init(PyObject *self, PyObject *args) { VIDEO_INIT_CHECK(); - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.scrap.init deprecated since 2.2.0", 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.scrap.init deprecated since 2.2.0", 1, 1) == -1) { return NULL; } @@ -132,9 +132,8 @@ _scrap_init(PyObject *self, PyObject *args) static PyObject * _scrap_get_init(PyObject *self, PyObject *_null) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.scrap.get_init deprecated since 2.2.0", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.scrap.get_init deprecated since 2.2.0", 1, 1) == -1) { return NULL; } @@ -153,9 +152,8 @@ _scrap_get_types(PyObject *self, PyObject *_null) PyObject *list; PyObject *tmp; - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.scrap.get_types deprecated since 2.2.0", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.scrap.get_types deprecated since 2.2.0", 1, 1) == -1) { return NULL; } @@ -200,9 +198,8 @@ _scrap_contains(PyObject *self, PyObject *args) { char *type = NULL; - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.scrap.contains deprecated since 2.2.0", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.scrap.contains deprecated since 2.2.0", 1, 1) == -1) { return NULL; } @@ -224,10 +221,10 @@ _scrap_get_scrap(PyObject *self, PyObject *args) char *scrap_type; size_t count; - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.scrap.get deprecated since 2.2.0. Consider using" - " pygame.scrap.get_text instead.", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.scrap.get deprecated since 2.2.0. Consider using" + " pygame.scrap.get_text instead.", + 1, 1) == -1) { return NULL; } @@ -303,10 +300,10 @@ _scrap_put_scrap(PyObject *self, PyObject *args) PyObject *tmp; static const char argfmt[] = "sy#"; - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.scrap.put deprecated since 2.2.0. Consider using" - " pygame.scrap.put_text instead.", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.scrap.put deprecated since 2.2.0. Consider using" + " pygame.scrap.put_text instead.", + 1, 1) == -1) { return NULL; } @@ -349,8 +346,8 @@ _scrap_lost_scrap(PyObject *self, PyObject *_null) { PYGAME_SCRAP_INIT_CHECK(); - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.scrap.lost deprecated since 2.2.0", 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.scrap.lost deprecated since 2.2.0", 1, 1) == -1) { return NULL; } @@ -368,9 +365,8 @@ _scrap_set_mode(PyObject *self, PyObject *args) { PYGAME_SCRAP_INIT_CHECK(); - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "pygame.scrap.set_mode deprecated since 2.2.0", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "pygame.scrap.set_mode deprecated since 2.2.0", 1, 1) == -1) { return NULL; } diff --git a/src_c/surface.c b/src_c/surface.c index 3f36377d22..045d209309 100644 --- a/src_c/surface.c +++ b/src_c/surface.c @@ -1667,9 +1667,9 @@ surf_convert_alpha(pgSurfaceObject *self, PyObject *args) return NULL; if (srcsurf != NULL) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "depth argument deprecated since version 2.4.0", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "depth argument deprecated since version 2.4.0", 1, + 1) == -1) { return NULL; } } diff --git a/src_c/transform.c b/src_c/transform.c index 94ef27453c..5f9ee17d2d 100644 --- a/src_c/transform.c +++ b/src_c/transform.c @@ -1594,10 +1594,9 @@ surf_set_smoothscale_backend(PyObject *self, PyObject *args, PyObject *kwargs) return RAISE(PyExc_ValueError, "MMX not supported on this machine"); } - if (PyErr_WarnEx( - PyExc_DeprecationWarning, - "MMX backend is deprecated in favor of new SSE2 backend", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "MMX backend is deprecated in favor of new SSE2 backend", 1, + 1) == -1) { return NULL; } st->filter_type = "MMX"; @@ -1611,10 +1610,9 @@ surf_set_smoothscale_backend(PyObject *self, PyObject *args, PyObject *kwargs) return RAISE(PyExc_ValueError, "SSE not supported on this machine"); } - if (PyErr_WarnEx( - PyExc_DeprecationWarning, - "SSE backend is deprecated in favor of new SSE2 backend", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "SSE backend is deprecated in favor of new SSE2 backend", 1, + 1) == -1) { return NULL; } st->filter_type = "SSE"; diff --git a/src_c/window.c b/src_c/window.c index f2217cd20c..9cd06e252e 100644 --- a/src_c/window.c +++ b/src_c/window.c @@ -245,8 +245,8 @@ _resize_event_watch(void *userdata, SDL_Event *event) if (_window_opengl_set_viewport(event_window, event_window_pg->context, event->window.data1, event->window.data2) < 0) { - return PyErr_WarnEx(PyExc_RuntimeWarning, - "Failed to set OpenGL viewport", 0); + return pgWarn(PyExc_RuntimeWarning, + "Failed to set OpenGL viewport", 0, 0); } } @@ -417,8 +417,8 @@ window_set_grab_keyboard(pgWindowObject *self, PyObject *arg, void *v) SDL_SetWindowKeyboardGrab(self->_win, enable); #else - if (PyErr_WarnEx(PyExc_Warning, "'grab_keyboard' requires SDL 2.0.16+", - 1) == -1) { + if (pgWarn(PyExc_Warning, "'grab_keyboard' requires SDL 2.0.16+", 1, 0) == + -1) { return -1; } #endif @@ -432,8 +432,8 @@ window_get_grab_keyboard(pgWindowObject *self, void *v) return PyBool_FromLong(SDL_GetWindowFlags(self->_win) & SDL_WINDOW_KEYBOARD_GRABBED); #else - if (PyErr_WarnEx(PyExc_Warning, "'grab_keyboard' requires SDL 2.0.16+", - 1) == -1) { + if (pgWarn(PyExc_Warning, "'grab_keyboard' requires SDL 2.0.16+", 1, 0) == + -1) { return NULL; } return PyBool_FromLong(SDL_FALSE); @@ -446,8 +446,8 @@ window_get_keyboard_grabbed(pgWindowObject *self, void *v) #if SDL_VERSION_ATLEAST(2, 0, 16) return PyBool_FromLong(SDL_GetWindowKeyboardGrab(self->_win)); #else - if (PyErr_WarnEx(PyExc_Warning, "'keyboard_captured' requires SDL 2.0.16+", - 1) == -1) { + if (pgWarn(PyExc_Warning, "'keyboard_captured' requires SDL 2.0.16+", 1, + 0) == -1) { return NULL; } return PyBool_FromLong(SDL_FALSE); @@ -523,9 +523,8 @@ window_set_always_on_top(pgWindowObject *self, PyObject *arg, void *v) SDL_SetWindowAlwaysOnTop(self->_win, enable); #else - if (PyErr_WarnEx(PyExc_Warning, - "Setting 'always_on_top' requires SDL 2.0.16+", - 1) == -1) { + if (pgWarn(PyExc_Warning, "Setting 'always_on_top' requires SDL 2.0.16+", + 1, 0) == -1) { return -1; } #endif // SDL_VERSION_ATLEAST(2, 0, 16) @@ -565,8 +564,8 @@ window_set_mouse_rect(pgWindowObject *self, PyObject *arg, void *v) return -1; } #else - if (PyErr_WarnEx(PyExc_Warning, - "Setting 'mouse_rect' requires SDL 2.0.18+", 1) == -1) { + if (pgWarn(PyExc_Warning, "Setting 'mouse_rect' requires SDL 2.0.18+", 1, + 0) == -1) { return -1; } #endif // SDL_VERSION_ATLEAST(2, 0, 18) @@ -582,8 +581,8 @@ window_get_mouse_rect(pgWindowObject *self, void *v) Py_RETURN_NONE; return pgRect_New((SDL_Rect *)mouse_rect_p); #else - if (PyErr_WarnEx(PyExc_Warning, - "Getting 'mouse_rect' requires SDL 2.0.18+", 1) == -1) { + if (pgWarn(PyExc_Warning, "Getting 'mouse_rect' requires SDL 2.0.18+", 1, + 0) == -1) { return NULL; } Py_RETURN_NONE; @@ -907,10 +906,10 @@ window_init(pgWindowObject *self, PyObject *args, PyObject *kwargs) #if SDL_VERSION_ATLEAST(2, 0, 16) flags |= SDL_WINDOW_KEYBOARD_GRABBED; #else - if (PyErr_WarnEx(PyExc_Warning, - "Keyword 'keyboard_grabbed' requires " - "SDL 2.0.16+", - 1) == -1) { + if (pgWarn(PyExc_Warning, + "Keyword 'keyboard_grabbed' requires " + "SDL 2.0.16+", + 1, 0) == -1) { return -1; } #endif @@ -1040,11 +1039,11 @@ window_init(pgWindowObject *self, PyObject *args, PyObject *kwargs) static PyObject * window_from_display_module(PyTypeObject *cls, PyObject *_null) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Please use Window.get_surface and Window.flip to use " - "surface-rendering with Window. This method will be " - "removed in a future version.", - 1) == -1) { + if (pgWarn(PyExc_DeprecationWarning, + "Please use Window.get_surface and Window.flip to use " + "surface-rendering with Window. This method will be " + "removed in a future version.", + 1, 1) == -1) { return NULL; } diff --git a/src_py/__init__.py b/src_py/__init__.py index bce9fe3ebb..7c8598a7c8 100644 --- a/src_py/__init__.py +++ b/src_py/__init__.py @@ -51,40 +51,6 @@ def _attribute_undefined(name): raise RuntimeError(f"{name} is not available") -class MissingModule: - _NOT_IMPLEMENTED_ = True - - def __init__(self, name, urgent=0): - self.name = name - exc_type, exc_msg = sys.exc_info()[:2] - self.info = str(exc_msg) - self.reason = f"{exc_type.__name__}: {self.info}" - self.urgent = urgent - if urgent: - self.warn() - - def __getattr__(self, var): - if not self.urgent: - self.warn() - self.urgent = 1 - missing_msg = f"{self.name} module not available ({self.reason})" - raise NotImplementedError(missing_msg) - - def __bool__(self): - return False - - def warn(self): - msg_type = "import" if self.urgent else "use" - message = f"{msg_type} {self.name}: {self.info}\n({self.reason})" - try: - import warnings - - level = 4 if self.urgent else 3 - warnings.warn(message, RuntimeWarning, level) - except ImportError: - print(message) - - # This is a special loader for WebAssembly platform # where pygame is in fact statically linked # mixing single phase (C) and multiphase modules (cython) @@ -127,6 +93,8 @@ def warn(self): from pygame.base import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] from pygame.constants import * # now has __all__ pylint: disable=wildcard-import; lgtm[py/polluting-import] from pygame.version import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] + + from pygame.rect import Rect, FRect from pygame.rwobject import encode_string, encode_file_path import pygame.surflock @@ -143,6 +111,42 @@ def warn(self): from pygame.base import __version__ +pygame.base.set_warnings_filter(1) + + +class MissingModule: + _NOT_IMPLEMENTED_ = True + + def __init__(self, name, urgent=0): + self.name = name + exc_type, exc_msg = sys.exc_info()[:2] + self.info = str(exc_msg) + self.reason = f"{exc_type.__name__}: {self.info}" + self.urgent = urgent + if urgent: + self.warn() + + def __getattr__(self, var): + if not self.urgent: + self.warn() + self.urgent = 1 + missing_msg = f"{self.name} module not available ({self.reason})" + raise NotImplementedError(missing_msg) + + def __bool__(self): + return False + + def warn(self): + msg_type = "import" if self.urgent else "use" + message = f"{msg_type} {self.name}: {self.info}\n({self.reason})" + try: + level = 3 if self.urgent else 2 + urgency = 0 if self.urgent else 1 + warn(message, urgency, level=level) + except ImportError: + print(message) + + # next, the "standard" modules # we still allow them to be missing for stripped down pygame distributions try: diff --git a/src_py/_sprite.py b/src_py/_sprite.py index 941db11504..eab296d604 100644 --- a/src_py/_sprite.py +++ b/src_py/_sprite.py @@ -1,9 +1,9 @@ -import warnings +from pygame import warn -warnings.warn( +warn( "The ._sprite submodule is deprecated since 2.4.0. Please use pygame.sprite instead.", + urgency=1, category=DeprecationWarning, - stacklevel=2, ) from pygame.sprite import ( diff --git a/src_py/camera.py b/src_py/camera.py index 2a5db6c4f2..3b2e63a20c 100644 --- a/src_py/camera.py +++ b/src_py/camera.py @@ -1,10 +1,9 @@ import os import platform import sys -import warnings from abc import ABC, abstractmethod -from pygame import error +from pygame import error, warn _is_init = False @@ -142,11 +141,11 @@ def init(backend=None): backend = backends[0] if backend is None else backend.lower() if backend not in backends: - warnings.warn( + warn( "We don't think this is a supported backend on this system, " "but we'll try it...", - Warning, - stacklevel=2, + urgency=2, + category=Warning, ) try: diff --git a/src_py/debug.py b/src_py/debug.py new file mode 100644 index 0000000000..ea2b2a322f --- /dev/null +++ b/src_py/debug.py @@ -0,0 +1,10 @@ +from pygame import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] + +set_warnings_filter(2) + +# TODO: Should we initialize here? +# pygame.print_debug_info() gives more information afterwards, +# but are there any side-effects of doing this? +init() + +print_debug_info() diff --git a/src_py/meson.build b/src_py/meson.build index 541c54cd69..44c75884ae 100644 --- a/src_py/meson.build +++ b/src_py/meson.build @@ -8,6 +8,7 @@ python_sources = files( 'camera.py', 'colordict.py', 'cursors.py', + 'debug.py', 'freetype.py', 'ftfont.py', 'locals.py', diff --git a/src_py/sndarray.py b/src_py/sndarray.py index 0791051eb8..8812a50163 100644 --- a/src_py/sndarray.py +++ b/src_py/sndarray.py @@ -37,11 +37,9 @@ if the sound sample type requests this. """ -from pygame import mixer +from pygame import mixer, warn import numpy -import warnings - __all__ = [ "array", @@ -97,12 +95,12 @@ def use_arraytype(arraytype): DEPRECATED - only numpy arrays are now supported. """ - warnings.warn( - DeprecationWarning( - "only numpy arrays are now supported, " - "this function will be removed in a " - "future version of the module" - ) + warn( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module", + urgency=1, + category=DeprecationWarning, ) arraytype = arraytype.lower() if arraytype != "numpy": @@ -114,12 +112,12 @@ def get_arraytype(): DEPRECATED - only numpy arrays are now supported. """ - warnings.warn( - DeprecationWarning( - "only numpy arrays are now supported, " - "this function will be removed in a " - "future version of the module" - ) + warn( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module", + urgency=1, + category=DeprecationWarning, ) return "numpy" @@ -129,11 +127,11 @@ def get_arraytypes(): DEPRECATED - only numpy arrays are now supported. """ - warnings.warn( - DeprecationWarning( - "only numpy arrays are now supported, " - "this function will be removed in a " - "future version of the module" - ) + warn( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module", + urgency=1, + category=DeprecationWarning, ) return ("numpy",) diff --git a/src_py/sprite.py b/src_py/sprite.py index 6f7f9e32dd..c6ac820c28 100644 --- a/src_py/sprite.py +++ b/src_py/sprite.py @@ -84,7 +84,6 @@ # specific ones that aren't quite so general but fit into common # specialized cases. -from warnings import warn from typing import Optional import pygame @@ -656,20 +655,20 @@ def __init__(self, *sprites): class RenderPlain(Group): def __init__(self, *sprites): super().__init__(*sprites) - warn( + pygame.warn( "This class is deprecated and will be removed in a future version.", - DeprecationWarning, - stacklevel=2, + urgency=1, + category=DeprecationWarning, ) class RenderClear(Group): def __init__(self, *sprites): super().__init__(*sprites) - warn( + pygame.warn( "This class is deprecated and will be removed in a future version.", - DeprecationWarning, - stacklevel=2, + urgency=1, + categry=DeprecationWarning, ) @@ -706,12 +705,12 @@ def draw(self, surface): class OrderedUpdates(RenderUpdates): def __init__(self, *sprites): super().__init__(*sprites) - warn( + pygame.warn( "OrderedUpdates is now just an alias to RenderUpdates, order of " "sprites is now maintained in all sprite Group classes. This " "class is deprecated and will be removed in a future version.", - DeprecationWarning, - stacklevel=2, + urgency=1, + category=DeprecationWarning, ) @@ -1345,9 +1344,10 @@ def set_timing_treshold(self, time_ms): Raises TypeError if time_ms is not int or float. """ - warn( + pygame.warn( "This function will be removed, use set_timing_threshold function instead", - DeprecationWarning, + urgency=1, + category=DeprecationWarning, ) self.set_timing_threshold(time_ms) diff --git a/src_py/surfarray.py b/src_py/surfarray.py index 9a1f7f4a63..20a0a7842a 100644 --- a/src_py/surfarray.py +++ b/src_py/surfarray.py @@ -37,12 +37,14 @@ blue. """ +from pygame import warn from pygame.pixelcopy import ( array_to_surface, surface_to_array, map_array as pix_map_array, make_surface as pix_make_surface, ) + import numpy from numpy import ( array as numpy_array, @@ -51,9 +53,6 @@ ndarray as numpy_ndarray, ) -import warnings # will be removed in the future - - # float96 not available on all numpy versions. numpy_floats = [ getattr(numpy, type_name) @@ -405,12 +404,12 @@ def use_arraytype(arraytype): DEPRECATED - only numpy arrays are now supported. """ - warnings.warn( - DeprecationWarning( - "only numpy arrays are now supported, " - "this function will be removed in a " - "future version of the module" - ) + warn( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module", + urgency=1, + category=DeprecationWarning, ) arraytype = arraytype.lower() if arraytype != "numpy": @@ -422,12 +421,12 @@ def get_arraytype(): DEPRECATED - only numpy arrays are now supported. """ - warnings.warn( - DeprecationWarning( - "only numpy arrays are now supported, " - "this function will be removed in a " - "future version of the module" - ) + warn( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module", + urgency=1, + category=DeprecationWarning, ) return "numpy" @@ -437,11 +436,11 @@ def get_arraytypes(): DEPRECATED - only numpy arrays are now supported. """ - warnings.warn( - DeprecationWarning( - "only numpy arrays are now supported, " - "this function will be removed in a " - "future version of the module" - ) + warn( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module", + urgency=1, + category=DeprecationWarning, ) return ("numpy",) diff --git a/src_py/sysfont.py b/src_py/sysfont.py index 8879f3e128..70a5f7a14e 100644 --- a/src_py/sysfont.py +++ b/src_py/sysfont.py @@ -19,13 +19,13 @@ # pete@shinners.org """sysfont, used in the font module to find system fonts""" -import warnings import os import sys import itertools import difflib from os.path import basename, dirname, exists, join, splitext +from pygame import warn from pygame.font import Font from pygame import __file__ as pygame_main_file @@ -220,20 +220,23 @@ def initsysfonts_unix(path="fc-list"): ) except FileNotFoundError: - warnings.warn( - f"'{path}' is missing, system fonts cannot be loaded on your platform" + warn( + f"'{path}' is missing, system fonts cannot be loaded on your platform", + urgency=0, ) except subprocess.TimeoutExpired: - warnings.warn( + warn( f"Process running '{path}' timed-out! System fonts cannot be loaded on " - "your platform" + "your platform", + urgency=0, ) except subprocess.CalledProcessError as e: - warnings.warn( + warn( f"'{path}' failed with error code {e.returncode}! System fonts cannot be " - f"loaded on your platform. Error log is:\n{e.stderr}" + f"loaded on your platform. Error log is:\n{e.stderr}", + urgency=0, ) else: @@ -471,10 +474,11 @@ def SysFont(name, size, bold=False, italic=False, constructor=None): else: if len(name) > 1: names = "', '".join(name) - warnings.warn( + warn( "None of the specified system fonts " f"('{names}') could be found. " - "Using the default font instead." + "Using the default font instead.", + urgency=2, ) else: # Identifies the closest matches to the font provided by @@ -487,10 +491,11 @@ def SysFont(name, size, bold=False, italic=False, constructor=None): else: match_text = "" - warnings.warn( + warn( f"The system font '{name[0]}' couldn't be " f"found. {match_text}" - "Using the default font instead." + "Using the default font instead.", + urgency=2, ) else: fontname = None diff --git a/test/base_test.py b/test/base_test.py index 0959295338..425f7da740 100644 --- a/test/base_test.py +++ b/test/base_test.py @@ -613,6 +613,42 @@ def test_get_init__after_quit(self): self.assertFalse(pygame.get_init()) + def test_get_set_warnings_filter(self): + filters = [-1, 0, 1, 2] + for num in filters: + pygame.set_warnings_filter(num) + self.assertEqual(num, pygame.get_warnings_filter()) + + def _warn(self, message, urgency): + pygame.warn(message, urgency) + + def test_warn(self): + # For pygame.warn + pygame.set_warnings_filter(1) + with self.assertWarns(Warning) as cx: + self._warn("message", 0) + self.assertEqual(len(cx.warnings), 1) + warning = cx.warnings[0] + self.assertEqual(str(warning.message), "message (urgent: 0)") + self.assertIn("base_test.py", warning.filename) + + with self.assertWarns(UserWarning) as cx: + pygame.warn("message", 0, level=0) + self.assertEqual(len(cx.warnings), 1) + self.assertIn("base_test.py", cx.warnings[0].filename) + + with self.assertWarns(DeprecationWarning): + pygame.warn("message2", 1, category=DeprecationWarning) + + with self.assertRaises(self.failureException): + with self.assertWarns(Warning): + pygame.warn("message3", 2) + + with self.assertRaises(self.failureException): + pygame.set_warnings_filter(-1) + with self.assertWarns(Warning): + pygame.warn("message4", 0) + if __name__ == "__main__": unittest.main() diff --git a/test/color_test.py b/test/color_test.py index a34424e957..a4f1d0b014 100644 --- a/test/color_test.py +++ b/test/color_test.py @@ -7,6 +7,8 @@ import pygame from pygame.colordict import THECOLORS +pygame.set_warnings_filter(2) + IS_PYPY = "PyPy" == platform.python_implementation() ################################### CONSTANTS ################################## diff --git a/test/display_test.py b/test/display_test.py index 5d5150fc91..e2dfe2583f 100644 --- a/test/display_test.py +++ b/test/display_test.py @@ -9,6 +9,8 @@ from pygame import display +pygame.set_warnings_filter(2) + class DisplayModuleTest(unittest.TestCase): default_caption = "pygame window" diff --git a/test/image_test.py b/test/image_test.py index 8bff1dd037..d7a88b7f20 100644 --- a/test/image_test.py +++ b/test/image_test.py @@ -18,6 +18,8 @@ _sdl_image_ver <= (2, 0, 5) and pygame.get_sdl_byteorder() == pygame.BIG_ENDIAN ) +pygame.set_warnings_filter(2) + def check_magic(f, magic_hexes): """Tests a given file to see if the magic hex matches.""" diff --git a/test/sprite_test.py b/test/sprite_test.py index 25415fce19..4362ad3f2e 100644 --- a/test/sprite_test.py +++ b/test/sprite_test.py @@ -7,6 +7,8 @@ from pygame import sprite +pygame.set_warnings_filter(2) + ################################# MODULE LEVEL ################################# diff --git a/test/surface_test.py b/test/surface_test.py index ca60ccb8e0..e602328d24 100644 --- a/test/surface_test.py +++ b/test/surface_test.py @@ -21,6 +21,7 @@ import itertools IS_PYPY = "PyPy" == platform.python_implementation() +pygame.set_warnings_filter(2) class SurfaceTypeTest(unittest.TestCase): diff --git a/test/sysfont_test.py b/test/sysfont_test.py index 4b45f018ef..b6d650fdf0 100644 --- a/test/sysfont_test.py +++ b/test/sysfont_test.py @@ -71,8 +71,11 @@ def test_initsysfonts_win32(self): def test_sysfont_warnings(self): import pygame.font + from pygame import get_warnings_filter, set_warnings_filter pygame.font.init() + old_filter = get_warnings_filter() + set_warnings_filter(2) with self.assertWarns(UserWarning): pygame.font.SysFont("non-existent font", 40) @@ -88,6 +91,8 @@ def test_sysfont_warnings(self): (bytes("non-existent font", "utf-8"), "non-existent font2"), 40 ) + set_warnings_filter(old_filter) + ############################################################################### diff --git a/test/transform_test.py b/test/transform_test.py index 5c96ca29fb..dde66781fd 100644 --- a/test/transform_test.py +++ b/test/transform_test.py @@ -10,6 +10,9 @@ from pygame.locals import * +pygame.set_warnings_filter(2) + + def show_image(s, images=[]): # pygame.display.init() size = s.get_rect()[2:]