Skip to content

Commit

Permalink
0.6.2 bugfix
Browse files Browse the repository at this point in the history
  • Loading branch information
pmp-p committed Jan 7, 2023
1 parent 85ae0a7 commit 28f3fbd
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 138 deletions.
2 changes: 1 addition & 1 deletion pygbag/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
""" packager+server for pygbag wasm loader """

__version__ = "0.7.0"
__version__ = "0.6.2"


# WaPy=>CPython compat
Expand Down
80 changes: 33 additions & 47 deletions pygbag/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,16 @@
print(f" *pygbag {__version__}*")

from pathlib import Path
from .app import main_run
from .app import main_run, set_args


async def custom_site():
async def import_site():
import sys
from pathlib import Path

required = []
patharg = Path(sys.argv[-1]).resolve()
mainscript = None
if patharg.is_file():
mainscript = patharg.name
app_folder = patharg.parent
else:
app_folder = patharg.resolve()

sys.path.insert(0, str(app_folder))

if not app_folder.is_dir() or patharg.as_posix().endswith("/pygbag/__main__.py"):
required.append(
"ERROR: Last argument must be app top level directory, or the main python script"
)
app_folder, mainscript = set_args(sys.argv[-1])

if sys.version_info < (3, 8):
# zip deflate compression level 3.7
# https://docs.python.org/3.11/library/shutil.html#shutil.copytree dirs_exist_ok = 3.8
required.append("pygbag requires CPython version >= 3.8")

if len(required):
while len(required):
print(required.pop())
sys.exit(1)

if not "--sim" in sys.argv:
if ("--sim" not in sys.argv) and ("--piny" not in sys.argv):
# run pygbag build/server
await main_run(app_folder, mainscript)
return True
Expand All @@ -57,12 +33,12 @@ async def custom_site():

sys.path.insert(0, str(support / "cross"))

try:
import pymunk4 as pymunk

sys.modules["pymunk"] = pymunk
except:
print("pymunk4 was not build for simulator")
# try:
# import pymunk4 as pymunk
#
# sys.modules["pymunk"] = pymunk
# except:
# print("pymunk4 was not build for simulator")

# need them earlier than aio

Expand Down Expand Up @@ -184,28 +160,38 @@ def eval(self, source):

ns["TopLevel_async_handler"] = TopLevel_async_handler

__import__(__name__).__file__ = sys.argv[-1]
sourcefile = sys.argv[-1]

__import__(__name__).__file__ = sourcefile

if "--piny" in sys.argv:
from . import mutator

mutator.transform_file(sourcefile, f"{sourcefile[:-3]}.pn")

else:

import aio.clock
import aio.clock

# asyncio.create_task( aio.clock.loop() )
aio.clock.start(x=80)
# asyncio.create_task( aio.clock.loop() )
aio.clock.start(x=80)

print(__name__, "sim repl ready for", __file__)
print(__name__, "sim repl ready for", __file__)

await shell.source(__file__)
await shell.runpy(__file__)
shell.interact()

# if you don't reach that step
# your main.py has an infinite sync loop somewhere !
print(f"{platform.is_browser=}, sim ready, press enter to start")
# if you don't reach that step
# your main.py has an infinite sync loop somewhere !
print(f"{platform.is_browser=}, sim ready, press enter to start")

while not aio.exit:
await aio.sleep(0.016)
print(__name__, "sim terminated")
while not aio.exit:
await aio.sleep(0.016)
print(__name__, "sim terminated")


if __name__ == "__main__":
asyncio.run(custom_site())
asyncio.run(import_site())


#
110 changes: 96 additions & 14 deletions pygbag/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@

devmode = "--dev" in sys.argv

DEFAULT_SCRIPT = "main.py"
CACHE_ROOT = Path("build")
CACHE_PATH = CACHE_ROOT / "web-cache"
CACHE_VERSION = CACHE_ROOT / "version.txt"
CACHE_APP = CACHE_ROOT / "web"

