Skip to content

Commit

Permalink
more pep722
Browse files Browse the repository at this point in the history
  • Loading branch information
pmp-p committed Aug 26, 2023
1 parent ef7c19e commit f316cdf
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 12 deletions.
8 changes: 7 additions & 1 deletion pygbag/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,14 @@ def __repr__(self):

# fake host document.window
import platform as fakehost



fakehost.window = NoOp("platform.window")

import aio.filelike
fakehost.fopen = aio.filelike.fopen

# cannot fake a cpu __WASM__ will be False

# but fake the platform AND the module
Expand Down Expand Up @@ -219,7 +225,7 @@ async def raw_input(self, prompt=">>> "):
ns = vars(__import__(__name__))

ns["TopLevel_async_handler"] = TopLevel_async_handler
# FIXME: store it elwhere.
# FIXME: store it elsewhere.
__import__('builtins').TopLevel_async_handler = TopLevel_async_handler

sourcefile = sourcefile or str(sys.argv[-1])
Expand Down
10 changes: 9 additions & 1 deletion pygbag/aio.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@

import aio.pep0722

if '.-X.dev.' in '.'.join(sys.orig_argv):
aio.pep0722.Config.PKG_INDEXES.extend( ["http://localhost:8000/archives/repo/"] )
else:
aio.pep0722.Config.PKG_INDEXES.extend( ["https://pygame-web.github.io/archives/repo/"] )

import pygbag.__main__

async def custom_async_input():
Expand All @@ -34,7 +39,10 @@ async def custom_async_input():

while not aio.exit:
next = time.time() + 0.016
aio.loop._run_once()
try:
aio.loop._run_once()
except KeyboardInterrupt:
print("45: KeyboardInterrupt")

dt = next - time.time()
if dt < 0:
Expand Down
2 changes: 1 addition & 1 deletion pygbag/support/cross/aio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ def pdb(*argv):
# usefull https://pymotw.com/3/sys/tracing.html
if DEBUG:
import trace
print("48:",trace.__file__,sys.path)

_tracer = trace.Trace(count=False, trace=True)

Expand Down Expand Up @@ -379,6 +378,7 @@ async def __main__():
try:
loop.run_forever()
except KeyboardInterrupt:
print("301: closing loop")
loop.close()

print(f"378: asyncio.run({coro=})")
Expand Down
103 changes: 103 additions & 0 deletions pygbag/support/cross/aio/filelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import aio

temporary = []


async def aio_sock_open(sock, host, port):
while True:
Expand All @@ -25,6 +27,107 @@ async def aio_sock_open(sock, host, port):
sys.print_exception(e)




def fix_url(maybe_url):
url = str(maybe_url)
if url.startswith("http://"):
pass
elif url.startswith("https://"):
pass
elif url.startswith("https:/"):
url = "https:/" + url[6:]
elif url.startswith("http:/"):
url = "http:/" + url[5:]
return url

def mktemp(suffix=""):
global temporary
tmpname = f"/tmp/tmp-{aio.ticks}-{len(temporary)}{suffix}"
temporary.append( tmpname )
return tmpname


class fopen:
flags = {
"redirect": "follow",
"credentials": "omit",
}

def __init__(self, maybe_url, mode="r", flags=None):
self.url = fix_url(maybe_url)
self.mode = mode
flags = flags or self.__class__.flags
print(f'849: fopen: fetching "{self.url}" with {flags=}')
if __WASM__:
self.flags = ffi(flags)
else:
self.flags = flags

self.tmpfile = None

async def __aexit__(self, *exc):
if self.tmpfile:
self.filelike.close()
try:
os.unlink(self.tmpfile)
except FileNotFoundError as e:
print("895: async I/O error", e)
del self.filelike, self.url, self.mode, self.tmpfile
return False

if __WASM__:
async def __aenter__(self):
import platform

if "b" in self.mode:
self.tmpfile = shell.mktemp()
cf = platform.window.cross_file(self.url, self.tmpfile, self.flags)
content = await platform.jsiter(cf)
self.filelike = open(content, "rb")
self.filelike.path = content

def rename_to(target):
print("rename_to", content, target)
# will be closed
self.filelike.close()
os.rename(self.tmpfile, target)
self.tmpfile = None
del self.filelike.rename_to
return target

else:
import io

jsp = platform.window.fetch(self.url, self.flags)
response = await platform.jsprom(jsp)
content = await platform.jsprom(response.text())
if len(content) == 4:
print("585 fopen", f"Binary {self.url=} ?")
self.filelike = io.StringIO(content)

def rename_to(target):
with open(target, "wb") as data:
date.write(self.filelike.read())
del self.filelike.rename_to
return target

self.filelike.rename_to = rename_to
return self.filelike

else:

