From 58623452303ac0b40eea331dc9052b47b77e86e5 Mon Sep 17 00:00:00 2001 From: pmp-p Date: Mon, 25 Sep 2023 04:03:38 +0200 Subject: [PATCH] add nofix #116 workaround --- pygbag/__init__.py | 6 +-- pygbag/support/cross/__EMSCRIPTEN__.py | 3 -- pygbag/support/cross/aio/fetch.py | 11 ++--- pygbag/support/cross/aio/filelike.py | 8 ++-- pygbag/support/cross/aio/pep0723.py | 5 +-- pygbag/support/cross/aio/toplevel.py | 30 ++++++++----- pygbag/support/cross/aio/tracer.py | 3 +- pygbag/support/pythonrc.py | 61 ++++++++++++-------------- 8 files changed, 63 insertions(+), 64 deletions(-) diff --git a/pygbag/__init__.py b/pygbag/__init__.py index 0dc6a6e..82b2469 100644 --- a/pygbag/__init__.py +++ b/pygbag/__init__.py @@ -3,7 +3,7 @@ import sys # some Linux distro are stuck in the past. Better safe than sorry -sys.stdout.reconfigure(encoding='utf-8') +sys.stdout.reconfigure(encoding="utf-8") from pathlib import Path @@ -32,10 +32,12 @@ try: # embed builtin module handles I/O on wasm import embed + # aio function implemented only on stackless WaPy sched_yield except: import builtins + builtins.sched_yield = lambda: None import sys, traceback @@ -59,5 +61,3 @@ def ESC(*argv): def CSI(*argv): for arg in argv: ESC(f"[{arg}") - - diff --git a/pygbag/support/cross/__EMSCRIPTEN__.py b/pygbag/support/cross/__EMSCRIPTEN__.py index 88cd675..78698a0 100644 --- a/pygbag/support/cross/__EMSCRIPTEN__.py +++ b/pygbag/support/cross/__EMSCRIPTEN__.py @@ -37,7 +37,6 @@ def shed_yield(): builtins.__UPY__ = None - # force use a fixed, tested version of uasyncio to avoid non-determinism if __UPY__: sys.modules["sys"] = sys @@ -101,7 +100,6 @@ async def jsprom(prom): builtins.__EMSCRIPTEN__ = None - def init_platform(embed): # simulator won't run javascript for now if not hasattr(embed, "run_script"): @@ -159,7 +157,6 @@ def build(self, evt_name, jsondata): sys.print_exception(e) print(jsondata) - # def dispatchEvent async def rpc(self, method, *argv): import inspect diff --git a/pygbag/support/cross/aio/fetch.py b/pygbag/support/cross/aio/fetch.py index f994ae6..95c519a 100644 --- a/pygbag/support/cross/aio/fetch.py +++ b/pygbag/support/cross/aio/fetch.py @@ -38,12 +38,11 @@ def make_src_dst(base_url, base_path, path, target): dst = target.copy() dst.extend(path[1:]) - preload_list.append([ base_path + "/".join(path), "/".join(dst)]) + preload_list.append([base_path + "/".join(path), "/".join(dst)]) if debug: print(preload_list[-1], "write", current, last) for l in map(str.rstrip, tree.split("\n")): - if not silent: print("HTMLFS:", base_url, base_path, "=>", target) @@ -62,9 +61,9 @@ def make_src_dst(base_url, base_path, path, target): base_path, trail = map(str.strip, l.split(" ~", 1)) - base_path = base_path.strip('/') + base_path = base_path.strip("/") - trail = trail.strip('/') + trail = trail.strip("/") # set destination target = [trail] @@ -86,8 +85,7 @@ def make_src_dst(base_url, base_path, path, target): preload_list.append([base_url, "."]) continue - - if l.find(' ')<0: + if l.find(" ") < 0: continue pos, elem = l.rsplit(" ", 1) @@ -156,7 +154,6 @@ async def preload(chroot=None, chdir=True, silent=FS_SILENT, debug=FS_DEBUG, sta print(f"153: REMOTE {full_url} LOCAL: {filename}") if not filename.is_file(): - filename.parent.mkdir(parents=True, exist_ok=True) if sys.platform in ("emscripten", "wasi"): async with platform.fopen(full_url, "rb") as source: diff --git a/pygbag/support/cross/aio/filelike.py b/pygbag/support/cross/aio/filelike.py index 78bba58..76eba2a 100644 --- a/pygbag/support/cross/aio/filelike.py +++ b/pygbag/support/cross/aio/filelike.py @@ -2,7 +2,7 @@ import io import socket -import os #unlink +import os # unlink socket.setdefaulttimeout(0.0) @@ -75,7 +75,7 @@ async def __aexit__(self, *exc): try: os.unlink(self.tmpfile) except FileNotFoundError as e: - print("78: Async I/O error : file not found", self.url) + print("78: Async I/O error : file not found", self.url) del self.filelike, self.url, self.mode, self.tmpfile if __WASM__: @@ -88,7 +88,7 @@ async def __aenter__(self): try: content = await platform.jsiter(cf) except Exception as e: - print("91:",e) + print("91:", e) if "b" in self.mode: self.filelike = open(content, "rb") @@ -128,7 +128,7 @@ async def __aenter__(self): class sopen: - def __init__(self, url, mode, tmout): #=6): + def __init__(self, url, mode, tmout): # =6): self.host, port = url.rsplit(":", 1) self.port = int(port) if __WASM__ and __import__("platform").is_browser: diff --git a/pygbag/support/cross/aio/pep0723.py b/pygbag/support/cross/aio/pep0723.py index 7828c43..34e680e 100644 --- a/pygbag/support/cross/aio/pep0723.py +++ b/pygbag/support/cross/aio/pep0723.py @@ -158,7 +158,7 @@ async def async_repos(): Config.pkg_repolist.append(repo) if not aio.cross.simulator: - if window.location.href.startswith('https://pmp-p.ddns.net/pygbag'): + if window.location.href.startswith("https://pmp-p.ddns.net/pygbag"): print(" =============== REDIRECTION TO DEV HOST ================ ") for idx, repo in enumerate(PyConfig.pkg_repolist): repo["-CDN-"] = "https://pmp-p.ddns.net/archives/repo/" @@ -207,7 +207,7 @@ async def pip_install(pkg, sconf={}): wheel_pkg, wheel_hash = wheel_url.rsplit("/", 1)[-1].split("#", 1) await install_pkg(sconf, wheel_url, wheel_pkg) except: - print("INVALID", pkg, 'from',wheel_url) + print("INVALID", pkg, "from", wheel_url) async def parse_code(code, env): @@ -262,7 +262,6 @@ async def check_list(code=None, filename=None): # mandatory importlib.invalidate_caches() - if code is None: code = open(filename, "r").read() diff --git a/pygbag/support/cross/aio/toplevel.py b/pygbag/support/cross/aio/toplevel.py index 5a5a818..4ee20ac 100644 --- a/pygbag/support/cross/aio/toplevel.py +++ b/pygbag/support/cross/aio/toplevel.py @@ -44,9 +44,9 @@ def install(pkg_file, sconf=None): ) HISTORY.append(pkg_file) except FileExistsError: - print(f"38: {pkg_file} already installed") + print(f"47: {pkg_file} already installed") except Exception as ex: - pdb(f"82: cannot install {pkg_file}") + pdb(f"49: cannot install {pkg_file}") sys.print_exception(ex) @@ -72,7 +72,7 @@ async def get_repo_pkg(pkg_file, pkg, resume, ex): try: aio.toplevel.install(pkg_file, sconf) except Exception as rx: - pdb(f"failed to install {pkg_file}") + pdb(f"75: failed to install {pkg_file}") sys.print_exception(rx) # let wasm compilation happen @@ -87,10 +87,10 @@ async def get_repo_pkg(pkg_file, pkg, resume, ex): pdb(f"failed to preload {pkg_file}") sys.print_exception(rx) else: - print(f"84: {pkg_file} already installed") + print(f"90: {pkg_file} already installed") if pkg in platform.patches: - print("88:", pkg, "requires patching") + print("93:", pkg, "requires patching") platform.patches.pop(pkg)() if resume and ex: @@ -212,6 +212,10 @@ def prompt(self): embed.prompt() async def interact(self): + + # multiline input clumsy sentinel + last_line = "" + try: sys.ps1 except AttributeError: @@ -241,17 +245,22 @@ async def interact(self): break else: if self.push(self.line): - prompt = sys.ps2 - if embed: - embed.set_ps2() - self.one_liner = False + if self.one_liner: + prompt = sys.ps2 + if embed: + embed.set_ps2() + print("Sorry, multi line input editing is not supported", file=sys.stderr) + self.one_liner = False + self.resetbuffer() + else: + continue else: prompt = sys.ps1 except KeyboardInterrupt: self.write("\nKeyboardInterrupt\n") self.resetbuffer() - more = 0 + self.one_liner = True if aio.exit: return @@ -275,6 +284,7 @@ async def interact(self): sys.print_exception(ex) self.prompt() + aio.exit_now(0) @classmethod diff --git a/pygbag/support/cross/aio/tracer.py b/pygbag/support/cross/aio/tracer.py index 222d09c..bf341db 100644 --- a/pygbag/support/cross/aio/tracer.py +++ b/pygbag/support/cross/aio/tracer.py @@ -29,7 +29,7 @@ def calls(frame, event, arg): co = frame.f_code func_name = co.co_name - if func_name in ("write","raw_input","process"): + if func_name in ("write", "raw_input", "process"): return func_line_no = frame.f_lineno func_filename = co.co_filename @@ -40,7 +40,6 @@ def calls(frame, event, arg): if func_filename.find("/aio/") > 0: return - caller = frame.f_back if caller: caller_line_no = caller.f_lineno diff --git a/pygbag/support/pythonrc.py b/pygbag/support/pythonrc.py index 1799736..e40cfc1 100644 --- a/pygbag/support/pythonrc.py +++ b/pygbag/support/pythonrc.py @@ -61,9 +61,10 @@ def overloaded(i, *attrs): def DBG(*argv): - if PyConfig.dev_mode>0: + if PyConfig.dev_mode > 0: print(*argv) + try: # mpy already has execfile execfile @@ -494,6 +495,7 @@ def dll(cls, *argv): @classmethod def strace(cls, *argv, **env): import aio.tracer + print("497: trace on") sys.settrace(aio.tracer.calls) return True @@ -624,7 +626,7 @@ async def preload_code(cls, code, callback=None, hint=""): # don't use an env path, but site-packages instead # we can only do purelib for now until pypi host wasm wheels sconf = __import__("sysconfig").get_paths() - env = Path( sconf["purelib"] ) + env = Path(sconf["purelib"]) DBG(f"628: aio.pep0723.check_list {env=}") deps = await aio.pep0723.parse_code(code, env) @@ -632,13 +634,11 @@ async def preload_code(cls, code, callback=None, hint=""): for dep in deps: await aio.pep0723.pip_install(dep) - else: # sim use a local folder venv model - + else: # sim use a local folder venv model await aio.pep0723.check_list(code=code, filename=None) - await TopLevel_async_handler.async_imports(callback, *maybe_wanted) -# await TopLevel_async_handler.async_imports(callback, *TopLevel_async_handler.list_imports(code, file=None)) + # await TopLevel_async_handler.async_imports(callback, *TopLevel_async_handler.list_imports(code, file=None)) PyConfig.imports_ready = True return True @@ -665,7 +665,6 @@ def interactive(cls, prompt=False): @classmethod async def runpy(cls, main, *args, **kw): - def check_code(file_name): nonlocal code maybe_sync = False @@ -696,7 +695,7 @@ def check_code(file_name): code = "" shell.pgzrunning = None DBG(f"690: : runpy({main=})") -# REMOVE THAT IT SHOULD BE DONE IN SIM ANALYSER AND HANDLED PROPERLY + # REMOVE THAT IT SHOULD BE DONE IN SIM ANALYSER AND HANDLED PROPERLY if not check_code(main): for base in ("pygame", "pg"): for func in ("flip", "update"): @@ -711,8 +710,8 @@ def check_code(file_name): cls.HOME = Path(realpath).parent os.chdir(cls.HOME) -# TODO: should be $0 / sys.argv[0] from there and while running - kw.setdefault('hint', main) + # TODO: should be $0 / sys.argv[0] from there and while running + kw.setdefault("hint", main) # get requirements await cls.preload_code(code, **kw) @@ -725,7 +724,7 @@ def check_code(file_name): shell.debug() await TopLevel_async_handler.start_toplevel(platform.shell, console=True) -# TODO: check if that thing really works + # TODO: check if that thing really works if shell.pgzrunning: DBG("728 : pygame zero detected") __main__ = __import__("__main__") @@ -848,6 +847,7 @@ async def exec(cls, sub, **env): platform.shell = shell import aio.filelike + platform.fopen = aio.filelike.fopen platform.sopen = aio.filelike.sopen @@ -964,7 +964,6 @@ def urlretrieve(maybe_url, filename=None, reporthook=None, data=None): from platform import window, document, ffi - apply_patches() del apply_patches @@ -1008,7 +1007,7 @@ class TopLevel_async_handler(aio.toplevel.AsyncInteractiveConsole): # ignore += ["ursina","gltf","pyperclip","screeninfo"] manual_deps = { - "matplotlib" : ["numpy", "six", "cycler", "PIL", "pygame-ce"], + "matplotlib": ["numpy", "six", "cycler", "PIL", "pygame-ce"], "bokeh": ["numpy", "yaml", "typing_extensions", "jinja2", "markupsafe"], "igraph": ["texttable"], "pygame_gui": ["i18n"], @@ -1135,7 +1134,6 @@ def list_imports(cls, code=None, file=None, hint=""): else: pdb("1134: no pkg repository available") - # TODO: re order repo on failures # TODO: try to download from pypi with # https://github.com/brettcannon/mousebender/blob/main/mousebender/simple.py @@ -1172,12 +1170,14 @@ def import_one(cls, mod, lvl=0): if mod in cls.manual_deps: deps = list(cls.manual_deps[mod]) deps.reverse() - DBG(f""" + DBG( + f""" 1176: added {deps=} for {mod=} {cls.missing_fence=} -""") +""" + ) for missing in deps: if missing in cls.missing_fence: continue @@ -1193,7 +1193,7 @@ def import_one(cls, mod, lvl=0): wants.insert(0, missing) DBG(f"1108: added {missing=} for {mod=}") - wants.append( mod ) + wants.append(mod) return wants @classmethod @@ -1222,7 +1222,6 @@ def imports(cls, *mods, lvl=0): return wants - @classmethod async def async_get_pkg(cls, want, ex, resume): pkg_file = "" @@ -1279,12 +1278,12 @@ async def async_imports_init(cls): if not len(PyConfig.pkg_repolist): await cls.async_repos() - if window.location.href.startswith('https://pmp-p.ddns.net/pygbag/'): + if window.location.href.startswith("https://pmp-p.ddns.net/pygbag/"): print(" =============== REDIRECTION TO DEV HOST ================ ") for idx, repo in enumerate(PyConfig.pkg_repolist): repo["-CDN-"] = "https://pmp-p.ddns.net/archives/repo/" elif PyConfig.pygbag > 0: -# if PyConfig.pygbag > 0: + # if PyConfig.pygbag > 0: for idx, repo in enumerate(PyConfig.pkg_repolist): DBG("1264:", repo["-CDN-"], "REMAPPED TO", PyConfig.pkg_indexes[-1]) repo["-CDN-"] = PyConfig.pkg_indexes[-1] @@ -1305,7 +1304,6 @@ def default_cb(pkg, error=None): print("1302: ============= ", wanted) - wants = cls.imports(*wanted) all = list(cls.missing_fence) print("1305: PRE REQ ", cls.missing_fence) @@ -1320,9 +1318,8 @@ async def import_now(mod): await cls.async_get_pkg(mod, None, None) __import__(mod) - # always put numpy first - await import_now('numpy') + await import_now("numpy") # pygame must be early for plotting if ("matplotlib" in all) and ("pygame" not in sys.modules): @@ -1377,11 +1374,11 @@ def print_pg_bar(total, iteration): @classmethod async def async_repos(cls): abitag = f"cp{sys.version_info.major}{sys.version_info.minor}" - apitag = __import__('sysconfig').get_config_var('HOST_GNU_TYPE') - apitag = apitag.replace('-','_') + apitag = __import__("sysconfig").get_config_var("HOST_GNU_TYPE") + apitag = apitag.replace("-", "_") for repo in PyConfig.pkg_indexes: - if apitag.find('mvp')>0: + if apitag.find("mvp") > 0: idx = f"{repo}index.json" else: idx = f"{repo}index-bi.json" @@ -1628,9 +1625,10 @@ def patch_panda3d_showbase(): def run(*argv, **env): print("ShowBase.run patched to launch asyncio.run(main())") import direct.task.TaskManagerGlobal + async def main(): try: - print('1633: auto resizing') + print("1633: auto resizing") platform.window.window_resize() except: ... @@ -1638,10 +1636,11 @@ async def main(): try: direct.task.TaskManagerGlobal.taskMgr.step() except SystemExit: - print('87: Panda3D stopped',file= sys.stderr) + print("87: Panda3D stopped", file=sys.stderr) break # go to host await asyncio.sleep(0) + asyncio.run(main()) print("panda3d: apply ShowBase.run patch") @@ -1759,15 +1758,15 @@ async def import_site(__file__, run=True): # if not imported by simulator then aio is handled externally if "pygbag.aio" not in sys.modules: import aio + sys.modules["pygbag.aio"] = aio # if running a script be silent for prompt - TopLevel_async_handler.mute_state = '.py' in ''.join(sys.argv) + TopLevel_async_handler.mute_state = ".py" in "".join(sys.argv) # always start async handler or we could not do imports on import errors. await TopLevel_async_handler.start_toplevel(platform.shell, console=True) - # RUNNING GIVEN DISK FILE with no prompt # this is usually the import site given by javascript loader or a template loader (pygbag apk mode) # or the user script (script mode). @@ -1787,7 +1786,6 @@ async def import_site(__file__, run=True): else: DBG(f"1767: {__file__=} NOT FOUND : now trying user sources") - # NOW CHECK OTHER SOURCES # where to retrieve @@ -1795,7 +1793,6 @@ async def import_site(__file__, run=True): tmpdir = Path(tempfile.gettempdir()) - # maybe a script filename or content passed as frozen config. source = getattr(PyConfig, "frozen", "")