cdn_dot = __version__.split(".")
cdn_dot.pop()
cdn_version = ".".join(cdn_dot)
Expand Down Expand Up @@ -50,31 +56,95 @@
DEFAULT_PORT = 8000
DEFAULT_TMPL = "default.tmpl"

DEFAULT_SCRIPT = "main.py"


async def main_run(app_folder, mainscript, cdn=DEFAULT_CDN):
global DEFAULT_PORT, DEFAULT_SCRIPT, required
def set_args(program):
import sys
from pathlib import Path

DEFAULT_SCRIPT = mainscript or DEFAULT_SCRIPT
required = []

patharg = Path(program).resolve()
if patharg.is_file():
mainscript = patharg.name
app_folder = patharg.parent
else:
app_folder = patharg.resolve()

sys.path.insert(0, str(app_folder))

if not app_folder.is_dir() or patharg.as_posix().endswith("/pygbag/__main__.py"):
required.append(
"78: Error, Last argument must be a valid app top level directory, or the main python script"
)

if sys.version_info < (3, 8):
# zip deflate compression level 3.7
# https://docs.python.org/3.11/library/shutil.html#shutil.copytree dirs_exist_ok = 3.8
required.append("84: Error, pygbag requires CPython version >= 3.8")

if len(required):
while len(required):
print(required.pop())
print("89: missing requirement(s)")
sys.exit(89)

return app_folder, mainscript


def cache_check(app_folder, devmode = False):
global CACHE_PATH, CACHE_APP, __version__

version_file = app_folder / CACHE_VERSION

clear_cache = False

# always clear the cache in devmode, because cache source is local and changes a lot
if devmode :
print("103: DEVMODE: clearing cache")
clear_cache = True
elif version_file.is_file():
try:
with open(version_file, "r") as file:
cache_ver = file.read()
if cache_ver != __version__:
print(f"115: cache {cache_ver} mismatch, want {__version__}, cleaning ...")
clear_cache = True
except:
# something's wrong in cache structure, try clean it up
clear_cache = True
else:
clear_cache = True

app_folder.joinpath("build").mkdir(exist_ok=True)
app_folder.joinpath(CACHE_ROOT).mkdir(exist_ok=True)

build_dir = app_folder.joinpath("build/web")
build_dir = app_folder / CACHE_APP
build_dir.mkdir(exist_ok=True)

cache_dir = app_folder.joinpath("build/web-cache")
cache_dir = app_folder / CACHE_PATH

if devmode and cache_dir.is_dir():
print("DEVMODE: clearing cache")
if clear_cache and cache_dir.is_dir():
if shutil.rmtree.avoids_symlink_attacks:
shutil.rmtree(cache_dir.as_posix())
else:
print("can't clear cache : rmtree is not safe")
print("115: cannot clear cache : rmtree is not safe on that system", file=sys.stderr)
raise SystemEXit(115)

cache_dir.mkdir(exist_ok=True)
# rebuild
cache_dir.mkdir(exist_ok=True)

# version = "0.0.0"
with open(version_file, "w") as file:
file.write(__version__)

return build_dir, cache_dir


async def main_run(app_folder, mainscript, cdn=DEFAULT_CDN):
global DEFAULT_PORT, DEFAULT_SCRIPT, APP_CACHE, required

DEFAULT_SCRIPT = mainscript or DEFAULT_SCRIPT

build_dir, cache_dir = cache_check(app_folder, devmode)

sys.argv.pop()

Expand Down Expand Up @@ -211,7 +281,7 @@ async def main_run(app_folder, mainscript, cdn=DEFAULT_CDN):
# the app folder
app_folder={app_folder}
# artefacts directoty
# artefacts directory
build_dir={build_dir}
# the window title and icon name
Expand All @@ -220,7 +290,7 @@ async def main_run(app_folder, mainscript, cdn=DEFAULT_CDN):
# package name, better make it unique
package={args.package}
# icon 96x96 for dekstop 16x16 for web
# icons: 96x96 for desktop, 16x16 for web
icon={args.icon}
# js/wasm provider
Expand Down Expand Up @@ -386,3 +456,15 @@ def cache_file(remote_url, suffix):
)
else:
print(args.template, "is not a valid template")