async def __aenter__(self):
import aiohttp
async with aiohttp.ClientSession() as session:
async with session.get(self.url) as response:
assert response.status == 200
# For large files use response.content.read(chunk_size) instead.
self.filelike = io.StringIO( (await response.read()).decode())

return self.filelike


class open:
def __init__(self, url, mode, tmout):
self.host, port = url.rsplit(":", 1)
Expand Down
45 changes: 42 additions & 3 deletions pygbag/support/cross/aio/pep0722.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
# https://peps.python.org/pep-0722/ – Dependency specification for single-file scripts
# https://peps.python.org/pep-0508/ – Dependency specification for Python Software Packages

from pathlib import Path

import re
import tokenize

import json

import importlib
import installer
import pyparsing
from packaging.requirements import Requirement


DEPENDENCY_BLOCK_MARKER = r"(?i)^#\s+script\s+dependencies:\s*$"

class Config:
DEPENDENCY_BLOCK_MARKER = r"(?i)^#\s+script\s+dependencies:\s*$"
PKG_INDEXES = []
REPO_INDEX = "repodata.json"
repos = []

def read_dependency_block(filename):
# Use the tokenize module to handle any encoding declaration.
with tokenize.open(filename) as f:
# Skip lines until we reach a dependency block (OR EOF).
for line in f:
if re.match(DEPENDENCY_BLOCK_MARKER, line):
if re.match(Config.DEPENDENCY_BLOCK_MARKER, line):
break
# Read dependency lines until we hit a line that doesn't
# start with #, or we are at EOF.
Expand All @@ -37,13 +46,43 @@ def read_dependency_block(filename):
yield Requirement(line)


async def async_imports_init():
from aio.filelike import fopen
global PKG_INDEXES
for cdn in Config.PKG_INDEXES:
print("init cdn :", Config.PKG_INDEXES)
async with fopen(Path(cdn) / Config.REPO_INDEX) as source:
Config.repos.append(json.loads(source.read()))

# print(json.dumps(cls.repos[0]["packages"], sort_keys=True, indent=4))

pdb("referenced packages :", len(Config.repos[0]["packages"]))

#if not len(PyConfig.pkg_repolist):
# await cls.async_repos()



async def check_list(filename):
global PKG_INDEXES
print()
print('-'*11,"required packages",'-'*10)
maybe_missing = []
for req in read_dependency_block(filename):
dep = str(req)

print(dep)
print(dep,':', end='')
if importlib.util.find_spec(dep):
print('found')
else:
print("?")
if dep not in maybe_missing:
maybe_missing.append(dep)

print('-'*40)
print()

if len(maybe_missing) and len(Config.PKG_INDEXES):
await async_imports_init()


1 change: 0 additions & 1 deletion pygbag/support/cross/aio/toplevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ def runcode(self, code):
try:
self.rv = bc()
except SystemExit:
#raise
aio.exit_now(0)

except KeyboardInterrupt as ex:
Expand Down
13 changes: 8 additions & 5 deletions pygbag/support/pythonrc.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,11 @@ class shell:
ROOT = f"/data/data/{sys.argv[0]}"
HOME = f"/data/data/{sys.argv[0]}/assets"

ticks = 0
pgzrunning = None

@classmethod
def mktemp(cls, suffix=""):
cls.ticks += 1
return f"/tmp/tmp-{cls.ticks}{suffix}"
return aio.filelike.mktemp(suffix)

@classmethod
def cat(cls, *argv):
Expand Down Expand Up @@ -969,7 +967,7 @@ async def __aenter__(self):
import platform

if "b" in self.mode:
self.tmpfile = shell.mktemp()
self.tmpfile = aio.filelike.mktemp()
cf = platform.window.cross_file(self.url, self.tmpfile, self.flags)
content = await platform.jsiter(cf)
self.filelike = open(content, "rb")
Expand Down Expand Up @@ -1056,6 +1054,7 @@ class TopLevel_async_handler(aio.toplevel.AsyncInteractiveConsole):
# be re entrant
import_lock = []

HTML_MARK = '"'*3 + ' # BEGIN -->'

repos = []
mapping = {
Expand Down Expand Up @@ -1672,7 +1671,7 @@ def patch_pygame():
# emulate pyodide display() cmd
# TODO: fixme target
async def display(obj, target=None, **kw):
filename = shell.mktemp(".png")
filename = aio.filelike.mktemp(".png")
target = kw.pop("target", None)
x = kw.pop("x", 0)
y = kw.pop("y", 0)
Expand Down Expand Up @@ -1750,6 +1749,10 @@ async def import_site(__file__, run=True):
embed = False
hint = "main.py"

# if not imported by simulator then aio is handled externally
if 'pygbag.aio' not in sys.modules:
sys.modules['pygbag.aio'] = aio

try:
# always start async handler or we could not do imports.
await TopLevel_async_handler.start_toplevel(platform.shell, console=True)
Expand Down

0 comments on commit f316cdf

Please sign in to comment.