diff --git a/core/src/stdlib/pyscript.js b/core/src/stdlib/pyscript.js index 5e8cda71..fcac6257 100644 --- a/core/src/stdlib/pyscript.js +++ b/core/src/stdlib/pyscript.js @@ -8,7 +8,7 @@ export default { "ffi.py": "try:\n\timport js;from pyodide.ffi import create_proxy as _cp,to_js as _py_tjs,jsnull;from_entries=js.Object.fromEntries;is_none=lambda value:value is None or value is jsnull\n\tdef _tjs(value,**A):\n\t\tB='dict_converter'\n\t\tif not hasattr(A,B):A[B]=from_entries\n\t\treturn _py_tjs(value,**A)\nexcept:from jsffi import create_proxy as _cp;from jsffi import to_js as _tjs;import js;jsnull=js.Object.getPrototypeOf(js.Object.prototype);is_none=lambda value:value is None or value is jsnull\ncreate_proxy=_cp\nto_js=_tjs\ntry:\n\tfrom polyscript import ffi as _ffi;direct=_ffi.direct;gather=_ffi.gather;query=_ffi.query\n\tdef assign(source,*B):\n\t\tA=source\n\t\tfor C in B:_ffi.assign(A,to_js(C))\n\t\treturn A\nexcept:\n\timport js;_assign=js.Object.assign;direct=lambda source:source\n\tdef assign(source,*B):\n\t\tA=source\n\t\tfor C in B:_assign(A,to_js(C))\n\t\treturn A", "flatted.py": "import json as _json\nclass _Known:\n\tdef __init__(A):A.key=[];A.value=[]\nclass _String:\n\tdef __init__(A,value):A.value=value\ndef _array_keys(value):\n\tA=[];B=0\n\tfor C in value:A.append(B);B+=1\n\treturn A\ndef _object_keys(value):\n\tA=[]\n\tfor B in value:A.append(B)\n\treturn A\ndef _is_array(value):return isinstance(value,(list,tuple))\ndef _is_object(value):return isinstance(value,dict)\ndef _is_string(value):return isinstance(value,str)\ndef _index(known,input,value):B=value;A=known;input.append(B);C=str(len(input)-1);A.key.append(B);A.value.append(C);return C\ndef _loop(keys,input,known,output):\n\tA=output\n\tfor B in keys:\n\t\tC=A[B]\n\t\tif isinstance(C,_String):_ref(B,input[int(C.value)],input,known,A)\n\treturn A\ndef _ref(key,value,input,known,output):\n\tB=known;A=value\n\tif _is_array(A)and A not in B:B.append(A);A=_loop(_array_keys(A),input,B,A)\n\telif _is_object(A)and A not in B:B.append(A);A=_loop(_object_keys(A),input,B,A)\n\toutput[key]=A\ndef _relate(known,input,value):\n\tB=known;A=value\n\tif _is_string(A)or _is_array(A)or _is_object(A):\n\t\ttry:return B.value[B.key.index(A)]\n\t\texcept:return _index(B,input,A)\n\treturn A\ndef _transform(known,input,value):\n\tB=known;A=value\n\tif _is_array(A):\n\t\tC=[]\n\t\tfor F in A:C.append(_relate(B,input,F))\n\t\treturn C\n\tif _is_object(A):\n\t\tD={}\n\t\tfor E in A:D[E]=_relate(B,input,A[E])\n\t\treturn D\n\treturn A\ndef _wrap(value):\n\tA=value\n\tif _is_string(A):return _String(A)\n\tif _is_array(A):\n\t\tB=0\n\t\tfor D in A:A[B]=_wrap(D);B+=1\n\telif _is_object(A):\n\t\tfor C in A:A[C]=_wrap(A[C])\n\treturn A\ndef parse(value,*C,**D):\n\tA=value;E=_json.loads(A,*C,**D);B=[]\n\tfor A in E:B.append(_wrap(A))\n\tinput=[]\n\tfor A in B:\n\t\tif isinstance(A,_String):input.append(A.value)\n\t\telse:input.append(A)\n\tA=input[0]\n\tif _is_array(A):return _loop(_array_keys(A),input,[A],A)\n\tif _is_object(A):return _loop(_object_keys(A),input,[A],A)\n\treturn A\ndef stringify(value,*D,**E):\n\tB=_Known();input=[];C=[];A=int(_index(B,input,value))\n\twhile A Promise.all(urls.map((url) => import(url)))')()\n\texcept:message='Unable to use `window` or `document` -> https://docs.pyscript.net/latest/faq/#sharedarraybuffer';globalThis.console.warn(message);window=NotSupported('pyscript.window',message);document=NotSupported('pyscript.document',message);js_import=None\n\tsync=polyscript.xworker.sync\n\tdef current_target():return polyscript.target\nelse:\n\timport _pyscript;from _pyscript import PyWorker as _PyWorker,js_import;from pyscript.ffi import to_js\n\tdef PyWorker(url,**A):return _PyWorker(url,to_js(A))\n\twindow=globalThis;document=globalThis.document;sync=NotSupported('pyscript.sync','pyscript.sync works only when running in a worker')\n\tdef current_target():return _pyscript.target", + "magic_js.py": "import json,sys,js as globalThis\nfrom polyscript import config as _config,js_modules\nfrom pyscript.util import NotSupported\nRUNNING_IN_WORKER=not hasattr(globalThis,'document')\nconfig=json.loads(globalThis.JSON.stringify(_config))\nif isinstance(config,str):config={}\nif'MicroPython'in sys.version:config['type']='mpy'\nelse:config['type']='py'\nclass JSModule:\n\tdef __init__(A,name):A.name=name\n\tdef __getattr__(B,field):\n\t\tA=field\n\t\tif not A.startswith('_'):return getattr(getattr(js_modules,B.name),A)\nfor name in globalThis.Reflect.ownKeys(js_modules):sys.modules[f\"pyscript.js_modules.{name}\"]=JSModule(name)\nsys.modules['pyscript.js_modules']=js_modules\nif RUNNING_IN_WORKER:\n\timport polyscript;PyWorker=NotSupported('pyscript.PyWorker','pyscript.PyWorker works only when running in the main thread')\n\ttry:import js;window=polyscript.xworker.window;document=window.document;js.document=document;js_import=window.Function('return (...urls) => Promise.all(urls.map((url) => import(url)))')()\n\texcept:message='Unable to use `window` or `document` -> https://docs.pyscript.net/latest/faq/#sharedarraybuffer';globalThis.console.warn(message);window=NotSupported('pyscript.window',message);document=NotSupported('pyscript.document',message);js_import=None\n\tsync=polyscript.xworker.sync\n\tdef current_target():return polyscript.target\nelse:\n\timport _pyscript;from _pyscript import PyWorker as _PyWorker,js_import;from pyscript.ffi import to_js\n\tdef PyWorker(url,**A):return _PyWorker(url,to_js(A))\n\twindow=globalThis;document=globalThis.document;sync=NotSupported('pyscript.sync','pyscript.sync works only when running in a worker')\n\tdef current_target():return _pyscript.target", "media.py": "from pyscript import window\nfrom pyscript.ffi import to_js\nclass Device:\n\tdef __init__(A,device):A._dom_element=device\n\t@property\n\tdef id(self):return self._dom_element.deviceId\n\t@property\n\tdef group(self):return self._dom_element.groupId\n\t@property\n\tdef kind(self):return self._dom_element.kind\n\t@property\n\tdef label(self):return self._dom_element.label\n\tdef __getitem__(A,key):return getattr(A,key)\n\t@classmethod\n\tasync def load(E,audio=False,video=True):\n\t\tC='video';B=video;A={};A['audio']=audio\n\t\tif isinstance(B,bool):A[C]=B\n\t\telse:\n\t\t\tA[C]={}\n\t\t\tfor D in B:A[C][D]=B[D]\n\t\treturn await window.navigator.mediaDevices.getUserMedia(to_js(A))\n\tasync def get_stream(A):B=A.kind.replace('input','').replace('output','');C={B:{'deviceId':{'exact':A.id}}};return await A.load(**C)\nasync def list_devices():return[Device(A)for A in await window.navigator.mediaDevices.enumerateDevices()]", "storage.py": "_C='memoryview'\n_B='bytearray'\n_A='generic'\nfrom polyscript import storage as _storage\nfrom pyscript.flatted import parse as _parse\nfrom pyscript.flatted import stringify as _stringify\nfrom pyscript.ffi import is_none\ndef _to_idb(value):\n\tA=value\n\tif is_none(A):return _stringify(['null',0])\n\tif isinstance(A,(bool,float,int,str,list,dict,tuple)):return _stringify([_A,A])\n\tif isinstance(A,bytearray):return _stringify([_B,list(A)])\n\tif isinstance(A,memoryview):return _stringify([_C,list(A)])\n\tB=f\"Unexpected value: {A}\";raise TypeError(B)\ndef _from_idb(value):\n\tC=value;A,B=_parse(C)\n\tif A=='null':return\n\tif A==_A:return B\n\tif A==_B:return bytearray(B)\n\tif A==_C:return memoryview(bytearray(B))\n\treturn C\nclass Storage(dict):\n\tdef __init__(B,store):A=store;super().__init__({A:_from_idb(B)for(A,B)in A.entries()});B.__store__=A\n\tdef __delitem__(A,attr):A.__store__.delete(attr);super().__delitem__(attr)\n\tdef __setitem__(B,attr,value):A=value;B.__store__.set(attr,_to_idb(A));super().__setitem__(attr,A)\n\tdef clear(A):A.__store__.clear();super().clear()\n\tasync def sync(A):await A.__store__.sync()\nasync def storage(name='',storage_class=Storage):\n\tif not name:A='The storage name must be defined';raise ValueError(A)\n\treturn storage_class(await _storage(f\"@pyscript/{name}\"))", "util.py": "import js,sys,inspect\ndef as_bytearray(buffer):\n\tA=js.Uint8Array.new(buffer);B=A.length;C=bytearray(B)\n\tfor D in range(B):C[D]=A[D]\n\treturn C\nclass NotSupported:\n\tdef __init__(A,name,error):object.__setattr__(A,'name',name);object.__setattr__(A,'error',error)\n\tdef __repr__(A):return f\"\"\n\tdef __getattr__(A,attr):raise AttributeError(A.error)\n\tdef __setattr__(A,attr,value):raise AttributeError(A.error)\n\tdef __call__(A,*B):raise TypeError(A.error)\ndef is_awaitable(obj):\n\tA=obj;from pyscript import config as B\n\tif B['type']=='mpy':\n\t\tif''in repr(A):return True\n\t\treturn inspect.isgeneratorfunction(A)\n\treturn inspect.iscoroutinefunction(A)", diff --git a/core/src/stdlib/pyscript/magic_js.py b/core/src/stdlib/pyscript/magic_js.py index dbd6df6a..34c988c9 100644 --- a/core/src/stdlib/pyscript/magic_js.py +++ b/core/src/stdlib/pyscript/magic_js.py @@ -10,6 +10,9 @@ RUNNING_IN_WORKER = not hasattr(globalThis, "document") config = json.loads(globalThis.JSON.stringify(_config)) +if isinstance(config, str): + config = {} + if "MicroPython" in sys.version: config["type"] = "mpy" else: diff --git a/core/tests/index.html b/core/tests/index.html index 92284850..e3ced3d3 100644 --- a/core/tests/index.html +++ b/core/tests/index.html @@ -14,5 +14,5 @@ a:hover { opacity: 1; } - + diff --git a/core/tests/javascript/worker-config/config.json b/core/tests/javascript/worker-config/config.json new file mode 100644 index 00000000..7c893540 --- /dev/null +++ b/core/tests/javascript/worker-config/config.json @@ -0,0 +1,3 @@ +{ + "packages": ["numpy"] +} diff --git a/core/tests/javascript/worker-config/index.html b/core/tests/javascript/worker-config/index.html new file mode 100644 index 00000000..931ea741 --- /dev/null +++ b/core/tests/javascript/worker-config/index.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/core/tests/javascript/worker-config/worker.py b/core/tests/javascript/worker-config/worker.py new file mode 100644 index 00000000..73e81cd3 --- /dev/null +++ b/core/tests/javascript/worker-config/worker.py @@ -0,0 +1,5 @@ +import numpy +from pyscript import document + +document.body.append(numpy.__version__) +document.documentElement.classList.add("done") diff --git a/core/tests/js_tests.spec.js b/core/tests/js_tests.spec.js index 080069b9..52a534bb 100644 --- a/core/tests/js_tests.spec.js +++ b/core/tests/js_tests.spec.js @@ -2,6 +2,11 @@ import { test, expect } from '@playwright/test'; test.setTimeout(120 * 1000); +test('Worker config as relative URL', async ({ page }) => { + await page.goto('http://localhost:8080/tests/javascript/worker-config/index.html'); + await page.waitForSelector('html.done'); +}); + test('config-parser custom TOML', async ({ page }) => { await page.goto('http://localhost:8080/tests/javascript/config-parser/index.html'); await page.waitForSelector('html.done');