From 8615d375fb190ec135833f5d1ca96ee2a01b836b Mon Sep 17 00:00:00 2001 From: Winston Chang Date: Tue, 28 Jan 2025 16:32:59 -0600 Subject: [PATCH 1/2] Update to pyodide 0.27.2 --- Makefile | 2 +- src/pyodide/ffi.d.ts | 5 +- src/pyodide/pyodide.d.ts | 123 +++++++++++++++++++++++++++++---------- src/pyodide/pyodide.js | 6 +- 4 files changed, 100 insertions(+), 36 deletions(-) diff --git a/Makefile b/Makefile index 887c95c4..0b0b34b8 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ SHINYLIVE_VERSION = $(shell node -p "require('./package.json').version") -PYODIDE_VERSION = 0.26.3 +PYODIDE_VERSION = 0.27.2 PYODIDE_DIST_FILENAME = pyodide-$(PYODIDE_VERSION).tar.bz2 DOWNLOAD_DIR = ./downloads R_SHINY_VERSION = 1.9.1.8002 diff --git a/src/pyodide/ffi.d.ts b/src/pyodide/ffi.d.ts index 9964b065..6203dea4 100644 --- a/src/pyodide/ffi.d.ts +++ b/src/pyodide/ffi.d.ts @@ -1086,8 +1086,11 @@ declare class PythonError extends Error { constructor(type: string, message: string, error_address: number); } /** - * See :ref:`js-api-pyodide-ffi` + * Foreign function interface classes. Can be used for typescript type + * annotations or at runtime for `instanceof` checks. + * @summaryLink :ref:`ffi ` * @hidetype + * @omitFromAutoModule */ declare const ffi: { PyProxy: typeof PyProxy; diff --git a/src/pyodide/pyodide.d.ts b/src/pyodide/pyodide.d.ts index c309ddc6..d1963ba3 100644 --- a/src/pyodide/pyodide.d.ts +++ b/src/pyodide/pyodide.d.ts @@ -37,6 +37,75 @@ declare function setStderr(options?: { }): void; /** @deprecated Use `import type { TypedArray } from "pyodide/ffi"` instead */ export type TypedArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array; +type FSNode = { + timestamp: number; + rdev: number; + contents: Uint8Array; + mode: number; +}; +type FSStream = { + tty?: boolean; + seekable?: boolean; + stream_ops: FSStreamOps; + node: FSNode; +}; +type FSStreamOps = FSStreamOpsGen; +type FSStreamOpsGen = { + open: (a: T) => void; + close: (a: T) => void; + fsync: (a: T) => void; + read: (a: T, b: Uint8Array, offset: number, length: number, pos: number) => number; + write: (a: T, b: Uint8Array, offset: number, length: number, pos: number) => number; +}; +interface FS { + unlink: (path: string) => void; + mkdirTree: (path: string, mode?: number) => void; + chdir: (path: string) => void; + symlink: (target: string, src: string) => FSNode; + createDevice: ((parent: string, name: string, input?: (() => number | null) | null, output?: ((code: number) => void) | null) => FSNode) & { + major: number; + }; + closeStream: (fd: number) => void; + open: (path: string, flags: string | number, mode?: number) => FSStream; + makedev: (major: number, minor: number) => number; + mkdev: (path: string, dev: number) => FSNode; + filesystems: any; + stat: (path: string, dontFollow?: boolean) => any; + readdir: (path: string) => string[]; + isDir: (mode: number) => boolean; + isMountpoint: (mode: FSNode) => boolean; + lookupPath: (path: string, options?: { + follow_mount?: boolean; + }) => { + node: FSNode; + }; + isFile: (mode: number) => boolean; + writeFile: (path: string, contents: any, o?: { + canOwn?: boolean; + }) => void; + chmod: (path: string, mode: number) => void; + utime: (path: string, atime: number, mtime: number) => void; + rmdir: (path: string) => void; + mount: (type: any, opts: any, mountpoint: string) => any; + write: (stream: FSStream, buffer: any, offset: number, length: number, position?: number) => number; + close: (stream: FSStream) => void; + ErrnoError: { + new (errno: number): Error; + }; + registerDevice(dev: number, ops: FSStreamOpsGen): void; + syncfs(dir: boolean, oncomplete: (val: void) => void): void; + findObject(a: string, dontResolveLastLink?: boolean): any; + readFile(a: string): Uint8Array; +} +type PackageType = "package" | "cpython_module" | "shared_library" | "static_library"; +interface PackageData { + name: string; + version: string; + fileName: string; + /** @experimental */ + packageType: PackageType; +} +type LoadedPackages = Record; /** @deprecated Use `import type { PyProxy } from "pyodide/ffi"` instead */ interface PyProxy { [x: string]: any; @@ -977,19 +1046,6 @@ declare class PyBufferView { */ release(): void; } -type PackageType = "package" | "cpython_module" | "shared_library" | "static_library"; -interface PackageData { - name: string; - version: string; - fileName: string; - /** @experimental */ - packageType: PackageType; -} -declare function loadPackage(names: string | PyProxy | Array, options?: { - messageCallback?: (message: string) => void; - errorCallback?: (message: string) => void; - checkIntegrity?: boolean; -}): Promise>; declare class PythonError extends Error { /** * The address of the error we are wrapping. We may later compare this @@ -1013,11 +1069,13 @@ declare class PyodideAPI { /** @hidden */ static version: string; /** @hidden */ - static loadPackage: typeof loadPackage; + static loadPackage: (names: string | PyProxy | Array, options?: { + messageCallback?: (message: string) => void; + errorCallback?: (message: string) => void; + checkIntegrity?: boolean; + }) => Promise>; /** @hidden */ - static loadedPackages: { - [key: string]: string; - }; + static loadedPackages: LoadedPackages; /** @hidden */ static ffi: { PyProxy: typeof PyProxy; @@ -1069,7 +1127,7 @@ declare class PyodideAPI { * are available as members of ``FS.filesystems``: * ``IDBFS``, ``NODEFS``, ``PROXYFS``, ``WORKERFS``. */ - static FS: any; + static FS: FS; /** * An alias to the `Emscripten Path API * `_. @@ -1079,8 +1137,9 @@ declare class PyodideAPI { */ static PATH: any; /** - * See :ref:`js-api-pyodide-canvas`. - * @hidetype + * APIs to set a canvas for rendering graphics. + * @summaryLink :ref:`canvas ` + * @omitFromAutoModule */ static canvas: CanvasInterface; /** @@ -1119,7 +1178,6 @@ declare class PyodideAPI { * (optional) * @param options.checkIntegrity If true, check the integrity of the downloaded * packages (default: true) - * @async */ static loadPackagesFromImports(code: string, options?: { messageCallback?: (message: string) => void; @@ -1203,7 +1261,6 @@ declare class PyodideAPI { * traceback for any exception that is thrown will show source lines * (unless the given file name starts with ``<`` and ends with ``>``). * @returns The result of the Python code translated to JavaScript. - * @async */ static runPythonAsync(code: string, options?: { globals?: PyProxy; @@ -1385,7 +1442,14 @@ declare class PyodideAPI { * @returns The old value of the debug flag. */ static setDebug(debug: boolean): boolean; - static makeMemorySnapshot(): Uint8Array; + /** + * + * @param param0 + * @returns + */ + static makeMemorySnapshot({ serializer, }?: { + serializer?: (obj: any) => any; + }): Uint8Array; } /** @hidden */ export type PyodideInterface = typeof PyodideAPI; @@ -1412,13 +1476,12 @@ type ConfigType = { _makeSnapshot: boolean; enableRunUntilComplete: boolean; checkAPIVersion: boolean; + BUILD_ID: string; }; /** * Load the main Pyodide wasm module and initialize it. * * @returns The :ref:`js-api-pyodide` module. - * @memberof globalThis - * @async * @example * async function main() { * const pyodide = await loadPyodide({ @@ -1547,14 +1610,12 @@ export declare function loadPyodide(options?: { * @ignore */ _node_mounts?: string[]; - /** - * @ignore - */ + /** @ignore */ _makeSnapshot?: boolean; - /** - * @ignore - */ + /** @ignore */ _loadSnapshot?: Uint8Array | ArrayBuffer | PromiseLike; + /** @ignore */ + _snapshotDeserializer?: (obj: any) => any; }): Promise; export type {}; diff --git a/src/pyodide/pyodide.js b/src/pyodide/pyodide.js index ced05553..ce303717 100644 --- a/src/pyodide/pyodide.js +++ b/src/pyodide/pyodide.js @@ -1,4 +1,4 @@ -var Q=Object.defineProperty;var c=(e,t)=>Q(e,"name",{value:t,configurable:!0}),O=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,i)=>(typeof require<"u"?require:t)[i]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+e+'" is not supported')});function Z(e){return!isNaN(parseFloat(e))&&isFinite(e)}c(Z,"_isNumber");function E(e){return e.charAt(0).toUpperCase()+e.substring(1)}c(E,"_capitalize");function P(e){return function(){return this[e]}}c(P,"_getter");var w=["isConstructor","isEval","isNative","isToplevel"],N=["columnNumber","lineNumber"],_=["fileName","functionName","source"],ee=["args"],te=["evalOrigin"],I=w.concat(N,_,ee,te);function p(e){if(e)for(var t=0;t-1&&(n=n.replace(/eval code/g,"eval").replace(/(\(eval at [^()]*)|(,.*$)/g,""));var o=n.replace(/^\s+/,"").replace(/\(eval code/g,"(").replace(/^.*?\s+/,""),s=o.match(/ (\(.+\)$)/);o=s?o.replace(s[0],""):o;var l=this.extractLocation(s?s[1]:o),d=s&&o||void 0,u=["eval",""].indexOf(l[0])>-1?void 0:l[0];return new x({functionName:d,fileName:u,lineNumber:l[1],columnNumber:l[2],source:n})},this)},"ErrorStackParser$$parseV8OrIE"),parseFFOrSafari:c(function(r){var a=r.stack.split(` -`).filter(function(n){return!n.match(t)},this);return a.map(function(n){if(n.indexOf(" > eval")>-1&&(n=n.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1")),n.indexOf("@")===-1&&n.indexOf(":")===-1)return new x({functionName:n});var o=/((.*".+"[^@]*)?[^@]*)(?:@)/,s=n.match(o),l=s&&s[1]?s[1]:void 0,d=this.extractLocation(n.replace(o,""));return new x({functionName:l,fileName:d[0],lineNumber:d[1],columnNumber:d[2],source:n})},this)},"ErrorStackParser$$parseFFOrSafari")}}c(ne,"ErrorStackParser");var re=new ne;var M=re;var g=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string"&&!process.browser,A=g&&typeof module<"u"&&typeof module.exports<"u"&&typeof O<"u"&&typeof __dirname<"u",W=g&&!A,Ne=typeof globalThis.Bun<"u",oe=typeof Deno<"u",B=!g&&!oe,$=B&&typeof window=="object"&&typeof document=="object"&&typeof document.createElement=="function"&&typeof sessionStorage=="object"&&typeof importScripts!="function",j=B&&typeof importScripts=="function"&&typeof self=="object",_e=typeof navigator=="object"&&typeof navigator.userAgent=="string"&&navigator.userAgent.indexOf("Chrome")==-1&&navigator.userAgent.indexOf("Safari")>-1;var V,L,z,H,D;async function T(){if(!g||(V=(await import("node:url")).default,H=await import("node:fs"),D=await import("node:fs/promises"),z=(await import("node:vm")).default,L=await import("node:path"),U=L.sep,typeof O<"u"))return;let e=H,t=await import("node:crypto"),i=await import("ws"),r=await import("node:child_process"),a={fs:e,crypto:t,ws:i,child_process:r};globalThis.require=function(n){return a[n]}}c(T,"initNodeModules");function ie(e,t){return L.resolve(t||".",e)}c(ie,"node_resolvePath");function ae(e,t){return t===void 0&&(t=location),new URL(e,t).toString()}c(ae,"browser_resolvePath");var k;g?k=ie:k=ae;var U;g||(U="/");function se(e,t){return e.startsWith("file://")&&(e=e.slice(7)),e.includes("://")?{response:fetch(e)}:{binary:D.readFile(e).then(i=>new Uint8Array(i.buffer,i.byteOffset,i.byteLength))}}c(se,"node_getBinaryResponse");function ce(e,t){let i=new URL(e,location);return{response:fetch(i,t?{integrity:t}:{})}}c(ce,"browser_getBinaryResponse");var R;g?R=se:R=ce;async function q(e,t){let{response:i,binary:r}=R(e,t);if(r)return r;let a=await i;if(!a.ok)throw new Error(`Failed to load '${e}': request failed.`);return new Uint8Array(await a.arrayBuffer())}c(q,"loadBinaryFile");var F;if($)F=c(async e=>await import(e),"loadScript");else if(j)F=c(async e=>{try{globalThis.importScripts(e)}catch(t){if(t instanceof TypeError)await import(e);else throw t}},"loadScript");else if(g)F=le;else throw new Error("Cannot determine runtime environment");async function le(e){e.startsWith("file://")&&(e=e.slice(7)),e.includes("://")?z.runInThisContext(await(await fetch(e)).text()):await import(V.pathToFileURL(e).href)}c(le,"nodeLoadScript");async function J(e){if(g){await T();let t=await D.readFile(e,{encoding:"utf8"});return JSON.parse(t)}else return await(await fetch(e)).json()}c(J,"loadLockFile");async function K(){if(A)return __dirname;let e;try{throw new Error}catch(r){e=r}let t=M.parse(e)[0].fileName;if(g&&!t.startsWith("file://")&&(t=`file://${t}`),W){let r=await import("node:path");return(await import("node:url")).fileURLToPath(r.dirname(t))}let i=t.lastIndexOf(U);if(i===-1)throw new Error("Could not extract indexURL path from pyodide module location");return t.slice(0,i)}c(K,"calculateDirname");function Y(e){let t=e.FS,i=e.FS.filesystems.MEMFS,r=e.PATH,a={DIR_MODE:16895,FILE_MODE:33279,mount:function(n){if(!n.opts.fileSystemHandle)throw new Error("opts.fileSystemHandle is required");return i.mount.apply(null,arguments)},syncfs:async(n,o,s)=>{try{let l=a.getLocalSet(n),d=await a.getRemoteSet(n),u=o?d:l,m=o?l:d;await a.reconcile(n,u,m),s(null)}catch(l){s(l)}},getLocalSet:n=>{let o=Object.create(null);function s(u){return u!=="."&&u!==".."}c(s,"isRealDir");function l(u){return m=>r.join2(u,m)}c(l,"toAbsolute");let d=t.readdir(n.mountpoint).filter(s).map(l(n.mountpoint));for(;d.length;){let u=d.pop(),m=t.stat(u);t.isDir(m.mode)&&d.push.apply(d,t.readdir(u).filter(s).map(l(u))),o[u]={timestamp:m.mtime,mode:m.mode}}return{type:"local",entries:o}},getRemoteSet:async n=>{let o=Object.create(null),s=await de(n.opts.fileSystemHandle);for(let[l,d]of s)l!=="."&&(o[r.join2(n.mountpoint,l)]={timestamp:d.kind==="file"?(await d.getFile()).lastModifiedDate:new Date,mode:d.kind==="file"?a.FILE_MODE:a.DIR_MODE});return{type:"remote",entries:o,handles:s}},loadLocalEntry:n=>{let s=t.lookupPath(n).node,l=t.stat(n);if(t.isDir(l.mode))return{timestamp:l.mtime,mode:l.mode};if(t.isFile(l.mode))return s.contents=i.getFileDataAsTypedArray(s),{timestamp:l.mtime,mode:l.mode,contents:s.contents};throw new Error("node type not supported")},storeLocalEntry:(n,o)=>{if(t.isDir(o.mode))t.mkdirTree(n,o.mode);else if(t.isFile(o.mode))t.writeFile(n,o.contents,{canOwn:!0});else throw new Error("node type not supported");t.chmod(n,o.mode),t.utime(n,o.timestamp,o.timestamp)},removeLocalEntry:n=>{var o=t.stat(n);t.isDir(o.mode)?t.rmdir(n):t.isFile(o.mode)&&t.unlink(n)},loadRemoteEntry:async n=>{if(n.kind==="file"){let o=await n.getFile();return{contents:new Uint8Array(await o.arrayBuffer()),mode:a.FILE_MODE,timestamp:o.lastModifiedDate}}else{if(n.kind==="directory")return{mode:a.DIR_MODE,timestamp:new Date};throw new Error("unknown kind: "+n.kind)}},storeRemoteEntry:async(n,o,s)=>{let l=n.get(r.dirname(o)),d=t.isFile(s.mode)?await l.getFileHandle(r.basename(o),{create:!0}):await l.getDirectoryHandle(r.basename(o),{create:!0});if(d.kind==="file"){let u=await d.createWritable();await u.write(s.contents),await u.close()}n.set(o,d)},removeRemoteEntry:async(n,o)=>{await n.get(r.dirname(o)).removeEntry(r.basename(o)),n.delete(o)},reconcile:async(n,o,s)=>{let l=0,d=[];Object.keys(o.entries).forEach(function(f){let y=o.entries[f],S=s.entries[f];(!S||t.isFile(y.mode)&&y.timestamp.getTime()>S.timestamp.getTime())&&(d.push(f),l++)}),d.sort();let u=[];if(Object.keys(s.entries).forEach(function(f){o.entries[f]||(u.push(f),l++)}),u.sort().reverse(),!l)return;let m=o.type==="remote"?o.handles:s.handles;for(let f of d){let y=r.normalize(f.replace(n.mountpoint,"/")).substring(1);if(s.type==="local"){let S=m.get(y),X=await a.loadRemoteEntry(S);a.storeLocalEntry(f,X)}else{let S=a.loadLocalEntry(f);await a.storeRemoteEntry(m,y,S)}}for(let f of u)if(s.type==="local")a.removeLocalEntry(f);else{let y=r.normalize(f.replace(n.mountpoint,"/")).substring(1);await a.removeRemoteEntry(m,y)}}};e.FS.filesystems.NATIVEFS_ASYNC=a}c(Y,"initializeNativeFS");var de=c(async e=>{let t=[];async function i(a){for await(let n of a.values())t.push(n),n.kind==="directory"&&await i(n)}c(i,"collect"),await i(e);let r=new Map;r.set(".",e);for(let a of t){let n=(await e.resolve(a)).join("/");r.set(n,a)}return r},"getFsHandles");function G(e){let t={noImageDecoding:!0,noAudioDecoding:!0,noWasmDecoding:!1,preRun:ge(e),quit(i,r){throw t.exited={status:i,toThrow:r},r},print:e.stdout,printErr:e.stderr,arguments:e.args,API:{config:e},locateFile:i=>e.indexURL+i,instantiateWasm:ye(e.indexURL)};return t}c(G,"createSettings");function ue(e){return function(t){let i="/";try{t.FS.mkdirTree(e)}catch(r){console.error(`Error occurred while making a home directory '${e}':`),console.error(r),console.error(`Using '${i}' for a home directory instead`),e=i}t.FS.chdir(e)}}c(ue,"createHomeDirectory");function fe(e){return function(t){Object.assign(t.ENV,e)}}c(fe,"setEnvironment");function me(e){return t=>{for(let i of e)t.FS.mkdirTree(i),t.FS.mount(t.FS.filesystems.NODEFS,{root:i},i)}}c(me,"mountLocalDirectories");function pe(e){let t=q(e);return i=>{let r=i._py_version_major(),a=i._py_version_minor();i.FS.mkdirTree("/lib"),i.FS.mkdirTree(`/lib/python${r}.${a}/site-packages`),i.addRunDependency("install-stdlib"),t.then(n=>{i.FS.writeFile(`/lib/python${r}${a}.zip`,n)}).catch(n=>{console.error("Error occurred while installing the standard library:"),console.error(n)}).finally(()=>{i.removeRunDependency("install-stdlib")})}}c(pe,"installStdlib");function ge(e){let t;return e.stdLibURL!=null?t=e.stdLibURL:t=e.indexURL+"python_stdlib.zip",[pe(t),ue(e.env.HOME),fe(e.env),me(e._node_mounts),Y]}c(ge,"getFileSystemInitializationFuncs");function ye(e){let{binary:t,response:i}=R(e+"pyodide.asm.wasm");return function(r,a){return async function(){try{let n;i?n=await WebAssembly.instantiateStreaming(i,r):n=await WebAssembly.instantiate(await t,r);let{instance:o,module:s}=n;typeof WasmOffsetConverter<"u"&&(wasmOffsetConverter=new WasmOffsetConverter(wasmBinary,s)),a(o,s)}catch(n){console.warn("wasm instantiation failed!"),console.warn(n)}}(),{}}}c(ye,"getInstantiateWasmFunc");var C="0.26.3";async function $e(e={}){var u,m;await T();let t=e.indexURL||await K();t=k(t),t.endsWith("/")||(t+="/"),e.indexURL=t;let i={fullStdLib:!1,jsglobals:globalThis,stdin:globalThis.prompt?globalThis.prompt:void 0,lockFileURL:t+"pyodide-lock.json",args:[],_node_mounts:[],env:{},packageCacheDir:t,packages:[],enableRunUntilComplete:!1,checkAPIVersion:!0},r=Object.assign(i,e);(u=r.env).HOME??(u.HOME="/home/pyodide"),(m=r.env).PYTHONINSPECT??(m.PYTHONINSPECT="1");let a=G(r),n=a.API;if(n.lockFilePromise=J(r.lockFileURL),typeof _createPyodideModule!="function"){let f=`${r.indexURL}pyodide.asm.js`;await F(f)}let o;if(e._loadSnapshot){let f=await e._loadSnapshot;ArrayBuffer.isView(f)?o=f:o=new Uint8Array(f),a.noInitialRun=!0,a.INITIAL_MEMORY=o.length}let s=await _createPyodideModule(a);if(a.exited)throw a.exited.toThrow;if(e.pyproxyToStringRepr&&n.setPyProxyToStringMethod(!0),n.version!==C&&r.checkAPIVersion)throw new Error(`Pyodide version does not match: '${C}' <==> '${n.version}'. If you updated the Pyodide version, make sure you also updated the 'indexURL' parameter passed to loadPyodide.`);s.locateFile=f=>{throw new Error("Didn't expect to load any more file_packager files!")};let l;o&&(l=n.restoreSnapshot(o));let d=n.finalizeBootstrap(l);return n.sys.path.insert(0,n.config.env.HOME),d.version.includes("dev")||n.setCdnUrl(`https://cdn.jsdelivr.net/pyodide/v${d.version}/full/`),n._pyodide.set_excepthook(),await n.packageIndexReady,n.initializeStreams(r.stdin,r.stdout,r.stderr),d}c($e,"loadPyodide");export{$e as loadPyodide,C as version}; +var Q=Object.defineProperty;var s=(e,t)=>Q(e,"name",{value:t,configurable:!0}),I=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,o)=>(typeof require<"u"?require:t)[o]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+e+'" is not supported')});function Z(e){return!isNaN(parseFloat(e))&&isFinite(e)}s(Z,"_isNumber");function E(e){return e.charAt(0).toUpperCase()+e.substring(1)}s(E,"_capitalize");function P(e){return function(){return this[e]}}s(P,"_getter");var w=["isConstructor","isEval","isNative","isToplevel"],N=["columnNumber","lineNumber"],_=["fileName","functionName","source"],ee=["args"],te=["evalOrigin"],O=w.concat(N,_,ee,te);function p(e){if(e)for(var t=0;t-1&&(n=n.replace(/eval code/g,"eval").replace(/(\(eval at [^()]*)|(,.*$)/g,""));var i=n.replace(/^\s+/,"").replace(/\(eval code/g,"(").replace(/^.*?\s+/,""),c=i.match(/ (\(.+\)$)/);i=c?i.replace(c[0],""):i;var l=this.extractLocation(c?c[1]:i),d=c&&i||void 0,u=["eval",""].indexOf(l[0])>-1?void 0:l[0];return new x({functionName:d,fileName:u,lineNumber:l[1],columnNumber:l[2],source:n})},this)},"ErrorStackParser$$parseV8OrIE"),parseFFOrSafari:s(function(r){var a=r.stack.split(` +`).filter(function(n){return!n.match(t)},this);return a.map(function(n){if(n.indexOf(" > eval")>-1&&(n=n.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1")),n.indexOf("@")===-1&&n.indexOf(":")===-1)return new x({functionName:n});var i=/((.*".+"[^@]*)?[^@]*)(?:@)/,c=n.match(i),l=c&&c[1]?c[1]:void 0,d=this.extractLocation(n.replace(i,""));return new x({functionName:l,fileName:d[0],lineNumber:d[1],columnNumber:d[2],source:n})},this)},"ErrorStackParser$$parseFFOrSafari")}}s(ne,"ErrorStackParser");var re=new ne;var C=re;var g=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string"&&!process.browser,A=g&&typeof module<"u"&&typeof module.exports<"u"&&typeof I<"u"&&typeof __dirname<"u",W=g&&!A,Ne=typeof globalThis.Bun<"u",ie=typeof Deno<"u",B=!g&&!ie,$=B&&typeof window=="object"&&typeof document=="object"&&typeof document.createElement=="function"&&"sessionStorage"in window&&typeof importScripts!="function",j=B&&typeof importScripts=="function"&&typeof self=="object",_e=typeof navigator=="object"&&typeof navigator.userAgent=="string"&&navigator.userAgent.indexOf("Chrome")==-1&&navigator.userAgent.indexOf("Safari")>-1;var z,D,V,H,L;async function T(){if(!g||(z=(await import("node:url")).default,H=await import("node:fs"),L=await import("node:fs/promises"),V=(await import("node:vm")).default,D=await import("node:path"),U=D.sep,typeof I<"u"))return;let e=H,t=await import("node:crypto"),o=await import("ws"),r=await import("node:child_process"),a={fs:e,crypto:t,ws:o,child_process:r};globalThis.require=function(n){return a[n]}}s(T,"initNodeModules");function oe(e,t){return D.resolve(t||".",e)}s(oe,"node_resolvePath");function ae(e,t){return t===void 0&&(t=location),new URL(e,t).toString()}s(ae,"browser_resolvePath");var k;g?k=oe:k=ae;var U;g||(U="/");function se(e,t){return e.startsWith("file://")&&(e=e.slice(7)),e.includes("://")?{response:fetch(e)}:{binary:L.readFile(e).then(o=>new Uint8Array(o.buffer,o.byteOffset,o.byteLength))}}s(se,"node_getBinaryResponse");function ce(e,t){let o=new URL(e,location);return{response:fetch(o,t?{integrity:t}:{})}}s(ce,"browser_getBinaryResponse");var R;g?R=se:R=ce;async function q(e,t){let{response:o,binary:r}=R(e,t);if(r)return r;let a=await o;if(!a.ok)throw new Error(`Failed to load '${e}': request failed.`);return new Uint8Array(await a.arrayBuffer())}s(q,"loadBinaryFile");var F;if($)F=s(async e=>await import(e),"loadScript");else if(j)F=s(async e=>{try{globalThis.importScripts(e)}catch(t){if(t instanceof TypeError)await import(e);else throw t}},"loadScript");else if(g)F=le;else throw new Error("Cannot determine runtime environment");async function le(e){e.startsWith("file://")&&(e=e.slice(7)),e.includes("://")?V.runInThisContext(await(await fetch(e)).text()):await import(z.pathToFileURL(e).href)}s(le,"nodeLoadScript");async function J(e){if(g){await T();let t=await L.readFile(e,{encoding:"utf8"});return JSON.parse(t)}else return await(await fetch(e)).json()}s(J,"loadLockFile");async function K(){if(A)return __dirname;let e;try{throw new Error}catch(r){e=r}let t=C.parse(e)[0].fileName;if(g&&!t.startsWith("file://")&&(t=`file://${t}`),W){let r=await import("node:path");return(await import("node:url")).fileURLToPath(r.dirname(t))}let o=t.lastIndexOf(U);if(o===-1)throw new Error("Could not extract indexURL path from pyodide module location");return t.slice(0,o)}s(K,"calculateDirname");function Y(e){let t=e.FS,o=e.FS.filesystems.MEMFS,r=e.PATH,a={DIR_MODE:16895,FILE_MODE:33279,mount:function(n){if(!n.opts.fileSystemHandle)throw new Error("opts.fileSystemHandle is required");return o.mount.apply(null,arguments)},syncfs:async(n,i,c)=>{try{let l=a.getLocalSet(n),d=await a.getRemoteSet(n),u=i?d:l,m=i?l:d;await a.reconcile(n,u,m),c(null)}catch(l){c(l)}},getLocalSet:n=>{let i=Object.create(null);function c(u){return u!=="."&&u!==".."}s(c,"isRealDir");function l(u){return m=>r.join2(u,m)}s(l,"toAbsolute");let d=t.readdir(n.mountpoint).filter(c).map(l(n.mountpoint));for(;d.length;){let u=d.pop(),m=t.stat(u);t.isDir(m.mode)&&d.push.apply(d,t.readdir(u).filter(c).map(l(u))),i[u]={timestamp:m.mtime,mode:m.mode}}return{type:"local",entries:i}},getRemoteSet:async n=>{let i=Object.create(null),c=await de(n.opts.fileSystemHandle);for(let[l,d]of c)l!=="."&&(i[r.join2(n.mountpoint,l)]={timestamp:d.kind==="file"?(await d.getFile()).lastModifiedDate:new Date,mode:d.kind==="file"?a.FILE_MODE:a.DIR_MODE});return{type:"remote",entries:i,handles:c}},loadLocalEntry:n=>{let c=t.lookupPath(n).node,l=t.stat(n);if(t.isDir(l.mode))return{timestamp:l.mtime,mode:l.mode};if(t.isFile(l.mode))return c.contents=o.getFileDataAsTypedArray(c),{timestamp:l.mtime,mode:l.mode,contents:c.contents};throw new Error("node type not supported")},storeLocalEntry:(n,i)=>{if(t.isDir(i.mode))t.mkdirTree(n,i.mode);else if(t.isFile(i.mode))t.writeFile(n,i.contents,{canOwn:!0});else throw new Error("node type not supported");t.chmod(n,i.mode),t.utime(n,i.timestamp,i.timestamp)},removeLocalEntry:n=>{var i=t.stat(n);t.isDir(i.mode)?t.rmdir(n):t.isFile(i.mode)&&t.unlink(n)},loadRemoteEntry:async n=>{if(n.kind==="file"){let i=await n.getFile();return{contents:new Uint8Array(await i.arrayBuffer()),mode:a.FILE_MODE,timestamp:i.lastModifiedDate}}else{if(n.kind==="directory")return{mode:a.DIR_MODE,timestamp:new Date};throw new Error("unknown kind: "+n.kind)}},storeRemoteEntry:async(n,i,c)=>{let l=n.get(r.dirname(i)),d=t.isFile(c.mode)?await l.getFileHandle(r.basename(i),{create:!0}):await l.getDirectoryHandle(r.basename(i),{create:!0});if(d.kind==="file"){let u=await d.createWritable();await u.write(c.contents),await u.close()}n.set(i,d)},removeRemoteEntry:async(n,i)=>{await n.get(r.dirname(i)).removeEntry(r.basename(i)),n.delete(i)},reconcile:async(n,i,c)=>{let l=0,d=[];Object.keys(i.entries).forEach(function(f){let y=i.entries[f],S=c.entries[f];(!S||t.isFile(y.mode)&&y.timestamp.getTime()>S.timestamp.getTime())&&(d.push(f),l++)}),d.sort();let u=[];if(Object.keys(c.entries).forEach(function(f){i.entries[f]||(u.push(f),l++)}),u.sort().reverse(),!l)return;let m=i.type==="remote"?i.handles:c.handles;for(let f of d){let y=r.normalize(f.replace(n.mountpoint,"/")).substring(1);if(c.type==="local"){let S=m.get(y),X=await a.loadRemoteEntry(S);a.storeLocalEntry(f,X)}else{let S=a.loadLocalEntry(f);await a.storeRemoteEntry(m,y,S)}}for(let f of u)if(c.type==="local")a.removeLocalEntry(f);else{let y=r.normalize(f.replace(n.mountpoint,"/")).substring(1);await a.removeRemoteEntry(m,y)}}};e.FS.filesystems.NATIVEFS_ASYNC=a}s(Y,"initializeNativeFS");var de=s(async e=>{let t=[];async function o(a){for await(let n of a.values())t.push(n),n.kind==="directory"&&await o(n)}s(o,"collect"),await o(e);let r=new Map;r.set(".",e);for(let a of t){let n=(await e.resolve(a)).join("/");r.set(n,a)}return r},"getFsHandles");function G(e){let t={noImageDecoding:!0,noAudioDecoding:!0,noWasmDecoding:!1,preRun:ge(e),quit(o,r){throw t.exited={status:o,toThrow:r},r},print:e.stdout,printErr:e.stderr,arguments:e.args,API:{config:e},locateFile:o=>e.indexURL+o,instantiateWasm:ye(e.indexURL)};return t}s(G,"createSettings");function ue(e){return function(t){let o="/";try{t.FS.mkdirTree(e)}catch(r){console.error(`Error occurred while making a home directory '${e}':`),console.error(r),console.error(`Using '${o}' for a home directory instead`),e=o}t.FS.chdir(e)}}s(ue,"createHomeDirectory");function fe(e){return function(t){Object.assign(t.ENV,e)}}s(fe,"setEnvironment");function me(e){return t=>{for(let o of e)t.FS.mkdirTree(o),t.FS.mount(t.FS.filesystems.NODEFS,{root:o},o)}}s(me,"mountLocalDirectories");function pe(e){let t=q(e);return o=>{let r=o._py_version_major(),a=o._py_version_minor();o.FS.mkdirTree("/lib"),o.FS.mkdirTree(`/lib/python${r}.${a}/site-packages`),o.addRunDependency("install-stdlib"),t.then(n=>{o.FS.writeFile(`/lib/python${r}${a}.zip`,n)}).catch(n=>{console.error("Error occurred while installing the standard library:"),console.error(n)}).finally(()=>{o.removeRunDependency("install-stdlib")})}}s(pe,"installStdlib");function ge(e){let t;return e.stdLibURL!=null?t=e.stdLibURL:t=e.indexURL+"python_stdlib.zip",[pe(t),ue(e.env.HOME),fe(e.env),me(e._node_mounts),Y]}s(ge,"getFileSystemInitializationFuncs");function ye(e){if(typeof WasmOffsetConverter<"u")return;let{binary:t,response:o}=R(e+"pyodide.asm.wasm");return function(r,a){return async function(){try{let n;o?n=await WebAssembly.instantiateStreaming(o,r):n=await WebAssembly.instantiate(await t,r);let{instance:i,module:c}=n;a(i,c)}catch(n){console.warn("wasm instantiation failed!"),console.warn(n)}}(),{}}}s(ye,"getInstantiateWasmFunc");var M="0.27.2";async function $e(e={}){var u,m;await T();let t=e.indexURL||await K();t=k(t),t.endsWith("/")||(t+="/"),e.indexURL=t;let o={fullStdLib:!1,jsglobals:globalThis,stdin:globalThis.prompt?globalThis.prompt:void 0,lockFileURL:t+"pyodide-lock.json",args:[],_node_mounts:[],env:{},packageCacheDir:t,packages:[],enableRunUntilComplete:!1,checkAPIVersion:!0,BUILD_ID:"f88dc4abb40ec8e780c94a5f70bcef45ec9eb3c1aee1c99da527febfef1c6f3f"},r=Object.assign(o,e);(u=r.env).HOME??(u.HOME="/home/pyodide"),(m=r.env).PYTHONINSPECT??(m.PYTHONINSPECT="1");let a=G(r),n=a.API;if(n.lockFilePromise=J(r.lockFileURL),typeof _createPyodideModule!="function"){let f=`${r.indexURL}pyodide.asm.js`;await F(f)}let i;if(e._loadSnapshot){let f=await e._loadSnapshot;ArrayBuffer.isView(f)?i=f:i=new Uint8Array(f),a.noInitialRun=!0,a.INITIAL_MEMORY=i.length}let c=await _createPyodideModule(a);if(a.exited)throw a.exited.toThrow;if(e.pyproxyToStringRepr&&n.setPyProxyToStringMethod(!0),n.version!==M&&r.checkAPIVersion)throw new Error(`Pyodide version does not match: '${M}' <==> '${n.version}'. If you updated the Pyodide version, make sure you also updated the 'indexURL' parameter passed to loadPyodide.`);c.locateFile=f=>{throw new Error("Didn't expect to load any more file_packager files!")};let l;i&&(l=n.restoreSnapshot(i));let d=n.finalizeBootstrap(l,e._snapshotDeserializer);return n.sys.path.insert(0,n.config.env.HOME),d.version.includes("dev")||n.setCdnUrl(`https://cdn.jsdelivr.net/pyodide/v${d.version}/full/`),n._pyodide.set_excepthook(),await n.packageIndexReady,n.initializeStreams(r.stdin,r.stdout,r.stderr),d}s($e,"loadPyodide");export{$e as loadPyodide,M as version}; //# sourceMappingURL=pyodide.mjs.map From d3f9fc63e0460b20577173c81faca3d349070072 Mon Sep 17 00:00:00 2001 From: Winston Chang Date: Tue, 28 Jan 2025 16:45:20 -0600 Subject: [PATCH 2/2] Stop using custom build of pyodide --- .gitmodules | 3 --- Makefile | 22 +--------------------- packages/plotnine | 1 - shinylive_lock.json | 35 +++++++++++++++++------------------ shinylive_requirements.json | 7 +------ 5 files changed, 19 insertions(+), 49 deletions(-) delete mode 160000 packages/plotnine diff --git a/.gitmodules b/.gitmodules index 2f0f79e1..217a3e84 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,6 +13,3 @@ [submodule "packages/py-faicons"] path = packages/py-faicons url = https://github.com/posit-dev/py-faicons.git -[submodule "packages/plotnine"] - path = packages/plotnine - url = https://github.com/wch/plotnine.git diff --git a/Makefile b/Makefile index 0b0b34b8..a2a1edd8 100644 --- a/Makefile +++ b/Makefile @@ -41,10 +41,6 @@ SHINY_WHEEL = shiny-$(SHINY_VERSION)-py3-none-any.whl SHINYWIDGETS_WHEEL = shinywidgets-$(SHINYWIDGETS_VERSION)-py3-none-any.whl FAICONS_WHEEL = faicons-$(FAICONS_VERSION)-py3-none-any.whl -# Hard code these versions for now -PLOTNINE_VERSION=0.0.0 -PLOTNINE_WHEEL=plotnine-$(PLOTNINE_VERSION)-py3-none-any.whl - # libsass is built in gadenbuie/libsass-python # NOTE: Update https://github.com/gadenbuie/libsass-python/blob/dev/.github/workflows/pyodide.yml # Pyodide, Emscripten, or Python versions change here. @@ -97,13 +93,11 @@ submodules: git submodule init git submodule update --depth=20 cd packages/py-shiny && git fetch --tags --unshallow - cd packages/plotnine && git fetch --tags --unshallow ## Pull latest changes in git submodules submodules-pull: git submodule update --recursive --remote cd packages/py-shiny && git fetch --tags - cd packages/plotnine && git fetch --tags submodules-pull-shiny: git submodule update --remote packages/py-shiny cd packages/py-shiny && git fetch --tags @@ -178,7 +172,6 @@ pyodide_packages_local: $(BUILD_DIR)/shinylive/pyodide/$(HTMLTOOLS_WHEEL) \ $(BUILD_DIR)/shinylive/pyodide/$(SHINY_WHEEL) \ $(BUILD_DIR)/shinylive/pyodide/$(SHINYWIDGETS_WHEEL) \ $(BUILD_DIR)/shinylive/pyodide/$(FAICONS_WHEEL) \ - $(BUILD_DIR)/shinylive/pyodide/$(PLOTNINE_WHEEL) \ $(BUILD_DIR)/shinylive/pyodide/$(LIBSASS_WHEEL) \ $(BUILD_DIR)/shinylive/pyodide/$(POLARS_WHEEL) @@ -206,11 +199,6 @@ $(BUILD_DIR)/shinylive/pyodide/$(FAICONS_WHEEL): $(PACKAGE_DIR)/$(FAICONS_WHEEL) rm -f $(BUILD_DIR)/shinylive/pyodide/faicons*.whl cp $(PACKAGE_DIR)/$(FAICONS_WHEEL) $(BUILD_DIR)/shinylive/pyodide/$(FAICONS_WHEEL) -$(BUILD_DIR)/shinylive/pyodide/$(PLOTNINE_WHEEL): $(PACKAGE_DIR)/$(PLOTNINE_WHEEL) - mkdir -p $(BUILD_DIR)/shinylive/pyodide - rm -f $(BUILD_DIR)/shinylive/pyodide/plotnine*.whl - cp $(PACKAGE_DIR)/$(PLOTNINE_WHEEL) $(BUILD_DIR)/shinylive/pyodide/$(PLOTNINE_WHEEL) - $(BUILD_DIR)/shinylive/pyodide/$(LIBSASS_WHEEL): $(PACKAGE_DIR)/$(LIBSASS_WHEEL) mkdir -p $(BUILD_DIR)/shinylive/pyodide rm -f $(BUILD_DIR)/shinylive/pyodide/libsass*.whl @@ -281,8 +269,7 @@ packages: clean-packages \ package-htmltools \ package-shiny \ package-shinywidgets \ - package-faicons \ - package-plotnine + package-faicons package-htmltools: $(PACKAGE_DIR)/$(HTMLTOOLS_WHEEL) @@ -293,8 +280,6 @@ package-shinywidgets: $(PACKAGE_DIR)/$(SHINYWIDGETS_WHEEL) package-faicons: $(PACKAGE_DIR)/$(FAICONS_WHEEL) -package-plotnine: $(PACKAGE_DIR)/$(PLOTNINE_WHEEL) - $(PACKAGE_DIR)/$(HTMLTOOLS_WHEEL): $(PYBIN) $(PACKAGE_DIR)/py-htmltools # Remove any old copies of the package @@ -317,11 +302,6 @@ $(PACKAGE_DIR)/$(FAICONS_WHEEL): $(PYBIN) $(PACKAGE_DIR)/py-faicons rm -f $(PACKAGE_DIR)/faicons*.whl . $(PYBIN)/activate && cd $(PACKAGE_DIR)/py-faicons && make install && mv dist/*.whl ../ -$(PACKAGE_DIR)/$(PLOTNINE_WHEEL): $(PYBIN) $(PACKAGE_DIR)/plotnine - rm -f $(PACKAGE_DIR)/plotnine*.whl - $(PYBIN)/pip install -e $(PACKAGE_DIR)/plotnine[build] - . $(PYBIN)/activate && cd $(PACKAGE_DIR)/plotnine && make dist && mv dist/*.whl ../$(PLOTNINE_WHEEL) - $(PACKAGE_DIR)/$(LIBSASS_WHEEL): $(PYBIN) $(PACKAGE_DIR)/$(LIBSASS_WHEEL) rm -f $(PACKAGE_DIR)/libsass*.whl curl --fail -L https://pkg.garrickadenbuie.com/libsass-python/$(LIBSASS_WHEEL) -o $(PACKAGE_DIR)/$(LIBSASS_WHEEL) diff --git a/packages/plotnine b/packages/plotnine deleted file mode 160000 index 64295e1a..00000000 --- a/packages/plotnine +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 64295e1a058ef34aa01f752611f24285364220e8 diff --git a/shinylive_lock.json b/shinylive_lock.json index b0f356a0..63c2478e 100644 --- a/shinylive_lock.json +++ b/shinylive_lock.json @@ -97,18 +97,17 @@ }, "plotnine": { "name": "plotnine", - "version": "0.10.1.post98+g64295e1a", - "filename": "plotnine-0.0.0-py3-none-any.whl", - "sha256": null, - "url": null, + "version": "0.14.5", + "filename": "plotnine-0.14.5-py3-none-any.whl", + "sha256": "4a8bc4360732dd69a0263def4abab285ed8f0f4386186f1e44c642f2cea79b88", + "url": "https://files.pythonhosted.org/packages/4d/c5/7cfda7ba9fa02243367fbfb4880b6de8039266f22c47c2dbbd39b6adc46f/plotnine-0.14.5-py3-none-any.whl", "depends": [ - {"name": "matplotlib", "specs": [[">=", "3.5.0"]]}, - {"name": "mizani", "specs": [[">=", "0.8.1"]]}, - {"name": "numpy", "specs": [[">=", "1.23.0"]]}, - {"name": "pandas", "specs": [[">=", "1.3.5"]]}, - {"name": "patsy", "specs": [[">=", "0.5.1"]]}, - {"name": "scipy", "specs": [[">=", "1.5.0"]]}, - {"name": "statsmodels", "specs": [[">=", "0.13.2"]]} + {"name": "matplotlib", "specs": [[">=", "3.8.0"]]}, + {"name": "pandas", "specs": [[">=", "2.2.0"]]}, + {"name": "mizani", "specs": [["~=", "0.13.0"]]}, + {"name": "numpy", "specs": [[">=", "1.23.5"]]}, + {"name": "scipy", "specs": [[">=", "1.8.0"]]}, + {"name": "statsmodels", "specs": [[">=", "0.14.0"]]} ], "imports": [ "plotnine" @@ -325,14 +324,14 @@ }, "mizani": { "name": "mizani", - "version": "0.11.4", - "filename": "mizani-0.11.4-py3-none-any.whl", - "sha256": "5b6271dc3da2c88694dca2e0e0a7e1879f0e2fb046c789776f54d090a5243735", - "url": "https://files.pythonhosted.org/packages/2a/11/f3777ad46c5d92e3ead121c22ea45fafb6c3b2c1edca0c0c6494969c125c/mizani-0.11.4-py3-none-any.whl", + "version": "0.13.1", + "filename": "mizani-0.13.1-py3-none-any.whl", + "sha256": "7da0dcacd43fbcc01c279ea06a76f1f064ae90dbb387c4a985ba24a92d3c7d7a", + "url": "https://files.pythonhosted.org/packages/29/85/16e17e75831ec01808c5f07e578f1552df87a4f5c827caa8be28f97b4c19/mizani-0.13.1-py3-none-any.whl", "depends": [ - {"name": "numpy", "specs": [[">=", "1.23.0"]]}, - {"name": "scipy", "specs": [[">=", "1.7.0"]]}, - {"name": "pandas", "specs": [[">=", "2.1.0"]]}, + {"name": "numpy", "specs": [[">=", "1.23.5"]]}, + {"name": "scipy", "specs": [[">=", "1.8.0"]]}, + {"name": "pandas", "specs": [[">=", "2.2.0"]]}, {"name": "tzdata", "specs": []} ], "imports": [ diff --git a/shinylive_requirements.json b/shinylive_requirements.json index 4ebba4fb..2bbde915 100644 --- a/shinylive_requirements.json +++ b/shinylive_requirements.json @@ -10,12 +10,7 @@ "version": "latest", "comment": "Needed to suppress warning from shiny/ui/_markdown.py." }, - { - "name": "plotnine", - "source": "local", - "version": "latest", - "comment": "Fixed version needed to avoid problem with mizani calling zoneinfo.ZoneInfo('UTC')." - }, + { "name": "plotnine", "source": "pypi", "version": "latest" }, { "name": "plotly", "source": "pypi", "version": "latest" }, { "name": "seaborn", "source": "pypi", "version": "latest" }, { "name": "ipywidgets", "source": "pypi", "version": "latest" },