diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c5b14ab65..5463294cc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1294,6 +1294,45 @@ jobs:
run: |
.\uv.exe pip install anyio
+ integration-test-pyodide-linux:
+ timeout-minutes: 10
+ needs: build-binary-linux-libc
+ name: "integration test | pyodide on ubuntu"
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+
+ - name: "Download binary"
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+ with:
+ name: uv-linux-libc-${{ github.sha }}
+
+ - name: "Prepare binary"
+ run: chmod +x ./uv
+
+ - name: "Create a native virtual environment"
+ run: |
+ ./uv venv venv-native -p 3.12
+ # We use features added in 0.30.3 but there is no known breakage in
+ # newer versions.
+ ./uv pip install -p venv-native/bin/python pyodide-build==0.30.3 pip
+
+ - name: "Install pyodide interpreter"
+ run: |
+ source ./venv-native/bin/activate
+ pyodide xbuildenv install 0.27.5
+ PYODIDE_PYTHON=$(pyodide config get interpreter)
+ PYODIDE_INDEX=$(pyodide config get package_index)
+ echo "PYODIDE_PYTHON=$PYODIDE_PYTHON" >> $GITHUB_ENV
+ echo "PYODIDE_INDEX=$PYODIDE_INDEX" >> $GITHUB_ENV
+
+ - name: "Create pyodide virtual environment"
+ run: |
+ ./uv venv -p $PYODIDE_PYTHON venv-pyodide
+ source ./venv-pyodide/bin/activate
+ ./uv pip install --extra-index-url=$PYODIDE_INDEX --no-build numpy
+ python -c 'import numpy'
+
integration-test-github-actions:
timeout-minutes: 10
needs: build-binary-linux-libc
diff --git a/crates/uv-configuration/src/target_triple.rs b/crates/uv-configuration/src/target_triple.rs
index c0c651409..b9ca3fafe 100644
--- a/crates/uv-configuration/src/target_triple.rs
+++ b/crates/uv-configuration/src/target_triple.rs
@@ -226,6 +226,10 @@ pub enum TargetTriple {
#[serde(rename = "aarch64-manylinux_2_40")]
#[serde(alias = "aarch64-manylinux240")]
Aarch64Manylinux240,
+
+ /// A wasm32 target using the the Pyodide 2024 platform. Meant for use with Python 3.12.
+ #[cfg_attr(feature = "clap", value(name = "wasm32-pyodide2024"))]
+ Wasm32Pyodide2024,
}
impl TargetTriple {
@@ -450,6 +454,13 @@ impl TargetTriple {
},
Arch::Aarch64,
),
+ Self::Wasm32Pyodide2024 => Platform::new(
+ Os::Pyodide {
+ major: 2024,
+ minor: 0,
+ },
+ Arch::Wasm32,
+ ),
}
}
@@ -490,6 +501,7 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "aarch64",
Self::Aarch64Manylinux239 => "aarch64",
Self::Aarch64Manylinux240 => "aarch64",
+ Self::Wasm32Pyodide2024 => "wasm32",
}
}
@@ -530,6 +542,7 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "Linux",
Self::Aarch64Manylinux239 => "Linux",
Self::Aarch64Manylinux240 => "Linux",
+ Self::Wasm32Pyodide2024 => "Emscripten",
}
}
@@ -570,6 +583,10 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "",
Self::Aarch64Manylinux239 => "",
Self::Aarch64Manylinux240 => "",
+ // This is the value Emscripten gives for its version:
+ // https://github.com/emscripten-core/emscripten/blob/4.0.8/system/lib/libc/emscripten_syscall_stubs.c#L63
+ // It doesn't really seem to mean anything? But for completeness we include it here.
+ Self::Wasm32Pyodide2024 => "#1",
}
}
@@ -610,6 +627,9 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "",
Self::Aarch64Manylinux239 => "",
Self::Aarch64Manylinux240 => "",
+ // This is the Emscripten compiler version for Pyodide 2024.
+ // See https://pyodide.org/en/stable/development/abi.html#pyodide-2024-0
+ Self::Wasm32Pyodide2024 => "3.1.58",
}
}
@@ -650,6 +670,7 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "posix",
Self::Aarch64Manylinux239 => "posix",
Self::Aarch64Manylinux240 => "posix",
+ Self::Wasm32Pyodide2024 => "posix",
}
}
@@ -690,6 +711,7 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "linux",
Self::Aarch64Manylinux239 => "linux",
Self::Aarch64Manylinux240 => "linux",
+ Self::Wasm32Pyodide2024 => "emscripten",
}
}
@@ -730,6 +752,7 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => true,
Self::Aarch64Manylinux239 => true,
Self::Aarch64Manylinux240 => true,
+ Self::Wasm32Pyodide2024 => false,
}
}
diff --git a/crates/uv-platform-tags/src/platform.rs b/crates/uv-platform-tags/src/platform.rs
index c2b849e0f..88c36714b 100644
--- a/crates/uv-platform-tags/src/platform.rs
+++ b/crates/uv-platform-tags/src/platform.rs
@@ -43,6 +43,7 @@ pub enum Os {
Manylinux { major: u16, minor: u16 },
Musllinux { major: u16, minor: u16 },
Windows,
+ Pyodide { major: u16, minor: u16 },
Macos { major: u16, minor: u16 },
FreeBsd { release: String },
NetBsd { release: String },
@@ -67,6 +68,7 @@ impl fmt::Display for Os {
Self::Illumos { .. } => write!(f, "illumos"),
Self::Haiku { .. } => write!(f, "haiku"),
Self::Android { .. } => write!(f, "android"),
+ Self::Pyodide { .. } => write!(f, "pyodide"),
}
}
}
@@ -109,6 +111,7 @@ pub enum Arch {
S390X,
LoongArch64,
Riscv64,
+ Wasm32,
}
impl fmt::Display for Arch {
@@ -126,6 +129,7 @@ impl fmt::Display for Arch {
Self::S390X => write!(f, "s390x"),
Self::LoongArch64 => write!(f, "loongarch64"),
Self::Riscv64 => write!(f, "riscv64"),
+ Self::Wasm32 => write!(f, "wasm32"),
}
}
}
@@ -168,7 +172,7 @@ impl Arch {
// manylinux_2_36
Self::LoongArch64 => Some(36),
// unsupported
- Self::Powerpc | Self::Armv5TEL | Self::Armv6L => None,
+ Self::Powerpc | Self::Armv5TEL | Self::Armv6L | Self::Wasm32 => None,
}
}
@@ -187,6 +191,7 @@ impl Arch {
Self::S390X => "s390x",
Self::LoongArch64 => "loongarch64",
Self::Riscv64 => "riscv64",
+ Self::Wasm32 => "wasm32",
}
}
diff --git a/crates/uv-platform-tags/src/platform_tag.rs b/crates/uv-platform-tags/src/platform_tag.rs
index 0ba46200d..1162a83d7 100644
--- a/crates/uv-platform-tags/src/platform_tag.rs
+++ b/crates/uv-platform-tags/src/platform_tag.rs
@@ -71,6 +71,8 @@ pub enum PlatformTag {
Illumos { release_arch: SmallString },
/// Ex) `solaris_11_4_x86_64`
Solaris { release_arch: SmallString },
+ /// Ex) `pyodide_2024_0_wasm32`
+ Pyodide { major: u16, minor: u16 },
}
impl PlatformTag {
@@ -97,6 +99,7 @@ impl PlatformTag {
PlatformTag::Haiku { .. } => Some("Haiku"),
PlatformTag::Illumos { .. } => Some("Illumos"),
PlatformTag::Solaris { .. } => Some("Solaris"),
+ PlatformTag::Pyodide { .. } => Some("Pyodide"),
}
}
}
@@ -262,6 +265,7 @@ impl std::fmt::Display for PlatformTag {
Self::Haiku { release_arch } => write!(f, "haiku_{release_arch}"),
Self::Illumos { release_arch } => write!(f, "illumos_{release_arch}"),
Self::Solaris { release_arch } => write!(f, "solaris_{release_arch}_64bit"),
+ Self::Pyodide { major, minor } => write!(f, "pyodide_{major}_{minor}_wasm32"),
}
}
}
@@ -616,6 +620,35 @@ impl FromStr for PlatformTag {
});
}
+ if let Some(rest) = s.strip_prefix("pyodide_") {
+ let mid =
+ rest.strip_suffix("_wasm32")
+ .ok_or_else(|| ParsePlatformTagError::InvalidArch {
+ platform: "pyodide",
+ tag: s.to_string(),
+ })?;
+ let underscore = memchr::memchr(b'_', mid.as_bytes()).ok_or_else(|| {
+ ParsePlatformTagError::InvalidFormat {
+ platform: "pyodide",
+ tag: s.to_string(),
+ }
+ })?;
+ let major: u16 = mid[..underscore].parse().map_err(|_| {
+ ParsePlatformTagError::InvalidMajorVersion {
+ platform: "pyodide",
+ tag: s.to_string(),
+ }
+ })?;
+
+ let minor: u16 = mid[underscore + 1..].parse().map_err(|_| {
+ ParsePlatformTagError::InvalidMinorVersion {
+ platform: "pyodide",
+ tag: s.to_string(),
+ }
+ })?;
+ return Ok(Self::Pyodide { major, minor });
+ }
+
Err(ParsePlatformTagError::UnknownFormat(s.to_string()))
}
}
@@ -900,6 +933,27 @@ mod tests {
);
}
+ #[test]
+ fn pyodide_platform() {
+ let tag = PlatformTag::Pyodide {
+ major: 2024,
+ minor: 0,
+ };
+ assert_eq!(
+ PlatformTag::from_str("pyodide_2024_0_wasm32").as_ref(),
+ Ok(&tag)
+ );
+ assert_eq!(tag.to_string(), "pyodide_2024_0_wasm32");
+
+ assert_eq!(
+ PlatformTag::from_str("pyodide_2024_0_wasm64"),
+ Err(ParsePlatformTagError::InvalidArch {
+ platform: "pyodide",
+ tag: "pyodide_2024_0_wasm64".to_string()
+ })
+ );
+ }
+
#[test]
fn unknown_platform() {
assert_eq!(
diff --git a/crates/uv-platform-tags/src/tags.rs b/crates/uv-platform-tags/src/tags.rs
index 1e20c348c..7381f5dd5 100644
--- a/crates/uv-platform-tags/src/tags.rs
+++ b/crates/uv-platform-tags/src/tags.rs
@@ -617,6 +617,12 @@ fn compatible_tags(platform: &Platform) -> Result The Python version to use when filtering the tree. For example, pass Defaults to the version of the discovered Python interpreter.--universal
to display the tree for all platforms,
aarch64-manylinux_2_38
: An ARM64 target for the manylinux_2_38
platformaarch64-manylinux_2_39
: An ARM64 target for the manylinux_2_39
platformaarch64-manylinux_2_40
: An ARM64 target for the manylinux_2_40
platformwasm32-pyodide2024
: A wasm32 target using the the Pyodide 2024 platform. Meant for use with Python 3.12--python-version
python-version--python-version 3.10
to display the dependencies that would be included when installing on Python 3.10.--python-version
.
aarch64-manylinux_2_38
: An ARM64 target for the manylinux_2_38
platformaarch64-manylinux_2_39
: An ARM64 target for the manylinux_2_39
platformaarch64-manylinux_2_40
: An ARM64 target for the manylinux_2_40
platformwasm32-pyodide2024
: A wasm32 target using the the Pyodide 2024 platform. Meant for use with Python 3.12--python-version
python-versionThe Python version to use for resolution.
For example, 3.8
or 3.8.17
.
Defaults to the version of the Python interpreter used for resolution.
@@ -3533,6 +3535,7 @@ be used with caution, as it can modify the system Python installation.aarch64-manylinux_2_38
: An ARM64 target for the manylinux_2_38
platformaarch64-manylinux_2_39
: An ARM64 target for the manylinux_2_39
platformaarch64-manylinux_2_40
: An ARM64 target for the manylinux_2_40
platformwasm32-pyodide2024
: A wasm32 target using the the Pyodide 2024 platform. Meant for use with Python 3.12--python-version
python-versionThe minimum Python version that should be supported by the requirements (e.g., 3.7
or 3.7.9
).
If a patch version is omitted, the minimum patch version is assumed. For example, 3.7
is mapped to 3.7.0
.
--quiet
, -q
Use quiet output.
@@ -3796,6 +3799,7 @@ should be used with caution, as it can modify the system Python installation.aarch64-manylinux_2_38
: An ARM64 target for the manylinux_2_38
platform
aarch64-manylinux_2_39
: An ARM64 target for the manylinux_2_39
platformaarch64-manylinux_2_40
: An ARM64 target for the manylinux_2_40
platformwasm32-pyodide2024
: A wasm32 target using the the Pyodide 2024 platform. Meant for use with Python 3.12--python-version
python-versionThe minimum Python version that should be supported by the requirements (e.g., 3.7
or 3.7.9
).
If a patch version is omitted, the minimum patch version is assumed. For example, 3.7
is mapped to 3.7.0
.
--quiet
, -q
Use quiet output.
diff --git a/uv.schema.json b/uv.schema.json index 54d5a0c74..19a6bf4bd 100644 --- a/uv.schema.json +++ b/uv.schema.json @@ -2338,6 +2338,13 @@ "enum": [ "aarch64-manylinux_2_40" ] + }, + { + "description": "A wasm32 target using the the Pyodide 2024 platform. Meant for use with Python 3.12.", + "type": "string", + "enum": [ + "wasm32-pyodide2024" + ] } ] },