@@ -11,6 +11,7 @@ from typing import (
1111 Union ,
1212)
1313
14+ # use typing_extensions for compatibility with older Python versions
1415if sys .version_info >= (3 , 13 ):
1516 from warnings import deprecated
1617else :
@@ -26,9 +27,6 @@ from pygame.rect import FRect, Rect
2627from pygame .surface import Surface
2728from pygame .typing import Point , RectLike
2829
29- # generic Group, used in Sprite
30- _TGroup = TypeVar ("_TGroup" , bound = AbstractGroup )
31-
3230# define some useful protocols first, which sprite functions accept
3331# sprite functions don't need all sprite attributes to be present in the
3432# arguments passed, they only use a few which are marked in the below protocols
@@ -49,7 +47,11 @@ class _HasMaskAndRect(_HasRect, Protocol):
4947class _HasRadiusAndRect (_HasRect , Protocol ):
5048 radius : float
5149
50+ # generic Group, used in Sprite
51+ _TGroup = TypeVar ("_TGroup" , bound = AbstractGroup )
52+
5253# protocol helps with structural subtyping for typevars in sprite group generics
54+ # and allows the use of any class with the required attributes and methods
5355class _SupportsSprite (Generic [_TGroup ], _HasImageAndRect , Protocol ):
5456 def __class_getitem__ (cls , item : type [AbstractGroup ], / ) -> types .GenericAlias : ...
5557 @property
@@ -125,28 +127,9 @@ _TSprite2 = TypeVar("_TSprite2", bound=_SupportsSprite)
125127# almost the same as _TSprite but bound to DirtySprite
126128_TDirtySprite = TypeVar ("_TDirtySprite" , bound = _SupportsDirtySprite )
127129
130+ # typevar for sprite or iterable of sprites, used in Group init, add and remove
128131_SpriteOrIterable = Union [_TSprite , Iterable [_SpriteOrIterable ]]
129132
130- # Below code demonstrates the advantages of the _SupportsSprite protocol
131-
132- # typechecker should error, regular Sprite does not support Group.draw due to
133- # missing image and rect attributes
134- # a = Group(Sprite())
135-
136- # typechecker should error, other Sprite attributes are also needed for Group
137- # class MySprite:
138- # image: Surface
139- # rect: Rect
140- #
141- # b = Group(MySprite())
142-
143- # typechecker should pass
144- # class MySprite(Sprite):
145- # image: Surface
146- # rect: Rect
147- #
148- # b = Group(MySprite())
149-
150133class AbstractGroup (Generic [_TSprite ]):
151134 spritedict : dict [_TSprite , Optional [Union [FRect , Rect ]]]
152135 lostsprites : list [Union [FRect , Rect ]]
@@ -223,9 +206,7 @@ class LayeredDirty(LayeredUpdates[_TDirtySprite]):
223206 def repaint_rect (self , screen_rect : RectLike ) -> None : ...
224207 def set_clip (self , screen_rect : Optional [RectLike ] = None ) -> None : ...
225208 def get_clip (self ) -> Union [FRect , Rect ]: ...
226- def set_timing_threshold (
227- self , time_ms : SupportsFloat
228- ) -> None : ... # This actually accept any value
209+ def set_timing_threshold (self , time_ms : SupportsFloat ) -> None : ...
229210 @deprecated (
230211 "since 2.1.1. Use `pygame.sprite.LayeredDirty.set_timing_threshold` instead"
231212 )
@@ -261,12 +242,13 @@ class collide_circle_ratio:
261242# addition to mandatorily having a rect attribute
262243_SupportsCollideMask = Union [_HasImageAndRect , _HasMaskAndRect ]
263244
264- # generic for _HasRect, used in sprite collide functions
265- _THasRect = TypeVar ("_THasRect" , bound = _HasRect )
266-
267245def collide_mask (
268246 left : _SupportsCollideMask , right : _SupportsCollideMask
269247) -> Optional [tuple [int , int ]]: ...
248+
249+ # generic for _HasRect, used in sprite collide functions
250+ _THasRect = TypeVar ("_THasRect" , bound = _HasRect )
251+
270252def spritecollide (
271253 sprite : _THasRect ,
272254 group : AbstractGroup [_TSprite ],
0 commit comments