Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Published wheels JS dependencies ... what could we do about it?#2301

WebReflection started this conversation inProposals
Discussion options

After a long discussionon our Discord channel I feel like we need to provide broader context and an easier way to discuss this forward, so here thediscussion around that topic.

You must be logged in to vote

Replies: 3 comments 5 replies

Comment options

WebReflection
Feb 26, 2025
Maintainer Author

Summarizing the previous discussion:

  • awheel would like to declare itsoptionalJS dependency once imported as package
  • we, thePyScript team, could offer an indirect solution through theconfig but that would not scale for suchwheel
  • thewheel should not statePyScript is needed, so that such package, with its JS dependencies, could work elsewhere too
  • the proposal is to have abrowser_env.json that dictates dependencies from the browser neededbefore the package executes
  • my idea is thatenv.json would be a better place to have abrowser field that contains bothmain andworker related fields, to disambiguate the package need in case it's running from the main thread or a worker
  • from now on ... it's discussion board/field, as long as we realize this is not aPyScript only request, this is something that should benefitpip or any publiched Python package to date in the future ... so please be careful with variants around this proposal, thank you!
You must be logged in to vote
0 replies
Comment options

Use-case

A cross-platform library implements functionality in a cross-platform way, across Windows, Mac, Linux, and browsers. It delegating to the appropriate platform-specific APIs and dependencies.
For example,funaudiolibrary supports audio playback across Windows, Linux, Mac, and browser using appropriate platform-specific APIs. In browser environments,funaudiolibrary leans on a.js shim/module which must be loaded into the browser environment.

Consumers offunaudiolibrary cansynchronouslyimport funaudiolibrary ; funaudiolibrary.play_sine_wave(440) without extra pyscript configuration.

Strawman proposal

Suppose a wheel can contain 2x files:

browser_adapter.js

// JS code that is loaded in the main thread or a worker thread async *before* the user's entrypoint .py begins executionclass EfficientJsTalksToWebAudioApi {  // ...}

browser_environment.json

// A manifest describing necessary bootstrapping tasks to support this python module in browser environment{  "main_modules": [    "./browser_adapter.js" // relative path within the VFS  ],  "worker_modules: [] // scripts to load in worker thread instead of main thread}

Browser runtime environments can bootstrap themselves like this:

  • Ask micropip/pypy/pip to fetch dependencies (this is async downloading)
  • Load them all into the VFS
  • asynchronously load required JS shims into main or worker thread
fordepinall_deps:ifVFS.exists(dep.path+"/browser_environment.json"):browser_env_manifest=parse_json(VFS.read(dep.path+"/browser_environment.json"))forjs_pathinbrowser_env_manifest.main_modules:load_js_into_main_thread(VFS.read(dep.path+js_path)
  • execute user's entrypoint .py

So when the user doesimport funaudiolibrary the library is able to synchronously access the JS library and call it immediately.

You must be logged in to vote
5 replies
@WebReflection
Comment options

WebReflectionFeb 26, 2025
Maintainer Author

interesting, here my counter-arguments:

  • why does it need to be abrowser_environment.json thing? wouldn't anenv.json fulfill the same purpose, as long as it has abrowser field in it?
  • you are assuming we knowdependencies paths ... well, we don't, we letmicropip do its job and we never look back to date ... re-looping all packages paths might be doable but ifmicropip doesn't give us back pathe per package name, we can't check for anything in there
  • previous point means if a package depends on another package with same dependency but different version:
    • we have no idea what should happen on the main thread
    • we have no idea how to handle different JS module for the same path
    • we are into dependencies injection hell that (imho) only top-level importer should care about, risking to break the rest of the code around
  • we currently supportCSS related modules too per eachJS package, where is that reflected as dependency as most Web dependent modules might trust their related CSS was there too?

These are all issues we've solved already via our config, but while I like the direction this discussion is taking, I want to be sure all our previous discussions are taken into account too.

@cspotcode
Comment options

How about we update the manifest schema to closely match the relevant parts ofpyscript.toml? I don't have a good reason for choosing.json; my only goal was to describe a static manifest containing a data structure, metadata, that runtimes can read without executing any.py or.js code.

well, we don't [know dependencies paths]

Interesting, ok, we want micropip to give us an array of the installed dependency names. Then, can we use python'simport resolver to locate each module to read its metadata?importlib.util.find_spec(dependency_name)?

Or, alternatively, can we find everysys.path[*]/*/env.json or something similar? Since, as far as I understand, all dependencies are imported from subdirectories ofsys.path entries.

@cspotcode
Comment options

Looks likemicropip.list() returns a list of dependencies. But I'm not sure the paths we get fromfind_spec will reliably point to the root directory of the wheel.

importmicropipimportimportlibimportpkgutildeps=micropip.list()print(deps)fordepName,depindeps.items():print(importlib.util.find_spec(depName))
@cspotcode
Comment options

if a package depends on another package with same dependency but different version

I thought python did not support this, that you can only have one version of each library loaded into the runtime.

@WebReflection
Comment options

WebReflectionFeb 26, 2025
Maintainer Author

those are indirect dependencies ... if Python guarantees once a version of any package is granted and reflected all over other dependencies, then yes, we can scratch that from my list of "what if" but aboutlist, that's both good news but most complains aroundPyodide are around bootstrap time + we would like to have feature parity withmip (the MicroPython counterpart) so ... investigation and some benchmark needed, but that might be it for Pyodide at least ... let's see!

Comment options

Examples in the wild: pyglet

pyglet does not current support browser runtimes, but they're interested in supporting them eventually. So they might use this proposal.

Audio

For example, pyglet supports multiple audio backends for different platforms. Roughly, it has a list of each backend. It iterates, attempts to load each in atry: block, stops at the first one which loads successfully.

I understand that pyodide/pygbag already supports some audio APIs, so maybe pyglet's existing OpenAL backend will "just work." Or perhaps pyglet will implement an additionalwebaudio backend which relies on a companion.js library.

Here are links to the relevant code:
https://github.com/pyglet/pyglet/blob/c374de9c654dac5af7e46b9c403af2f417f49bbb/pyglet/__init__.py#L53-L56
https://github.com/pyglet/pyglet/blob/c374de9c654dac5af7e46b9c403af2f417f49bbb/pyglet/media/drivers/__init__.py#L18-L19
https://github.com/pyglet/pyglet/blob/c374de9c654dac5af7e46b9c403af2f417f49bbb/pyglet/media/drivers/__init__.py#L62-L73

Font rendering

Another example: font loading, font rendering.

Here, pyglet usespyglet.compat_platform to decide which implementation to load. Each usesctypes to bind to native platform APIs.
https://github.com/pyglet/pyglet/blob/c374de9c654dac5af7e46b9c403af2f417f49bbb/pyglet/font/__init__.py#L33-L54

I can imagine pyglet adding another "web" platform, conditionally using the browser'sFontFace andCanvas APIs to load fonts. This could be done directly from python using FFI, but it might be more performant or easier to write the backend in .js using .js dependencies.

You must be logged in to vote
0 replies
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Labels
None yet
2 participants
@WebReflection@cspotcode

[8]ページ先頭

©2009-2025 Movatter.jp