def main():
app_folder, mainscript = set_args(sys.argv[-1])

# sim does not use cache.
if "--sim" in sys.argv:
print(f"To use simulator launch with : {sys.executable} -m pygbag {' '.join(sys.argv[1:])}")
return 1
else:
asyncio.run(main_run(app_folder, mainscript))
return 0
75 changes: 69 additions & 6 deletions pygbag/mutator.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,76 @@ def generate_predictable_names():
def transform_source(source: str) -> str:
src = transform_source_nobreak(source)
src = transform_source_repeat(src)
src = transform_source_switch(src)
# faulty
# src = transform_source_switch(src)
src = transform_source_sched_yield(src)
return src

# py => nim
lines = source.split("\n")

def transform_file(filename: str):
with open("extended_syntax.py", "r") as sourcefile:
return transform_source(sourcefile.read())
defcpp = {"include ": "include ", "if ": "when ", "else": "else:", "endif": "pass"}

for idx, l in enumerate(lines):
ll = l.lstrip(" ")

if not len(ll):
continue

if ll.rstrip() == "...":
lines[idx] = l.replace("...", "pass")

if ll[0] == "#":
pos = l.find("#")
head = l[:pos]
trail = ""
for tag, value in defcpp.items():
if ll.startswith(f"#{tag}"):
trail = ll[1:].replace(tag, value)
elif ll.startswith(f"# {tag}"):
trail = ll[2:].replace(tag, value)
else:
continue
break

if trail:
lines[idx] = head + trail
continue

if ll.startswith("##nim "):
lines[idx] = l.replace("##nim ", "")
continue

if ll.startswith('"""#!nim'):
lines[idx] = "#nim:Begin"

elif ll.startswith('""" #!nim'):
lines[idx] = "#nim:End"

elif l.find(", end=") >= 0:
# TODO: will fail on , end="x", sep=","

pos = l.find("print(")
head = l[:pos]

if pos >= 0:
print("=" * 80)
l = l[pos + 6 :].rstrip(") ")
l, endl = l.rsplit(", end=", 1)
# print(f'{l=}{endl=}')
lines[idx] = f"{head}write(stdout, {l});write(stdout, {endl})"
print("=" * 80)
# lines[idx] = l.replace(', end=','

return "\n".join(lines)


def transform_file(filename: str, out: str = ""):
with open(filename, "r") as sourcefile:
source = transform_source(sourcefile.read())
if out:
with open(out, "w") as file:
file.write(source)
return source


# =============================================================================
Expand Down Expand Up @@ -181,7 +243,9 @@ def transform_source_switch(source, callback_params=None, **_kwargs):

if len(line) > 1:
_index = token_utils.get_first_index(line)
print("205:", line)
second_token = line[_index + 1]

else:
second_token = None

Expand Down Expand Up @@ -222,7 +286,6 @@ def transform_source_switch(source, callback_params=None, **_kwargs):


def transform_source_sched_yield(source, **_kwargs):
"""This performs a simple replacement of ``function`` by ``lambda``."""
new_tokens = []
skip = 0
for token in token_utils.tokenize(source):
Expand Down
5 changes: 4 additions & 1 deletion pygbag/support/cross/aio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,16 +351,19 @@ def run(coro, *, debug=False):
# https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
elif __EMSCRIPTEN__ or __wasi__:
# handle special custom_site() case
if coro.__name__ == "custom_site":
if coro.__name__ == "import_site":
embed.run()
run_called = False
elif coro.__name__ == "custom_site":
run_called = False
elif not aio.cross.simulator:
# let prelinker start asyncio loop
print("AIO will auto-start at 0+, now is", embed.counter())

# fallback to blocking asyncio
else:
loop.run_forever()
print(f"364: asyncio.run({coro=})")
elif run_called:
pdb("273: aio.run called twice !!!")

Expand Down
Loading

0 comments on commit 28f3fbd

Please sign in to comment.