Skip to content

Add Emscripten/Pyodide support#1022

Open
hoodmane wants to merge 13 commits into
pydantic:mainfrom
hoodmane:pyodide-httpx2
Open

Add Emscripten/Pyodide support#1022
hoodmane wants to merge 13 commits into
pydantic:mainfrom
hoodmane:pyodide-httpx2

Conversation

@hoodmane
Copy link
Copy Markdown

@hoodmane hoodmane commented Jun 3, 2026

Checklist

  • I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.

Comment thread .github/workflows/main.yml Fixed
Comment thread .github/workflows/main.yml Fixed
Comment thread .github/workflows/main.yml Fixed
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Jun 3, 2026

Merging this PR will not alter performance

✅ 15 untouched benchmarks
⏩ 7 skipped benchmarks1


Comparing hoodmane:pyodide-httpx2 (6e1a1b0) with main (3146201)

Open in CodSpeed

Footnotes

  1. 7 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 issues found across 20 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/download-pyodide">

<violation number="1" location="scripts/download-pyodide:18">
P2: `pyodide_js.loadPackage()` is an async function returning a Promise, but it is called without `await` or any synchronization. The Python process may exit before packages finish loading, causing nondeterministic environment setup.</violation>
</file>

<file name="tests/httpx2/emscripten/conftest.py">

<violation number="1" location="tests/httpx2/emscripten/conftest.py:65">
P2: Worker fixture lookup is based on an unsupported naming convention, so worker-based emscripten tests will fail to find a fixture.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/httpx2/httpx2/_transports/jsfetch.py Outdated
Comment thread src/httpx2/httpx2/_transports/jsfetch.py
Comment thread docs/advanced/emscripten.md Outdated
Comment thread docs/advanced/emscripten.md Outdated
Comment thread docs/overrides/pyodide.html
Comment thread scripts/download-pyodide Outdated
Comment thread tests/httpx2/emscripten/conftest.py
Comment thread pyproject.toml
Comment on lines +84 to +88
[tool.coverage.paths]
source = [
"src/httpx2/httpx2",
"*/site-packages/httpx2",
]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this interact with source_pkgs above?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is orthogonal: [tool.coverage.run] indicates what files should get coverage information initially, [tool.coverage.paths] controls how coverage combine remaps paths. I think when you run the native tests, it uses an editable install so the file paths point into the source tree. On the other hand, in Pyodide it has to install the wheel into site-packages, and this tells it to remap the path back to the source tree path.

Comment thread requirements-emscripten.txt Outdated
Comment thread tests/httpx2/conftest.py Outdated
Comment on lines +344 to +345
cert_pem_file: str,
cert_private_key_file: str,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just add those to the above server fixture, and have a single one?

Comment thread tests/httpx2/conftest.py

# For testing on emscripten, we require cross origin isolation headers
# to be set or else browsers won't be able to read from us from javascript
async def hello_world_emscripten(scope: Scope, receive: Receive, send: Send) -> None: # pragma: nocover for emscripten
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a new custom pragma in exclude_also in coverage report called pragma: emscripten please.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't # pragma: nocover emscripten clearer than # pragma: emscripten?

Comment thread tests/httpx2/conftest.py
Comment on lines +115 to +136
# For testing on emscripten, it is useful to be able to
# get the wheel package so that we can install it e.g.
# on web-workers
async def wheel_download(scope: Scope, receive: Receive, send: Send) -> None: # pragma: nocover for emscripten
wheel_file = sorted(Path("dist").glob("httpx2-*.whl"))[0]
await send(
{
"type": "http.response.start",
"status": 200,
"headers": [
[b"content-type", b"application/x-wheel"],
[b"access-control-allow-origin", b"*"],
[
b"access-control-allow-methods",
b"PUT, GET, HEAD, POST, DELETE, OPTIONS",
],
[b"Access-Control-Allow-Headers", b"*"],
],
}
)
wheel_bytes = wheel_file.read_bytes()
await send({"type": "http.response.body", "body": wheel_bytes})
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a bit weird. The endpoints here are used by the tests.

Just pointing out.

Comment thread tests/httpx2/emscripten/test_emscripten.py Outdated
Comment thread tests/httpx2/emscripten/test_emscripten.py Outdated
Comment thread .github/workflows/main.yml Outdated
Comment thread docs/index.md Outdated
Comment thread scripts/coverage
IGNORE_ARGS="--omit=src/httpx2/httpx2/_transports/jsfetch.py,tests/httpx2/emscripten/*"
fi

uv run coverage report ${IGNORE_ARGS} --show-missing --skip-covered --fail-under=100
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm inclined to not have this machinery here, and not care about coverage on jsfetch.py. 🤔

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what it's worth, the coverage information has been quite useful when editing jsfetch.py, the uncovered lines are often buggy.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a coverage purist. I understand this.

Maybe we can have it self contained? e.g. needs to be 100% on the jsfetch and test file. Instead of combining I mean.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well we'll need to combine even if we just want to check jsfetch.py because each call to @run_in_pyodide generates it's own separate coverage file.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 7 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/overrides/pyodide.html">

<violation number="1" location="docs/overrides/pyodide.html:77">
P2: Development-mode detection uses overly broad origin prefix matching instead of exact hostname comparison</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread docs/overrides/pyodide.html
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/overrides/pyodide.html">

<violation number="1" location="docs/overrides/pyodide.html:77">
P2: Development-mode detection uses overly broad origin prefix matching instead of exact hostname comparison</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread tests/httpx2/emscripten/test_emscripten.py Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread src/httpx2/httpx2/_transports/jsfetch.py Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread tests/httpx2/emscripten/conftest.py Outdated
@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented Jun 3, 2026

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants