From 2ad6b83b94c29b5f66db126ef79abc4b042520bf Mon Sep 17 00:00:00 2001 From: Notenlish <71970100+Notenlish@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:11:47 +0000 Subject: [PATCH 1/3] add warning for pep 723 --- src/pygbag/app.py | 26 +++++- test/main-pygbag.py | 208 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 test/main-pygbag.py diff --git a/src/pygbag/app.py b/src/pygbag/app.py index 15a8d51..b422517 100644 --- a/src/pygbag/app.py +++ b/src/pygbag/app.py @@ -31,6 +31,7 @@ from . import pack from . import web from .config_types import Config +from src.pygbag.support.cross.aio.pep0723 import read_dependency_block_723 from config_to_object import load_config @@ -87,6 +88,11 @@ DEFAULT_WIDTH = 1280 DEFAULT_HEIGHT = 720 +from colorama import Fore + +def warn(msg): + print(f"{Fore.RED}WARNING!{Fore.RESET} ${msg}") + def set_args(program): global DEFAULT_SCRIPT @@ -195,7 +201,25 @@ def make_cache_dirs(): async def main_run(app_folder, mainscript, cdn=DEFAULT_CDN): global DEFAULT_PORT, DEFAULT_SCRIPT, APP_CACHE, required - + + # Checks for existance of PEP 723 header on main.py https://peps.python.org/pep-0723/ + main_file = Path(app_folder, mainscript) + with open(main_file, "r") as f: + src_code = f.read() + + has_pep723 = False + deps = {"pygame-ce"} + for dep in read_dependency_block_723(src_code): + has_pep723 = True + if dep == "pygame-ce": + pass + elif dep == "pygame": + warn("Pygbag uses pygame-ce for running on web. If you're using pygame, you should probably upgrade to pygame-ce, it is backwards compatible so your code will still work. If you're using pygame-ce already, specify 'pygame-ce' instead of 'pygame'.") + else: + deps.add(dep) + if not has_pep723: + warn("Couldn't find PEP 723 Header. See this: https://pygame-web.github.io/wiki/pygbag/#complex-packages") + DEFAULT_SCRIPT = mainscript or DEFAULT_SCRIPT build_dir, cache_dir = cache_check(app_folder, devmode) diff --git a/test/main-pygbag.py b/test/main-pygbag.py new file mode 100644 index 0000000..52a4dd0 --- /dev/null +++ b/test/main-pygbag.py @@ -0,0 +1,208 @@ +# this test is only for pygbag internals +# to learn about pygbag, go to https://pygame-web.github.io instead. + +# Green threads are ordered at runtime unlike system threads. +# they may be usefull for ECS and porting software to async web. + +# on native, this test show how threading model can be toxic for drawing. +# do not use this code : +# hardware threads are better used for I/O, neural net, pipelines + + +import builtins + +# fixme should be auto +if __import__("os").uname().machine.startswith("wasm"): + import aio.gthread as threading + +else: + # native case + + import asyncio as aio + aio.exit = False + aio.frame = 1.0/60 + aio.sync = False + + # because threading target= does not handle generators + def synchronized(f): + def run(*argv,**kw): + global Native + gen = f(*argv,**kw) + while True: + deadline = time.time()+aio.frame + if next(gen) is StopIteration: + return + alarm = deadline - time.time() + if alarm>0: + time.sleep(alarm) + return run + + +import asyncio +import pygame +import time + +pygame.init() + +import module + +print() +print(f"{aio=} {aio.sync=}") +print() + + +def new_screen(title): + global screen + pygame.display.set_caption(title) + screen = pygame.display.set_mode((640, 360)) + return screen + + +from threading import Thread + + +class Moving_svg(Thread): + + def __init__(self): + super().__init__() + print(f"{self.native_id=} {self.ident=} {self.is_alive()=}") + self.surf = pygame.image.load("img/tiger.svg") + self.way = 1 + self.auth = False + + def loop(self): + decal = abs(count) % 100 + if not decal: + self.way = -self.way + self.win.blit(self.surf, (50 + (self.way * decal), 50 + (-self.way * decal))) + + + @synchronized + def run(self): + print(f"{self.native_id=} {self.ident=} {self.is_alive()=}") + while self: + if self.auth: + self.loop() + self.auth = False + yield aio + + +# ok model +moving_svg = None + +@synchronized +def color_background(win): + global moving_svg, count + while not aio.exit: + if 1: + if moving_svg: + if not moving_svg.auth: + win.fill((count % 50, count % 50, count % 50)) + moving_svg.auth = True + else: + win.fill((count % 50, count % 50, count % 50)) + yield aio + + +@synchronized +def moving_bmp(win): + global count + print("moving_bmp started") + bmp = pygame.image.load_basic("img/pygc.png") + way = 1 + while not aio.exit: + decal = abs(count) % 100 + if not decal: + way = -way + + win.blit(bmp, (50 + (way * decal), 50 + (-way * decal))) + yield aio + +@synchronized +def moving_png(win): + global count + print("moving_png started") + try: + png = pygame.image.load("img/pygc.png") + except: + print("png support error upgrade SDL_image !") + return + + way = 1 + while not aio.exit: + decal = abs(count) % 100 + if not decal: + way = -way + + win.blit(png, (200 + (way * decal), 100 + (way * decal))) + yield aio + + +async def main(): + global count, bmp, moving_svg + + # using the whole display. + win = new_screen("TEST") + + count = 3 + + # still bugs in that thread model + # mbmp = Moving_bmp() + + + # erase and fill + (t1:=Thread(target=color_background, args=[win])).start() + + + + moving_svg = Moving_svg() + moving_svg.win = win + print(f"{moving_svg.native_id=} {moving_svg.ident=} {moving_svg.is_alive()=}") + moving_svg.start() + + + # 1st object to draw + t2=Thread(target=moving_bmp, args=[win]) + t2.start() + + # 2nd + + t3=Thread(target=moving_png, args=[win]) + t3.start() + + + print( t1.native_id , t2.native_id , t3.native_id) + + + + while True: + if count >= 0: + print( + f""" + + Hello[{count}] from Pygame + +""" + ) + +# if moving_svg and moving_svg.native_id: +# moving_svg.loop() + + pygame.display.update() + + if not aio.sync: + time.sleep(aio.frame) # frametime idle + + await asyncio.sleep(0) + + + if count < -60 * 30: # about * seconds + print("exit game loop") + break + + count = count - 1 + + pygame.quit() + + +asyncio.run(main()) From f440e7458cde6728c7a66c37284a9e7d4bd82d43 Mon Sep 17 00:00:00 2001 From: Notenlish <71970100+Notenlish@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:17:30 +0000 Subject: [PATCH 2/3] import error fixed --- src/pygbag/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygbag/app.py b/src/pygbag/app.py index b422517..acfdb9b 100644 --- a/src/pygbag/app.py +++ b/src/pygbag/app.py @@ -31,7 +31,7 @@ from . import pack from . import web from .config_types import Config -from src.pygbag.support.cross.aio.pep0723 import read_dependency_block_723 +from .support.cross.aio.pep0723 import read_dependency_block_723 from config_to_object import load_config From 61e52172f11efb86e6853af01b0da5d7996b2f0c Mon Sep 17 00:00:00 2001 From: Notenlish <71970100+Notenlish@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:25:15 +0000 Subject: [PATCH 3/3] remove useless main-pygbag.py file --- test/main-pygbag.py | 208 -------------------------------------------- 1 file changed, 208 deletions(-) delete mode 100644 test/main-pygbag.py diff --git a/test/main-pygbag.py b/test/main-pygbag.py deleted file mode 100644 index 52a4dd0..0000000 --- a/test/main-pygbag.py +++ /dev/null @@ -1,208 +0,0 @@ -# this test is only for pygbag internals -# to learn about pygbag, go to https://pygame-web.github.io instead. - -# Green threads are ordered at runtime unlike system threads. -# they may be usefull for ECS and porting software to async web. - -# on native, this test show how threading model can be toxic for drawing. -# do not use this code : -# hardware threads are better used for I/O, neural net, pipelines - - -import builtins - -# fixme should be auto -if __import__("os").uname().machine.startswith("wasm"): - import aio.gthread as threading - -else: - # native case - - import asyncio as aio - aio.exit = False - aio.frame = 1.0/60 - aio.sync = False - - # because threading target= does not handle generators - def synchronized(f): - def run(*argv,**kw): - global Native - gen = f(*argv,**kw) - while True: - deadline = time.time()+aio.frame - if next(gen) is StopIteration: - return - alarm = deadline - time.time() - if alarm>0: - time.sleep(alarm) - return run - - -import asyncio -import pygame -import time - -pygame.init() - -import module - -print() -print(f"{aio=} {aio.sync=}") -print() - - -def new_screen(title): - global screen - pygame.display.set_caption(title) - screen = pygame.display.set_mode((640, 360)) - return screen - - -from threading import Thread - - -class Moving_svg(Thread): - - def __init__(self): - super().__init__() - print(f"{self.native_id=} {self.ident=} {self.is_alive()=}") - self.surf = pygame.image.load("img/tiger.svg") - self.way = 1 - self.auth = False - - def loop(self): - decal = abs(count) % 100 - if not decal: - self.way = -self.way - self.win.blit(self.surf, (50 + (self.way * decal), 50 + (-self.way * decal))) - - - @synchronized - def run(self): - print(f"{self.native_id=} {self.ident=} {self.is_alive()=}") - while self: - if self.auth: - self.loop() - self.auth = False - yield aio - - -# ok model -moving_svg = None - -@synchronized -def color_background(win): - global moving_svg, count - while not aio.exit: - if 1: - if moving_svg: - if not moving_svg.auth: - win.fill((count % 50, count % 50, count % 50)) - moving_svg.auth = True - else: - win.fill((count % 50, count % 50, count % 50)) - yield aio - - -@synchronized -def moving_bmp(win): - global count - print("moving_bmp started") - bmp = pygame.image.load_basic("img/pygc.png") - way = 1 - while not aio.exit: - decal = abs(count) % 100 - if not decal: - way = -way - - win.blit(bmp, (50 + (way * decal), 50 + (-way * decal))) - yield aio - -@synchronized -def moving_png(win): - global count - print("moving_png started") - try: - png = pygame.image.load("img/pygc.png") - except: - print("png support error upgrade SDL_image !") - return - - way = 1 - while not aio.exit: - decal = abs(count) % 100 - if not decal: - way = -way - - win.blit(png, (200 + (way * decal), 100 + (way * decal))) - yield aio - - -async def main(): - global count, bmp, moving_svg - - # using the whole display. - win = new_screen("TEST") - - count = 3 - - # still bugs in that thread model - # mbmp = Moving_bmp() - - - # erase and fill - (t1:=Thread(target=color_background, args=[win])).start() - - - - moving_svg = Moving_svg() - moving_svg.win = win - print(f"{moving_svg.native_id=} {moving_svg.ident=} {moving_svg.is_alive()=}") - moving_svg.start() - - - # 1st object to draw - t2=Thread(target=moving_bmp, args=[win]) - t2.start() - - # 2nd - - t3=Thread(target=moving_png, args=[win]) - t3.start() - - - print( t1.native_id , t2.native_id , t3.native_id) - - - - while True: - if count >= 0: - print( - f""" - - Hello[{count}] from Pygame - -""" - ) - -# if moving_svg and moving_svg.native_id: -# moving_svg.loop() - - pygame.display.update() - - if not aio.sync: - time.sleep(aio.frame) # frametime idle - - await asyncio.sleep(0) - - - if count < -60 * 30: # about * seconds - print("exit game loop") - break - - count = count - 1 - - pygame.quit() - - -asyncio.run(main())