Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

About Pygame's "Sequence" object and display.update #2986

Open
Pousles opened this issue Jul 12, 2024 · 1 comment · May be fixed by #2987
Open

About Pygame's "Sequence" object and display.update #2986

Pousles opened this issue Jul 12, 2024 · 1 comment · May be fixed by #2987

Comments

@Pousles
Copy link

Pousles commented Jul 12, 2024

Sometimes I want to use "display.update" to update my screen. I would use dict.values() or chain() to improve performance , but it only receives an object which has "len" and "getitem". Through the test, I know some behavior the function will do.
For example, I use this py-code.

from typing import Generator, Generic, Iterable, Iterator, Protocol, Sequence, SupportsIndex,TypeVar, ValuesView
_T = TypeVar("_T",covariant=True)
class CanBeChained(Protocol[_T]):
    def __iter__(self)->Iterator[_T]:...
    def __len__(self) -> int: ...
class H_Chain(Generic[_T]):
    content:Sequence[CanBeChained[_T]]
    where:int=-1
    _len:int
    _generator:Generator[_T,None,None]
    def __init__(self,*canBeChained:CanBeChained[_T]) -> None:
        self.content=canBeChained
        self._len=sum(len(i) for i in canBeChained)
        self._generator=(elem for iterable in canBeChained for elem in iterable)
    def __getitem__(self,__i:SupportsIndex):
        print("GetItem",__i)
        return next(self._generator)
    def __len__(self):
        return self._len
    def __getattribute__(self, name: str):
        print("getattribute",name)
        return super().__getattribute__(name)
def test():
    display.update
    init();size=(300,300)
    sur=display.set_mode(size,RESIZABLE)
    l=H_Chain([None])#Pay attention here
    display.update(l)
if __name__=="__main__":
    test()

It will print something like this:

getattribute __class__
getattribute __class__
getattribute _len
getattribute rect
getattribute _len
GetItem 0
getattribute _generator

I can't understand why you can't make it generator compatible and why the "class" and "len" attributes were gotten twice, while there is one "getitem" between two "len" sometimes, which causes an error.

Fatal Python error: pygame_parachute: (pygame parachute) Segmentation Fault
Python runtime state: initialized

Current thread 0x0000346c (most recent call first):
  File "C:\Users\HDS\Desktop\py\Task\temp.py", line 31 in test
  File "C:\Users\HDS\Desktop\py\Task\temp.py", line 33 in <module>

Extension modules: win32api, _win32sysloader, pygame.base, pygame.constants, pygame.rect, pygame.rwobject, pygame.surflock, pygame.bufferproxy, pygame.math, pygame.surface, pygame.window, pygame.display, pygame.draw, pygame.joystick, pygame.event, pygame.imageext, pygame.image, pygame.key, pygame.mouse, pygame.time, pygame.mask, pygame.pixelcopy, pygame.transform, pygame.font, pygame.mixer_music, pygame.mixer, pygame.scrap, numpy.core._multiarray_umath, numpy.core._multiarray_tests, numpy.linalg._umath_linalg, numpy.fft._pocketfft_internal, numpy.random._common, numpy.random.bit_generator, numpy.random._bounded_integers, numpy.random._mt19937, numpy.random.mtrand, numpy.random._philox, numpy.random._pcg64, numpy.random._sfc64, numpy.random._generator, pygame.system, pygame._freetype (total: 42)

So, how to deal with this situation? I have only one botched solution.

class H_Chain(Generic[_T]):
    content:Sequence[CanBeChained[_T]]
    where:int=-1
    _len:int
    _generator:Generator[_T,None,None]
    def __init__(self,*canBeChained:CanBeChained[_T]) -> None:
        self.content=canBeChained
        self._len=sum(len(i) for i in canBeChained)
    def __getitem__(self,__i:SupportsIndex):
        if __i==0:self._generator=(elem for iterable in self.content for elem in iterable)
        return next(self._generator)
    def __len__(self):return self._len

That's not a method I'm happy with.(This is my first time filing an issue, and there will be many mistakes. Please forgive me.)
Looking forward to your early reply!

@Pousles Pousles changed the title About Pygame's "Sequence" object About Pygame's "Sequence" object and display.update Jul 12, 2024
@ankith26
Copy link
Member

Thanks for posting the issue.

Indeed, display.update doesn't support generators/iterables, and the type-hinting/docs also reflects the same. I believe this shouldn't be too hard to update to support generators/iterables

I couldn't reproduce the segmentation fault with your reproducer (I had to make some fixes to get it to run, it is currently missing the pygame import).

from typing import Generator, Generic, Iterable, Iterator, Protocol, Sequence, SupportsIndex,TypeVar, ValuesView
import pygame

_T = TypeVar("_T",covariant=True)
class CanBeChained(Protocol[_T]):
    def __iter__(self)->Iterator[_T]:...
    def __len__(self) -> int: ...
    
class H_Chain(Generic[_T]):
    content:Sequence[CanBeChained[_T]]
    where:int=-1
    _len:int
    _generator:Generator[_T,None,None]
    def __init__(self,*canBeChained:CanBeChained[_T]) -> None:
        self.content=canBeChained
        self._len=sum(len(i) for i in canBeChained)
        self._generator=(elem for iterable in canBeChained for elem in iterable)
    def __getitem__(self,__i:SupportsIndex):
        print("GetItem",__i)
        return next(self._generator)
    def __len__(self):
        return self._len
    def __getattribute__(self, name: str):
        print("getattribute",name)
        return super().__getattribute__(name)
        
def test():
    pygame.init()
    sur=pygame.display.set_mode((300,300),pygame.RESIZABLE)
    l=H_Chain([None])#Pay attention here
    pygame.display.update(l)

if __name__=="__main__":
    test()

@ankith26 ankith26 linked a pull request Jul 12, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants