From 555563b1b463bc1755f5573e2970b3a08ae7f84a Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 28 Nov 2024 13:37:28 +0000 Subject: [PATCH 01/78] fix: properly setup outbound network connectivity in getting started MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the getting started guide was hardcoding eth0 as the network interface on the host to route outbound microvm network traffic to. However, on EC2 instances (and my laptop), that's wrong, because its not called eth0. So instead dynamically determine the hopefully correct network interface on the host. Fixes: #4930 Suggested-by: Pablo Barbáchano Signed-off-by: Patrick Roy --- docs/getting-started.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 1b55fbf3230..02a2077207b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -197,17 +197,16 @@ sudo ip link set dev "$TAP_DEV" up # Enable ip forwarding sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward" +sudo iptables -P FORWARD ACCEPT -HOST_IFACE="eth0" +# This tries to determine the name of the host network interface to forward +# VM's outbound network traffic through. If outbound traffic doesn't work, +# double check this returns the correct interface! +HOST_IFACE=$(ip -j route list default |jq -r '.[0].dev') # Set up microVM internet access sudo iptables -t nat -D POSTROUTING -o "$HOST_IFACE" -j MASQUERADE || true -sudo iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT \ - || true -sudo iptables -D FORWARD -i "$TAP_DEV" -o "$HOST_IFACE" -j ACCEPT || true sudo iptables -t nat -A POSTROUTING -o "$HOST_IFACE" -j MASQUERADE -sudo iptables -I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -sudo iptables -I FORWARD 1 -i "$TAP_DEV" -o "$HOST_IFACE" -j ACCEPT API_SOCKET="/tmp/firecracker.socket" LOGFILE="./firecracker.log" From 1e3d4e9a08318134f072ccca91006181dd684091 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 14:49:41 +0000 Subject: [PATCH 02/78] build(deps): Bump the firecracker group across 1 directory with 14 updates Bumps the firecracker group with 14 updates in the / directory: | Package | From | To | | --- | --- | --- | | [zerocopy](https://github.com/google/zerocopy) | `0.8.10` | `0.8.11` | | [proc-macro2](https://github.com/dtolnay/proc-macro2) | `1.0.89` | `1.0.92` | | [syn](https://github.com/dtolnay/syn) | `2.0.87` | `2.0.89` | | [libc](https://github.com/rust-lang/libc) | `0.2.164` | `0.2.167` | | [aws-lc-rs](https://github.com/aws/aws-lc-rs) | `1.11.0` | `1.11.1` | | [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) | `0.12.14` | `0.12.15` | | [aws-lc-sys](https://github.com/aws/aws-lc-rs) | `0.23.0` | `0.23.1` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.1` | `1.2.2` | | [cmake](https://github.com/rust-lang/cmake-rs) | `0.1.51` | `0.1.52` | | [cpufeatures](https://github.com/RustCrypto/utils) | `0.2.15` | `0.2.16` | | [errno](https://github.com/lambda-fairy/rust-errno) | `0.3.9` | `0.3.10` | | [hashbrown](https://github.com/rust-lang/hashbrown) | `0.15.1` | `0.15.2` | | [itoa](https://github.com/dtolnay/itoa) | `1.0.11` | `1.0.14` | | [rustix](https://github.com/bytecodealliance/rustix) | `0.38.40` | `0.38.41` | Updates `zerocopy` from 0.8.10 to 0.8.11 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.10...v0.8.11) Updates `proc-macro2` from 1.0.89 to 1.0.92 - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.89...1.0.92) Updates `syn` from 2.0.87 to 2.0.89 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.87...2.0.89) Updates `libc` from 0.2.164 to 0.2.167 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.167/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.164...0.2.167) Updates `aws-lc-rs` from 1.11.0 to 1.11.1 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/v1.11.0...v1.11.1) Updates `aws-lc-fips-sys` from 0.12.14 to 0.12.15 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.12.14...aws-lc-fips-sys/v0.12.15) Updates `aws-lc-sys` from 0.23.0 to 0.23.1 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.23.0...aws-lc-sys/v0.23.1) Updates `cc` from 1.2.1 to 1.2.2 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.1...cc-v1.2.2) Updates `cmake` from 0.1.51 to 0.1.52 - [Release notes](https://github.com/rust-lang/cmake-rs/releases) - [Changelog](https://github.com/rust-lang/cmake-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cmake-rs/compare/v0.1.51...v0.1.52) Updates `cpufeatures` from 0.2.15 to 0.2.16 - [Commits](https://github.com/RustCrypto/utils/compare/cpufeatures-v0.2.15...cpufeatures-v0.2.16) Updates `errno` from 0.3.9 to 0.3.10 - [Release notes](https://github.com/lambda-fairy/rust-errno/releases) - [Changelog](https://github.com/lambda-fairy/rust-errno/blob/main/CHANGELOG.md) - [Commits](https://github.com/lambda-fairy/rust-errno/compare/v0.3.9...v0.3.10) Updates `hashbrown` from 0.15.1 to 0.15.2 - [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/hashbrown/commits) Updates `itoa` from 1.0.11 to 1.0.14 - [Release notes](https://github.com/dtolnay/itoa/releases) - [Commits](https://github.com/dtolnay/itoa/compare/1.0.11...1.0.14) Updates `rustix` from 0.38.40 to 0.38.41 - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.40...v0.38.41) --- updated-dependencies: - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-rs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-fips-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cmake dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cpufeatures dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: errno dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: hashbrown dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: itoa dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: rustix dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 75 +++++++++++++--------------- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 4 +- src/cpu-template-helper/Cargo.toml | 2 +- src/firecracker/Cargo.toml | 4 +- src/jailer/Cargo.toml | 2 +- src/log-instrument-macros/Cargo.toml | 4 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/snapshot-editor/Cargo.toml | 2 +- src/utils/Cargo.toml | 2 +- src/vmm/Cargo.toml | 6 +-- 12 files changed, 50 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3ad7e16b54..c3fed9c404a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "displaydoc", "thiserror 2.0.3", "vm-memory", - "zerocopy 0.8.10", + "zerocopy 0.8.11", ] [[package]] @@ -125,9 +125,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.12.14" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8671005a9c1e80bd3dc9aee84c5bfd594d32a3d645fdb56d5d9d5e26daa4c315" +checksum = "df1e8a8e212a7851ef3d4c28cdfc017072bc684f0e0f57c7943ab60f695c3bfb" dependencies = [ "bindgen 0.69.5", "cc", @@ -140,13 +140,12 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7c2840b66236045acd2607d5866e274380afd87ef99d6226e961e2cb47df45" +checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", - "mirai-annotations", "paste", "untrusted", "zeroize", @@ -154,9 +153,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad3a619a9de81e1d7de1f1186dcba4506ed661a0e483d84410fdef0ee87b2f96" +checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" dependencies = [ "bindgen 0.69.5", "cc", @@ -261,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "jobserver", "libc", @@ -403,9 +402,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" dependencies = [ "cc", ] @@ -433,9 +432,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -586,12 +585,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -707,9 +706,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -794,9 +793,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jailer" @@ -857,9 +856,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libloading" @@ -955,12 +954,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "mirai-annotations" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" - [[package]] name = "nix" version = "0.27.1" @@ -1067,9 +1060,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1187,9 +1180,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -1323,9 +1316,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -1630,7 +1623,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.10", + "zerocopy 0.8.11", ] [[package]] @@ -1807,11 +1800,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13a42ed30c63171d820889b2981318736915150575b8d2d6dbee7edd68336ca" +checksum = "cce3b5629d87654b53a49002acc2ce64aa5aa7255f5c718374a37ac7fd98c218" dependencies = [ - "zerocopy-derive 0.8.10", + "zerocopy-derive 0.8.11", ] [[package]] @@ -1827,9 +1820,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "593e7c96176495043fcb9e87cf7659f4d18679b5bab6b92bdef359c76a7795dd" +checksum = "74a82c26c3986af2623ec9eb890ff4aa19c006e30a1133dc9bd1830ec1612e20" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 15137400180..39b8f1574c9 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" displaydoc = "0.2.5" thiserror = "2.0.3" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.10", features = ["derive"] } +zerocopy = { version = "0.8.11", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 91e03a2afb8..f316fa884dc 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -12,9 +12,9 @@ bench = false [dependencies] clap = { version = "4.5.21", features = ["derive"] } itertools = "0.13.0" -proc-macro2 = { version = "1.0.89", features = ["span-locations"] } +proc-macro2 = { version = "1.0.92", features = ["span-locations"] } quote = "1.0.37" -syn = { version = "2.0.85", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +syn = { version = "2.0.89", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 6654bb090c4..eb7c16472e0 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -12,7 +12,7 @@ bench = false [dependencies] clap = { version = "4.5.21", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 8d0889c23dd..6cd237aaabe 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -18,7 +18,7 @@ bench = false [dependencies] displaydoc = "0.2.5" event-manager = "0.4.0" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } @@ -34,7 +34,7 @@ vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } [dev-dependencies] cargo_toml = "0.20.5" -libc = "0.2.164" +libc = "0.2.167" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index 55b50efb785..ef9162027be 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -12,7 +12,7 @@ name = "jailer" bench = false [dependencies] -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } nix = { version = "0.29.0", default-features = false, features = ["dir"] } regex = { version = "1.11.1", default-features = false, features = ["std"] } diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index fd25f4ffe08..660a7cbb7cd 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -11,9 +11,9 @@ proc-macro = true bench = false [dependencies] -proc-macro2 = "1.0.89" +proc-macro2 = "1.0.92" quote = "1.0.37" -syn = { version = "2.0.85", features = ["full", "extra-traits"] } +syn = { version = "2.0.89", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index c944f5f346d..1615260b03b 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -11,7 +11,7 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } thiserror = "2.0.3" vmm-sys-util = "0.12.1" diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 1916a085b51..90477e3e025 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -18,7 +18,7 @@ bench = false [dependencies] bincode = "1.2.1" displaydoc = "0.2.5" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 022342d896f..91bbebf7f27 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -14,7 +14,7 @@ clap = { version = "4.5.21", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } semver = "1.0.23" thiserror = "2.0.3" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index 2514ee05b0b..7f57e5081a0 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -11,7 +11,7 @@ bench = false [dependencies] derive_more = { version = "1.0.0", default-features = false, features = ["from"] } displaydoc = "0.2.5" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } thiserror = "2.0.3" diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 070cae5088f..283a47a5982 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,7 +12,7 @@ bench = false acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } -aws-lc-rs = { version = "1.11.0", features = ["bindgen"] } +aws-lc-rs = { version = "1.11.1", features = ["bindgen"] } base64 = "0.22.1" bincode = "1.2.1" bitflags = "2.6.0" @@ -25,7 +25,7 @@ gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.19.0" lazy_static = "1.5.0" -libc = "0.2.164" +libc = "0.2.167" linux-loader = "0.13.0" log = { version = "0.4.22", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } @@ -46,7 +46,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.10" } +zerocopy = { version = "0.8.11" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From 7f3715f4310f18507c78381a3636d8260a017db1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 2 Dec 2024 09:34:33 +0000 Subject: [PATCH 03/78] devtool: do not call ensure_ci_artifacts in cmd_sh This already caused a recursive call between ensure_ci_artifacts and cmd_sh (since the former calls the later), which was only benign because ensure_ci_artifacts exits early if the directory exists. With the next patch, it will use cmd_sh before creating the directory, so break this recursion once and for all by instead making the call-sites of cmd_sh that require artifacts to just ensure them themselves. Signed-off-by: Patrick Roy --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 3e0bc857ed5..200dcc43b10 100755 --- a/tools/devtool +++ b/tools/devtool @@ -878,7 +878,6 @@ cmd_shell() { cmd_sh() { ensure_build_dir - ensure_ci_artifacts run_devctr \ --privileged \ --ulimit nofile=4096:4096 \ @@ -916,6 +915,7 @@ cmd_sandbox_native() { } cmd_test_debug() { + ensure_ci_artifacts cmd_sh "tmux new ./tools/test.sh --pdb $@" } From aed4abec4a28128fe7177480b81aebb407d855f1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 2 Dec 2024 07:50:06 +0000 Subject: [PATCH 04/78] devtool: resolve artifact version from Cargo.toml automatically determine the version of the artifacts folder from the Firecracker version in Cargo.toml. Eliminates one of the things we have to manually update during the release. Signed-off-by: Patrick Roy --- tools/devtool | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 200dcc43b10..d3a59f7c5b2 100755 --- a/tools/devtool +++ b/tools/devtool @@ -562,7 +562,8 @@ ensure_ci_artifacts() { # Fetch all the artifacts so they are local say "Fetching CI artifacts from S3" - S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.11/$(uname -m) + FC_VERSION=$(cmd_sh "cd src/firecracker/src; cargo pkgid | cut -d# -f2 | cut -d. -f1-2") + S3_URL=s3://spec.ccfc.min/firecracker-ci/v$FC_VERSION/$(uname -m) ARTIFACTS=$MICROVM_IMAGES_DIR/$(uname -m) if [ ! -d "$ARTIFACTS" ]; then mkdir -pv $ARTIFACTS From 4b9df906d2da5396eb1244576c5f21b983441e53 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 2 Dec 2024 07:57:49 +0000 Subject: [PATCH 05/78] devtool: add `download_ci_artifacts` command Every now and then, I managed to end up with an empty CI artifacts folder, for whatever reason (mostly me being silly). The solution is generally to remove whatever messed up stuff I ended up with in build/img, and run some arbitrary devtool command that I know will redownload everything. Similar workflows must happen whenever we do an in-place update of our CI artifacts. Abstract this away into a command that deletes the build/img folder, and then redownloads it. Signed-off-by: Patrick Roy --- tools/devtool | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/devtool b/tools/devtool index d3a59f7c5b2..4019a7f4b1e 100755 --- a/tools/devtool +++ b/tools/devtool @@ -418,6 +418,10 @@ cmd_help() { echo " Builds the rootfs and guest kernel artifacts we use for our CI." echo " Run './tools/devtool build_ci_artifacts help' for more details about the available commands." echo "" + echo " download_ci_artifacts [--force]" + echo " Downloads the CI artifacts used for testing from our S3 bucket. If --force is passed, purges any existing" + echo " artifacts first. Useful for refreshing local artifacts after an update, or if something got messed up." + echo "" cat <]] @@ -555,6 +559,14 @@ cmd_distclean() { fi } +cmd_download_ci_artifacts() { + if [ "$1" = "--force" ]; then + rm -rf $FC_BUILD_DIR/img + fi + + ensure_ci_artifacts +} + ensure_ci_artifacts() { if ! command -v aws >/dev/null; then die "AWS CLI not installed, which is required for downloading artifacts for integration tests." From f3046829da6c6edf5a669d80d7e4e8c7f962cc58 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 28 Nov 2024 13:56:30 +0000 Subject: [PATCH 06/78] test: use pinned ami for m6i/6.1 This is to keep monitoring functionality and performance on the latest known stable AMI. Signed-off-by: Patrick Roy --- .buildkite/pipeline_perf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.buildkite/pipeline_perf.py b/.buildkite/pipeline_perf.py index e8169bfb2cd..2a26f4277cc 100755 --- a/.buildkite/pipeline_perf.py +++ b/.buildkite/pipeline_perf.py @@ -124,6 +124,8 @@ pins = { # TODO: Unpin when performance instability on m6i/5.10 has gone. "linux_5.10-pinned": {"instance": "m6i.metal", "kv": "linux_5.10"}, + # TODO: Unpin when performance instability on m6i/6.1 has gone. + "linux_6.1-pinned": {"instance": "m6i.metal", "kv": "linux_6.1"}, } From 692c53d663a91abefcbb8f50dc5ffd550504f08d Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 2 Dec 2024 15:31:26 +0000 Subject: [PATCH 07/78] devtool: stop asking for user confirmation on container pull Whenever devtool notices that its container is not cached locally, it requests user input to confirm the new devctr version should indeed be downloaded. In practice, I do not remember ever saying "no" here. On the other hand, forgetting to explicitly disable these confirmations in buildkite pipelines has lead to a myriad of "stuck pipeline" issues. Thus, remove this confirmation step altogether, as it does more harm than good. To avoid having to fix all pipelines that do pass `-y` today, simply treat the `-y` parameter as a no-op (suggested by Pablo, thanks!). We cannot remove get_user_confirmation altogether, as its also used by some of the release scripts, and there it seems like a valid usecase (but these scripts we never run in buildkite). Signed-off-by: Patrick Roy --- tools/devtool | 8 ++------ tools/functions | 5 ----- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/tools/devtool b/tools/devtool index 4019a7f4b1e..36406c61bda 100755 --- a/tools/devtool +++ b/tools/devtool @@ -127,10 +127,6 @@ PRIV_KEY_PATH=/root/.ssh/id_rsa # Path to the linux kernel directory, as bind-mounted in the container. CTR_KERNEL_DIR="${CTR_FC_ROOT_DIR}/.kernel" -# Global options received by $0 -# These options are not command-specific, so we store them as global vars -OPT_UNATTENDED=false - # Get the target prefix to avoid repeated calls to uname -m TARGET_PREFIX="$(uname -m)-unknown-linux-" @@ -195,7 +191,6 @@ ensure_devctr() { # download it, if we don't. [[ $(docker images -q "$DEVCTR_IMAGE" | wc -l) -gt 0 ]] || { say "About to pull docker image $DEVCTR_IMAGE" - get_user_confirmation || die "Aborted." # Run docker pull 5 times in case it fails - sleep 3 seconds # between attempts @@ -1235,7 +1230,8 @@ main() { while [ $# -gt 0 ]; do case "$1" in -h|--help) { cmd_help; exit 1; } ;; - -y|--unattended) { OPT_UNATTENDED=true; } ;; + -y|--unattended) # purposefully ignored + ;; -*) die "Unknown arg: $1. Please use \`$0 help\` for help." ;; diff --git a/tools/functions b/tools/functions index 429a082d7a9..90e75c251bd 100644 --- a/tools/functions +++ b/tools/functions @@ -71,12 +71,7 @@ function SGR { # exit code 0 for successful confirmation # exit code != 0 if the user declined # -OPT_UNATTENDED=false get_user_confirmation() { - - # Pass if running unattended - [[ "$OPT_UNATTENDED" = true ]] && return 0 - # Fail if STDIN is not a terminal (there's no user to confirm anything) [[ -t 0 ]] || return 1 From d27e6978f5188ef973fad80c3d3c02c59317983f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:15:08 +0000 Subject: [PATCH 08/78] build(deps): Bump the firecracker group with 3 updates Bumps the firecracker group with 3 updates: [syn](https://github.com/dtolnay/syn), [indexmap](https://github.com/indexmap-rs/indexmap) and [libloading](https://github.com/nagisa/rust_libloading). Updates `syn` from 2.0.89 to 2.0.90 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.89...2.0.90) Updates `indexmap` from 2.6.0 to 2.7.0 - [Changelog](https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md) - [Commits](https://github.com/indexmap-rs/indexmap/compare/2.6.0...2.7.0) Updates `libloading` from 0.8.5 to 0.8.6 - [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.5...0.8.6) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: indexmap dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: libloading dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ src/clippy-tracing/Cargo.toml | 2 +- src/log-instrument-macros/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3fed9c404a..521552d3f87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -739,9 +739,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -862,9 +862,9 @@ checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets", @@ -1316,9 +1316,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.89" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index f316fa884dc..e22cd6a1eae 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -14,7 +14,7 @@ clap = { version = "4.5.21", features = ["derive"] } itertools = "0.13.0" proc-macro2 = { version = "1.0.92", features = ["span-locations"] } quote = "1.0.37" -syn = { version = "2.0.89", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +syn = { version = "2.0.90", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index 660a7cbb7cd..2129df061f2 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -13,7 +13,7 @@ bench = false [dependencies] proc-macro2 = "1.0.92" quote = "1.0.37" -syn = { version = "2.0.89", features = ["full", "extra-traits"] } +syn = { version = "2.0.90", features = ["full", "extra-traits"] } [lints] workspace = true From 81bae9f8284abc2ab6778746bb60563d224c8025 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Mon, 2 Dec 2024 14:40:01 +0000 Subject: [PATCH 09/78] Add support for M7a in testing utils Add support for detection on m7a instance and prevent the test failure from missing cpu config test Signed-off-by: Jack Thomson --- tests/framework/utils_cpuid.py | 5 ++--- .../functional/test_cpu_features_x86_64.py | 7 ++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/framework/utils_cpuid.py b/tests/framework/utils_cpuid.py index 4303e3ba967..dabfb220240 100644 --- a/tests/framework/utils_cpuid.py +++ b/tests/framework/utils_cpuid.py @@ -25,6 +25,7 @@ class CpuModel(str, Enum): """CPU models""" AMD_MILAN = "AMD_MILAN" + AMD_GENOA = "AMD_GENOA" ARM_NEOVERSE_N1 = "ARM_NEOVERSE_N1" ARM_NEOVERSE_V1 = "ARM_NEOVERSE_V1" INTEL_SKYLAKE = "INTEL_SKYLAKE" @@ -39,9 +40,7 @@ class CpuModel(str, Enum): "Intel(R) Xeon(R) Platinum 8259CL CPU": "INTEL_CASCADELAKE", "Intel(R) Xeon(R) Platinum 8375C CPU": "INTEL_ICELAKE", }, - CpuVendor.AMD: { - "AMD EPYC 7R13": "AMD_MILAN", - }, + CpuVendor.AMD: {"AMD EPYC 7R13": "AMD_MILAN", "AMD EPYC 9R14": "AMD_GENOA"}, CpuVendor.ARM: {"0xd0c": "ARM_NEOVERSE_N1", "0xd40": "ARM_NEOVERSE_V1"}, } diff --git a/tests/integration_tests/functional/test_cpu_features_x86_64.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py index 23818ddc6b1..84d84bd8659 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -486,9 +486,14 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): "hypervisor", "tsc_known_freq", } + case CpuModel.AMD_GENOA: + # Return here to allow the test to pass until CPU features to enable are confirmed + return case _: if os.environ.get("BUILDKITE") is not None: - assert False, f"Cpu model {cpu_model} is not supported" + assert ( + guest_feats == host_feats + ), f"Cpu model {cpu_model} is not supported" # From the `Intel® 64 Architecture x2APIC Specification` From 110e33087168170750639dbbb102f581a0fbadaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sun, 20 Oct 2024 13:36:58 +0200 Subject: [PATCH 10/78] tests: save metadata on snapshot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is some information in the Microvm class that we don't save in the snapshot. Some tests do depend on those, so to make the booted/restored case homogenous, make room in the snapshot to save metadata that we can then restore. Signed-off-by: Pablo Barbáchano --- tests/framework/microvm.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index ed02488bc7b..c1be701665a 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -75,6 +75,7 @@ class Snapshot: disks: dict ssh_key: Path snapshot_type: SnapshotType + meta: dict @property def is_diff(self) -> bool: @@ -110,6 +111,7 @@ def copy_to_chroot(self, chroot) -> "Snapshot": disks=self.disks, ssh_key=self.ssh_key, snapshot_type=self.snapshot_type, + meta=self.meta, ) @classmethod @@ -125,6 +127,7 @@ def load_from(cls, src: Path) -> "Snapshot": disks={dsk: src / p for dsk, p in obj["disks"].items()}, ssh_key=src / obj["ssh_key"], snapshot_type=SnapshotType(obj["snapshot_type"]), + meta=obj["meta"], ) def save_to(self, dst: Path): @@ -917,6 +920,9 @@ def make_snapshot( net_ifaces=[x["iface"] for ifname, x in self.iface.items()], ssh_key=self.ssh_key, snapshot_type=snapshot_type, + meta={ + "kernel_file": self.kernel_file, + }, ) def snapshot_diff(self, *, mem_path: str = "mem", vmstate_path="vmstate"): @@ -954,6 +960,9 @@ def restore_from_snapshot( if uffd_path is not None: mem_backend = {"backend_type": "Uffd", "backend_path": str(uffd_path)} + for key, value in snapshot.meta.items(): + setattr(self, key, value) + self.api.snapshot_load.put( mem_backend=mem_backend, snapshot_path=str(jailed_vmstate), From c2ebbb4d4d10538559d906b2108bb873f3bffb6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sun, 20 Oct 2024 12:55:38 +0200 Subject: [PATCH 11/78] tests: refactor test_vulnerabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some further simplifications: - Simplify the "_host" tests as they will provide the same result in both A/B situations. - Add a second MicrovmFactory fixture with the "A" firecracker. - Add a uvm_any fixture that includes all CPU templates and also a boot/restored dimension. This decreases the need for separate tests. For example the guest test test_check_vulnerability_files_ab can now test all variants: 2 (restored/booted) * 3 (kernels) * 9 (cpu templates) = 54 tests Signed-off-by: Pablo Barbáchano --- tests/README.md | 12 +- tests/conftest.py | 35 ++ tests/framework/ab_test.py | 64 +-- tests/framework/microvm.py | 18 +- tests/framework/properties.py | 5 +- tests/framework/utils_cpu_templates.py | 4 +- .../integration_tests/functional/test_net.py | 43 +- .../security/test_vulnerabilities.py | 499 +++++------------- 8 files changed, 213 insertions(+), 467 deletions(-) diff --git a/tests/README.md b/tests/README.md index ea46ff56786..bf7aba9a547 100644 --- a/tests/README.md +++ b/tests/README.md @@ -306,10 +306,14 @@ that are pre-initialized with specific guest kernels and rootfs: 24.04 squashfs as rootfs, - `uvm_plain` yields a Firecracker process pre-initialized with a 5.10 kernel and the same Ubuntu 24.04 squashfs. - -Generally, tests should use the former if you are testing some interaction -between the guest and Firecracker, while the latter should be used if -Firecracker functionality unrelated to the guest is being tested. +- `uvm_any` yields started microvms, parametrized by all supported kernels, all + CPU templates (static, custom and none), and either booted or restored from a + snapshot. +- `uvm_any_booted` works the same as `uvm_any`, but only for booted VMs. + +Generally, tests should use `uvm_plain_any` if you are testing some interaction +between the guest and Firecracker, and `uvm_plain` should be used if Firecracker +functionality unrelated to the guest is being tested. ### Markers diff --git a/tests/conftest.py b/tests/conftest.py index 8f4c2e51ff5..5ad291d01a4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -459,3 +459,38 @@ def uvm_with_initrd( uvm = microvm_factory.build(guest_kernel_linux_5_10) uvm.initrd_file = fs yield uvm + + +def uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template): + """Return a booted uvm""" + uvm = microvm_factory.build(guest_kernel, rootfs) + uvm.spawn() + uvm.basic_config(vcpu_count=2, mem_size_mib=256) + uvm.set_cpu_template(cpu_template) + uvm.add_net_iface() + uvm.start() + return uvm + + +def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template): + """Return a restored uvm""" + uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template) + snapshot = uvm.snapshot_full() + uvm.kill() + uvm2 = microvm_factory.build() + uvm2.spawn() + uvm2.restore_from_snapshot(snapshot, resume=True) + uvm2.cpu_template_name = uvm.cpu_template_name + return uvm2 + + +@pytest.fixture(params=[uvm_booted, uvm_restored]) +def uvm_ctor(request): + """Fixture to return uvms with different constructors""" + return request.param + + +@pytest.fixture +def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, cpu_template_any): + """Return booted and restored uvms""" + return uvm_ctor(microvm_factory, guest_kernel, rootfs, cpu_template_any) diff --git a/tests/framework/ab_test.py b/tests/framework/ab_test.py index cf909d44fa6..2ef3e2350a7 100644 --- a/tests/framework/ab_test.py +++ b/tests/framework/ab_test.py @@ -21,7 +21,6 @@ of both invocations is the same, the test passes (with us being alerted to this situtation via a special pipeline that does not block PRs). If not, it fails, preventing PRs from introducing new vulnerable dependencies. """ -import os import statistics from pathlib import Path from tempfile import TemporaryDirectory @@ -31,14 +30,14 @@ from framework import utils from framework.defs import FC_WORKSPACE_DIR -from framework.microvm import Microvm +from framework.properties import global_props from framework.utils import CommandReturn from framework.with_filelock import with_filelock -from host_tools.cargo_build import DEFAULT_TARGET_DIR, get_firecracker_binaries +from host_tools.cargo_build import DEFAULT_TARGET_DIR # Locally, this will always compare against main, even if we try to merge into, say, a feature branch. # We might want to do a more sophisticated way to determine a "parent" branch here. -DEFAULT_A_REVISION = os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH") or "main" +DEFAULT_A_REVISION = global_props.buildkite_revision_a or "main" T = TypeVar("T") @@ -120,11 +119,6 @@ def binary_ab_test( return result_a, result_b, comparator(result_a, result_b) -def is_pr() -> bool: - """Returns `True` iff we are executing in the context of a build kite run on a pull request""" - return os.environ.get("BUILDKITE_PULL_REQUEST", "false") != "false" - - def git_ab_test_host_command_if_pr( command: str, *, @@ -134,7 +128,7 @@ def git_ab_test_host_command_if_pr( """Runs the given bash command as an A/B-Test if we're in a pull request context (asserting that its stdout and stderr did not change across the PR). Otherwise runs the command, asserting it returns a zero exit code """ - if is_pr(): + if global_props.buildkite_pr: git_ab_test_host_command(command, comparator=comparator) return None @@ -176,56 +170,6 @@ def set_did_not_grow_comparator( ) -def precompiled_ab_test_guest_command( - microvm_factory: Callable[[Path, Path], Microvm], - command: str, - *, - comparator: Callable[[CommandReturn, CommandReturn], bool] = default_comparator, - a_revision: str = DEFAULT_A_REVISION, - b_revision: Optional[str] = None, -): - """The same as git_ab_test_command, but via SSH. The closure argument should setup a microvm using the passed - paths to firecracker and jailer binaries.""" - b_directory = ( - DEFAULT_B_DIRECTORY - if b_revision is None - else FC_WORKSPACE_DIR / "build" / b_revision - ) - - def test_runner(bin_dir, _is_a: bool): - microvm = microvm_factory(bin_dir / "firecracker", bin_dir / "jailer") - return microvm.ssh.run(command) - - (_, old_out, old_err), (_, new_out, new_err), the_same = binary_ab_test( - test_runner, - comparator, - a_directory=FC_WORKSPACE_DIR / "build" / a_revision, - b_directory=b_directory, - ) - - assert ( - the_same - ), f"The output of running command `{command}` changed:\nOld:\nstdout:\n{old_out}\nstderr\n{old_err}\n\nNew:\nstdout:\n{new_out}\nstderr:\n{new_err}" - - -def precompiled_ab_test_guest_command_if_pr( - microvm_factory: Callable[[Path, Path], Microvm], - command: str, - *, - comparator=default_comparator, - check_in_nonpr=True, -): - """The same as git_ab_test_command_if_pr, but via SSH""" - if is_pr(): - precompiled_ab_test_guest_command( - microvm_factory, command, comparator=comparator - ) - return None - - microvm = microvm_factory(*get_firecracker_binaries()) - return microvm.ssh.run(command, check=check_in_nonpr) - - def check_regression( a_samples: List[float], b_samples: List[float], *, n_resamples: int = 9999 ): diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index c1be701665a..832f56a877e 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -244,6 +244,7 @@ def __init__( self.disks_vhost_user = {} self.vcpus_count = None self.mem_size_bytes = None + self.cpu_template_name = None self._pre_cmd = [] if numa_node: @@ -735,12 +736,14 @@ def basic_config( smt=smt, mem_size_mib=mem_size_mib, track_dirty_pages=track_dirty_pages, - cpu_template=cpu_template, huge_pages=huge_pages, ) self.vcpus_count = vcpu_count self.mem_size_bytes = mem_size_mib * 2**20 + if cpu_template is not None: + self.set_cpu_template(cpu_template) + if self.memory_monitor: self.memory_monitor.start() @@ -773,6 +776,19 @@ def basic_config( if enable_entropy_device: self.enable_entropy_device() + def set_cpu_template(self, cpu_template): + """Set guest CPU template.""" + if cpu_template is None: + return + # static CPU template + if isinstance(cpu_template, str): + self.api.machine_config.patch(cpu_template=cpu_template) + self.cpu_template_name = cpu_template.lower() + # custom CPU template + elif isinstance(cpu_template, dict): + self.api.cpu_config.put(**cpu_template["template"]) + self.cpu_template_name = cpu_template["name"].lower() + def add_drive( self, drive_id, diff --git a/tests/framework/properties.py b/tests/framework/properties.py index b40df56249e..7dd1cb46588 100644 --- a/tests/framework/properties.py +++ b/tests/framework/properties.py @@ -72,11 +72,14 @@ def __init__(self): # major.minor.patch self.host_linux_patch = get_kernel_version(2) self.os = get_os_version() - self.host_os = get_host_os() + self.host_os = get_host_os() or "NA" self.libc_ver = "-".join(platform.libc_ver()) self.rust_version = run_cmd("rustc --version |awk '{print $2}'") + # Buildkite/PR information self.buildkite_pipeline_slug = os.environ.get("BUILDKITE_PIPELINE_SLUG") self.buildkite_build_number = os.environ.get("BUILDKITE_BUILD_NUMBER") + self.buildkite_pr = os.environ.get("BUILDKITE_PULL_REQUEST", "false") != "false" + self.buildkite_revision_a = os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH") if self._in_git_repo(): self.git_commit_id = run_cmd("git rev-parse HEAD") diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py index e57ecfe72c7..89326c1da5a 100644 --- a/tests/framework/utils_cpu_templates.py +++ b/tests/framework/utils_cpu_templates.py @@ -3,6 +3,8 @@ """Utilities for CPU template related functionality.""" +# pylint:disable=too-many-return-statements + import json from pathlib import Path @@ -23,9 +25,7 @@ def get_supported_cpu_templates(): """ Return the list of CPU templates supported by the platform. """ - # pylint:disable=too-many-return-statements host_linux = global_props.host_linux_version_tpl - match get_cpu_vendor(), global_props.cpu_codename: # T2CL template is only supported on Cascade Lake and newer CPUs. case CpuVendor.INTEL, CpuModel.INTEL_SKYLAKE: diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index a804b8f90a8..2072d015ca2 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -84,14 +84,23 @@ def test_multi_queue_unsupported(uvm_plain): ) -def run_udp_offload_test(vm): +@pytest.fixture +def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs): + """Return booted and restored uvm with no CPU templates""" + return uvm_ctor(microvm_factory, guest_kernel, rootfs, None) + + +def test_tap_offload(uvm_any): """ + Verify that tap offload features are configured for a booted/restored VM. + - Start a socat UDP server in the guest. - Try to send a UDP message with UDP offload enabled. If tap offload features are not configured, an attempt to send a message will fail with EIO "Input/output error". More info (search for "TUN_F_CSUM is a must"): https://blog.cloudflare.com/fr-fr/virtual-networking-101-understanding-tap/ """ + vm = uvm_any port = "81" out_filename = "/tmp/out.txt" message = "x" @@ -112,35 +121,3 @@ def run_udp_offload_test(vm): # Check that the server received the message ret = vm.ssh.run(f"cat {out_filename}") assert ret.stdout == message, f"{ret.stdout=} {ret.stderr=}" - - -def test_tap_offload_booted(uvm_plain_any): - """ - Verify that tap offload features are configured for a booted VM. - """ - vm = uvm_plain_any - vm.spawn() - vm.basic_config() - vm.add_net_iface() - vm.start() - - run_udp_offload_test(vm) - - -def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs): - """ - Verify that tap offload features are configured for a restored VM. - """ - src = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) - src.spawn() - src.basic_config() - src.add_net_iface() - src.start() - snapshot = src.snapshot_full() - src.kill() - - dst = microvm_factory.build() - dst.spawn() - dst.restore_from_snapshot(snapshot, resume=True) - - run_udp_offload_test(dst) diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py index fed9dbc96d7..a4461aded78 100644 --- a/tests/integration_tests/security/test_vulnerabilities.py +++ b/tests/integration_tests/security/test_vulnerabilities.py @@ -5,21 +5,17 @@ # script from the third party "Spectre & Meltdown Checker" project. This script is under the # GPL-3.0-only license. """Tests vulnerabilities mitigations.""" + import json -import os +from pathlib import Path import pytest import requests from framework import utils -from framework.ab_test import ( - is_pr, - precompiled_ab_test_guest_command, - precompiled_ab_test_guest_command_if_pr, - set_did_not_grow_comparator, -) +from framework.ab_test import git_clone +from framework.microvm import MicroVMFactory from framework.properties import global_props -from framework.utils import CommandReturn CHECKER_URL = "https://meltdown.ovh" CHECKER_FILENAME = "spectre-meltdown-checker.sh" @@ -29,119 +25,71 @@ VULN_DIR = "/sys/devices/system/cpu/vulnerabilities" -def configure_microvm( - factory, - kernel, - rootfs, - *, - firecracker=None, - jailer=None, - cpu_template=None, - custom_cpu_template=None, -): - """Build a microvm for vulnerability tests""" - assert not (cpu_template and custom_cpu_template) - # Either both or neither are specified - assert firecracker and jailer or not firecracker and not jailer - - if firecracker: - microvm = factory.build( - kernel, rootfs, fc_binary_path=firecracker, jailer_binary_path=jailer - ) - else: - microvm = factory.build(kernel, rootfs) - - microvm.spawn() - microvm.basic_config(vcpu_count=2, mem_size_mib=256, cpu_template=cpu_template) - if custom_cpu_template: - microvm.api.cpu_config.put(**custom_cpu_template["template"]) - microvm.cpu_template = cpu_template - if cpu_template is None and custom_cpu_template is not None: - microvm.cpu_template = custom_cpu_template["name"] - microvm.add_net_iface() - microvm.start() - return microvm +class SpectreMeltdownChecker: + """Helper class to use Spectre & Meltdown Checker""" + def __init__(self, path): + self.path = path -@pytest.fixture -def build_microvm( - microvm_factory, - guest_kernel_linux_5_10, - rootfs, -): - """Fixture returning a factory function for a normal microvm""" - return lambda firecracker=None, jailer=None: configure_microvm( - microvm_factory, - guest_kernel_linux_5_10, - rootfs, - firecracker=firecracker, - jailer=jailer, - ) - - -@pytest.fixture -def build_microvm_with_template( - microvm_factory, guest_kernel_linux_5_10, rootfs, cpu_template -): - """Fixture returning a factory function for microvms with our built-in template""" - return lambda firecracker=None, jailer=None: configure_microvm( - microvm_factory, - guest_kernel_linux_5_10, - rootfs, - firecracker=firecracker, - jailer=jailer, - cpu_template=cpu_template, - ) - - -@pytest.fixture -def build_microvm_with_custom_template( - microvm_factory, guest_kernel_linux_5_10, rootfs, custom_cpu_template -): - """Fixture returning a factory function for microvms with custom cpu templates""" - return lambda firecracker=None, jailer=None: configure_microvm( - microvm_factory, - guest_kernel_linux_5_10, - rootfs, - firecracker=firecracker, - jailer=jailer, - custom_cpu_template=custom_cpu_template, - ) - - -def with_restore(factory, microvm_factory): - """Turns the given microvm factory into one that makes the microvm go through a snapshot-restore cycle""" - - def restore(firecracker=None, jailer=None): - microvm = factory(firecracker, jailer) - - snapshot = microvm.snapshot_full() - - if firecracker: - dst_vm = microvm_factory.build( - fc_binary_path=firecracker, jailer_binary_path=jailer - ) - else: - dst_vm = microvm_factory.build() - dst_vm.spawn() - # Restore the destination VM from the snapshot - dst_vm.restore_from_snapshot(snapshot, resume=True) - dst_vm.cpu_template = microvm.cpu_template - - return dst_vm - - return restore - - -def with_checker(factory, spectre_meltdown_checker): - """Turns the given microvm factory function into one that also contains the spectre-meltdown checker script""" + def _parse_output(self, output): + return { + json.dumps(entry) # dict is unhashable + for entry in json.loads(output) + if entry["VULNERABLE"] + } - def download_checker(firecracker, jailer): - microvm = factory(firecracker, jailer) - microvm.ssh.scp_put(spectre_meltdown_checker, REMOTE_CHECKER_PATH) - return microvm + def get_report_for_guest(self, vm) -> set: + """Parses the output of `spectre-meltdown-checker.sh --batch json` + and returns the set of issues for which it reported 'Vulnerable'. - return download_checker + Sample stdout: + ``` + [ + { + "NAME": "SPECTRE VARIANT 1", + "CVE": "CVE-2017-5753", + "VULNERABLE": false, + "INFOS": "Mitigation: usercopy/swapgs barriers and __user pointer sanitization" + }, + { ... } + ] + ``` + """ + vm.ssh.scp_put(self.path, REMOTE_CHECKER_PATH) + res = vm.ssh.run(REMOTE_CHECKER_COMMAND) + return self._parse_output(res.stdout) + + def get_report_for_host(self) -> set: + """Runs `spectre-meltdown-checker.sh` in the host and returns the set of + issues for which it reported 'Vulnerable'. + """ + + res = utils.check_output(f"sh {self.path} --batch json") + return self._parse_output(res.stdout) + + def expected_vulnerabilities(self, cpu_template_name): + """ + There is a REPTAR exception reported on INTEL_ICELAKE when spectre-meltdown-checker.sh + script is run inside the guest from below the tests: + test_spectre_meltdown_checker_on_guest and + test_spectre_meltdown_checker_on_restored_guest + The same script when run on host doesn't report the + exception which means the instances are actually not vulnerable to REPTAR. + The only reason why the script cannot determine if the guest + is vulnerable or not because Firecracker does not expose the microcode + version to the guest. + + The check in spectre_meltdown_checker is here: + https://github.com/speed47/spectre-meltdown-checker/blob/0f2edb1a71733c1074550166c5e53abcfaa4d6ca/spectre-meltdown-checker.sh#L6635-L6637 + + Since we have a test on host and the exception in guest is not valid, + we add a check to ignore this exception. + """ + if global_props.cpu_codename == "INTEL_ICELAKE" and cpu_template_name is None: + return { + '{"NAME": "REPTAR", "CVE": "CVE-2023-23583", "VULNERABLE": true, "INFOS": "Your microcode is too old to mitigate the vulnerability"}' + } + return set() @pytest.fixture(scope="session", name="spectre_meltdown_checker") @@ -149,189 +97,32 @@ def download_spectre_meltdown_checker(tmp_path_factory): """Download spectre / meltdown checker script.""" resp = requests.get(CHECKER_URL, timeout=5) resp.raise_for_status() - path = tmp_path_factory.mktemp("tmp", True) / CHECKER_FILENAME path.write_bytes(resp.content) - - return path - - -def spectre_meltdown_reported_vulnerablities( - spectre_meltdown_checker_output: CommandReturn, -) -> set: - """ - Parses the output of `spectre-meltdown-checker.sh --batch json` and returns the set of issues - for which it reported 'Vulnerable'. - - Sample stdout: - ``` - [ - { - "NAME": "SPECTRE VARIANT 1", - "CVE": "CVE-2017-5753", - "VULNERABLE": false, - "INFOS": "Mitigation: usercopy/swapgs barriers and __user pointer sanitization" - }, - { - ... - } - ] - ``` - """ - return { - json.dumps(entry) # dict is unhashable - for entry in json.loads(spectre_meltdown_checker_output.stdout) - if entry["VULNERABLE"] - } - - -def check_vulnerabilities_on_guest(status): - """ - There is a REPTAR exception reported on INTEL_ICELAKE when spectre-meltdown-checker.sh - script is run inside the guest from below the tests: - test_spectre_meltdown_checker_on_guest and - test_spectre_meltdown_checker_on_restored_guest - The same script when run on host doesn't report the - exception which means the instances are actually not vulnerable to REPTAR. - The only reason why the script cannot determine if the guest - is vulnerable or not because Firecracker does not expose the microcode - version to the guest. - - The check in spectre_meltdown_checker is here: - https://github.com/speed47/spectre-meltdown-checker/blob/0f2edb1a71733c1074550166c5e53abcfaa4d6ca/spectre-meltdown-checker.sh#L6635-L6637 - - Since we have a test on host and the exception in guest is not valid, - we add a check to ignore this exception. - """ - report_guest_vulnerabilities = spectre_meltdown_reported_vulnerablities(status) - known_guest_vulnerabilities = set() - if global_props.cpu_codename == "INTEL_ICELAKE": - known_guest_vulnerabilities = { - '{"NAME": "REPTAR", "CVE": "CVE-2023-23583", "VULNERABLE": true, "INFOS": "Your microcode is too old to mitigate the vulnerability"}' - } - assert report_guest_vulnerabilities == known_guest_vulnerabilities + return SpectreMeltdownChecker(path) # Nothing can be sensibly tested in a PR context here @pytest.mark.skipif( - is_pr(), reason="Test depends solely on factors external to GitHub repository" + global_props.buildkite_pr, + reason="Test depends solely on factors external to GitHub repository", ) def test_spectre_meltdown_checker_on_host(spectre_meltdown_checker): - """ - Test with the spectre / meltdown checker on host. - """ - rc, output, _ = utils.run_cmd(f"sh {spectre_meltdown_checker} --batch json") - - if output and rc != 0: - report = spectre_meltdown_reported_vulnerablities(output) - expected = {} - assert report == expected, f"Unexpected vulnerabilities: {report} vs {expected}" - - -def test_spectre_meltdown_checker_on_guest(spectre_meltdown_checker, build_microvm): - """ - Test with the spectre / meltdown checker on guest. - """ - - status = precompiled_ab_test_guest_command_if_pr( - with_checker(build_microvm, spectre_meltdown_checker), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - check_in_nonpr=False, - ) - if status and status.returncode != 0: - check_vulnerabilities_on_guest(status) - - -def test_spectre_meltdown_checker_on_restored_guest( - spectre_meltdown_checker, build_microvm, microvm_factory -): - """ - Test with the spectre / meltdown checker on a restored guest. - """ - status = precompiled_ab_test_guest_command_if_pr( - with_checker( - with_restore(build_microvm, microvm_factory), spectre_meltdown_checker - ), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - check_in_nonpr=False, - ) - if status and status.returncode != 0: - check_vulnerabilities_on_guest(status) - - -def test_spectre_meltdown_checker_on_guest_with_template( - spectre_meltdown_checker, build_microvm_with_template -): - """ - Test with the spectre / meltdown checker on guest with CPU template. - """ + """Test with the spectre / meltdown checker on host.""" + report = spectre_meltdown_checker.get_report_for_host() + assert report == set(), f"Unexpected vulnerabilities: {report}" - precompiled_ab_test_guest_command_if_pr( - with_checker(build_microvm_with_template, spectre_meltdown_checker), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - ) - -def test_spectre_meltdown_checker_on_guest_with_custom_template( - spectre_meltdown_checker, build_microvm_with_custom_template -): - """ - Test with the spectre / meltdown checker on guest with a custom CPU template. - """ - precompiled_ab_test_guest_command_if_pr( - with_checker(build_microvm_with_custom_template, spectre_meltdown_checker), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - ) - - -def test_spectre_meltdown_checker_on_restored_guest_with_template( - spectre_meltdown_checker, build_microvm_with_template, microvm_factory -): - """ - Test with the spectre / meltdown checker on a restored guest with a CPU template. - """ - precompiled_ab_test_guest_command_if_pr( - with_checker( - with_restore(build_microvm_with_template, microvm_factory), - spectre_meltdown_checker, - ), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - ) - - -def test_spectre_meltdown_checker_on_restored_guest_with_custom_template( - spectre_meltdown_checker, - build_microvm_with_custom_template, - microvm_factory, -): - """ - Test with the spectre / meltdown checker on a restored guest with a custom CPU template. - """ - precompiled_ab_test_guest_command_if_pr( - with_checker( - with_restore(build_microvm_with_custom_template, microvm_factory), - spectre_meltdown_checker, - ), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - ) +# Nothing can be sensibly tested here in a PR context +@pytest.mark.skipif( + global_props.buildkite_pr, + reason="Test depends solely on factors external to GitHub repository", +) +def test_vulnerabilities_on_host(): + """Test vulnerability files on host.""" + res = utils.run_cmd(f"grep -r Vulnerable {VULN_DIR}") + # if grep finds no matching lines, it exits with status 1 + assert res.returncode == 1, res.stdout def get_vuln_files_exception_dict(template): @@ -372,25 +163,14 @@ def get_vuln_files_exception_dict(template): # Since those bits are not set on Intel Skylake and C3 template makes guests pretend to be AWS # C3 instance (quite old processor now) by overwriting CPUID.1H:EAX, it is impossible to avoid # this "Unknown" state. - if global_props.cpu_codename == "INTEL_SKYLAKE" and template == "C3": + if global_props.cpu_codename == "INTEL_SKYLAKE" and template == "c3": exception_dict["mmio_stale_data"] = "Unknown: No mitigations" - elif global_props.cpu_codename == "INTEL_SKYLAKE" or template == "T2S": + elif global_props.cpu_codename == "INTEL_SKYLAKE" or template == "t2s": exception_dict["mmio_stale_data"] = "Clear CPU buffers" return exception_dict -# Nothing can be sensibly tested here in a PR context -@pytest.mark.skipif( - is_pr(), reason="Test depends solely on factors external to GitHub repository" -) -def test_vulnerabilities_on_host(): - """ - Test vulnerabilities files on host. - """ - utils.check_output(f"! grep -r Vulnerable {VULN_DIR}") - - def check_vulnerabilities_files_on_guest(microvm): """ Check that the guest's vulnerabilities files do not contain `Vulnerable`. @@ -400,88 +180,75 @@ def check_vulnerabilities_files_on_guest(microvm): # Retrieve a list of vulnerabilities files available inside guests. vuln_dir = "/sys/devices/system/cpu/vulnerabilities" _, stdout, _ = microvm.ssh.check_output(f"find -D all {vuln_dir} -type f") - vuln_files = stdout.split("\n") + vuln_files = stdout.splitlines() # Fixtures in this file (test_vulnerabilities.py) add this special field. - template = microvm.cpu_template + template = microvm.cpu_template_name # Check that vulnerabilities files in the exception dictionary have the expected values and # the others do not contain "Vulnerable". exceptions = get_vuln_files_exception_dict(template) + results = [] for vuln_file in vuln_files: - filename = os.path.basename(vuln_file) + filename = Path(vuln_file).name if filename in exceptions: - _, stdout, _ = microvm.ssh.run(f"cat {vuln_file}") + _, stdout, _ = microvm.ssh.check_output(f"cat {vuln_file}") assert exceptions[filename] in stdout else: cmd = f"grep Vulnerable {vuln_file}" - ecode, stdout, stderr = microvm.ssh.run(cmd) - assert ecode == 1, f"{vuln_file}: stdout:\n{stdout}\nstderr:\n{stderr}\n" - - -def check_vulnerabilities_files_ab(builder): - """Does an A/B test on the contents of the /sys/devices/system/cpu/vulnerabilities files in the guest if - running in a PR pipeline, and otherwise calls `check_vulnerabilities_files_on_guest` - """ - if is_pr(): - precompiled_ab_test_guest_command( - builder, - f"! grep -r Vulnerable {VULN_DIR}", - comparator=set_did_not_grow_comparator( - lambda output: set(output.stdout.splitlines()) - ), - ) - else: - check_vulnerabilities_files_on_guest(builder()) + _ecode, stdout, _stderr = microvm.ssh.run(cmd) + results.append({"file": vuln_file, "stdout": stdout}) + return results -def test_vulnerabilities_files_on_guest(build_microvm): - """ - Test vulnerabilities files on guest. - """ - check_vulnerabilities_files_ab(build_microvm) - - -def test_vulnerabilities_files_on_restored_guest(build_microvm, microvm_factory): - """ - Test vulnerabilities files on a restored guest. - """ - check_vulnerabilities_files_ab(with_restore(build_microvm, microvm_factory)) +@pytest.fixture +def microvm_factory_a(record_property): + """MicroVMFactory using revision A binaries""" + revision_a = global_props.buildkite_revision_a + bin_dir = git_clone(Path("../build") / revision_a, revision_a).resolve() + fc_bin = bin_dir / "firecracker" + jailer_bin = bin_dir / "jailer" + record_property("firecracker_bin", str(fc_bin)) + uvm_factory = MicroVMFactory(fc_bin, jailer_bin) + yield uvm_factory + uvm_factory.kill() -def test_vulnerabilities_files_on_guest_with_template(build_microvm_with_template): - """ - Test vulnerabilities files on guest with CPU template. - """ - check_vulnerabilities_files_ab(build_microvm_with_template) - +@pytest.fixture +def uvm_any_a(microvm_factory_a, uvm_ctor, guest_kernel, rootfs, cpu_template_any): + """Return uvm with revision A firecracker -def test_vulnerabilities_files_on_guest_with_custom_template( - build_microvm_with_custom_template, -): + Since pytest caches fixtures, this guarantees uvm_any_a will match a vm from uvm_any. + See https://docs.pytest.org/en/stable/how-to/fixtures.html#fixtures-can-be-requested-more-than-once-per-test-return-values-are-cached """ - Test vulnerabilities files on guest with a custom CPU template. - """ - check_vulnerabilities_files_ab(build_microvm_with_custom_template) + return uvm_ctor(microvm_factory_a, guest_kernel, rootfs, cpu_template_any) -def test_vulnerabilities_files_on_restored_guest_with_template( - build_microvm_with_template, microvm_factory -): - """ - Test vulnerabilities files on a restored guest with a CPU template. - """ - check_vulnerabilities_files_ab( - with_restore(build_microvm_with_template, microvm_factory) - ) +def test_check_vulnerability_files_ab(request, uvm_any): + """Test vulnerability files on guests""" + res_b = check_vulnerabilities_files_on_guest(uvm_any) + if global_props.buildkite_pr: + # we only get the uvm_any_a fixtures if we need it + uvm_a = request.getfixturevalue("uvm_any_a") + res_a = check_vulnerabilities_files_on_guest(uvm_a) + assert res_b <= res_a + else: + assert not [x for x in res_b if "Vulnerable" in x["stdout"]] -def test_vulnerabilities_files_on_restored_guest_with_custom_template( - build_microvm_with_custom_template, microvm_factory +def test_spectre_meltdown_checker_on_guest( + request, + uvm_any, + spectre_meltdown_checker, ): - """ - Test vulnerabilities files on a restored guest with a custom CPU template. - """ - check_vulnerabilities_files_ab( - with_restore(build_microvm_with_custom_template, microvm_factory) - ) + """Test with the spectre / meltdown checker on any supported guest.""" + res_b = spectre_meltdown_checker.get_report_for_guest(uvm_any) + if global_props.buildkite_pr: + # we only get the uvm_any_a fixtures if we need it + uvm_a = request.getfixturevalue("uvm_any_a") + res_a = spectre_meltdown_checker.get_report_for_guest(uvm_a) + assert res_b <= res_a + else: + assert res_b == spectre_meltdown_checker.expected_vulnerabilities( + uvm_any.cpu_template_name + ) From 1882a3da67ecb06ebf19fe9b4a9b3701edd6d323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 31 Oct 2024 22:49:26 +0100 Subject: [PATCH 12/78] tests: refactor test_nv.py to use uvm_any_booted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a new uvm_any_booted fixture to make the test simpler. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 6 +++++ tests/integration_tests/security/test_nv.py | 30 +++------------------ 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 5ad291d01a4..a2990a56c98 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -494,3 +494,9 @@ def uvm_ctor(request): def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, cpu_template_any): """Return booted and restored uvms""" return uvm_ctor(microvm_factory, guest_kernel, rootfs, cpu_template_any) + + +@pytest.fixture +def uvm_any_booted(microvm_factory, guest_kernel, rootfs, cpu_template_any): + """Return booted uvms""" + return uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template_any) diff --git a/tests/integration_tests/security/test_nv.py b/tests/integration_tests/security/test_nv.py index 5dd5acb2308..73f042d5ae3 100644 --- a/tests/integration_tests/security/test_nv.py +++ b/tests/integration_tests/security/test_nv.py @@ -16,31 +16,7 @@ start providing the feature by mistake. """ -import pytest - -@pytest.fixture -def uvm_with_cpu_template(microvm_factory, guest_kernel, rootfs, cpu_template_any): - """A microvm fixture parametrized with all possible templates""" - vm = microvm_factory.build(guest_kernel, rootfs) - vm.spawn() - cpu_template = None - if isinstance(cpu_template_any, str): - cpu_template = cpu_template_any - vm.basic_config(cpu_template=cpu_template) - if isinstance(cpu_template_any, dict): - vm.api.cpu_config.put(**cpu_template_any["template"]) - vm.add_net_iface() - vm.start() - yield vm - - -def test_no_nv_when_using_cpu_templates(uvm_with_cpu_template): - """ - Double-check that guests using CPU templates don't have Nested Virtualization - enabled. - """ - - vm = uvm_with_cpu_template - rc, _, _ = vm.ssh.run("[ ! -e /dev/kvm ]") - assert rc == 0, "/dev/kvm exists" +def test_no_nested_virtualization(uvm_any_booted): + """Validate that guests don't have Nested Virtualization enabled.""" + uvm_any_booted.ssh.check_output("[ ! -e /dev/kvm ]") From 033402e7147118539d7379ba11d1881ec42911bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 29 Oct 2024 16:06:17 +0100 Subject: [PATCH 13/78] tests: refactor test_cpu_features_aarch64 to use uvm_any MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new uvm_any fixture to make the tests simpler Signed-off-by: Pablo Barbáchano --- tests/framework/utils_cpu_templates.py | 10 +- .../functional/test_cpu_features_aarch64.py | 157 ++++-------------- 2 files changed, 34 insertions(+), 133 deletions(-) diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py index 89326c1da5a..56021a21aaa 100644 --- a/tests/framework/utils_cpu_templates.py +++ b/tests/framework/utils_cpu_templates.py @@ -22,9 +22,7 @@ def get_supported_cpu_templates(): - """ - Return the list of CPU templates supported by the platform. - """ + """Return the list of static CPU templates supported by the platform.""" host_linux = global_props.host_linux_version_tpl match get_cpu_vendor(), global_props.cpu_codename: # T2CL template is only supported on Cascade Lake and newer CPUs. @@ -44,12 +42,8 @@ def get_supported_cpu_templates(): def get_supported_custom_cpu_templates(): - """ - Return the list of custom CPU templates supported by the platform. - """ - # pylint:disable=too-many-return-statements + """Return the list of custom CPU templates supported by the platform.""" host_linux = global_props.host_linux_version_tpl - match get_cpu_vendor(), global_props.cpu_codename: # T2CL template is only supported on Cascade Lake and newer CPUs. case CpuVendor.INTEL, CpuModel.INTEL_SKYLAKE: diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index 8357f54b568..1edcb39f151 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -3,83 +3,63 @@ """Tests for the CPU features for aarch64.""" import os -import platform -import re import pytest -import framework.utils_cpuid as cpuid_utils from framework import utils from framework.properties import global_props from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel -PLATFORM = platform.machine() +pytestmark = pytest.mark.skipif( + global_props.cpu_architecture != "aarch64", reason="Only run in aarch64" +) -DEFAULT_G2_FEATURES = set( +G2_FEATS = set( ( "fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp " "asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs" - ).split(" ") + ).split() ) -DEFAULT_G3_FEATURES_5_10 = DEFAULT_G2_FEATURES | set( - "sha512 asimdfhm dit uscat ilrcpc flagm jscvt fcma sha3 sm3 sm4 rng dcpodp i8mm bf16 dgh".split( - " " - ) +G3_FEATS = G2_FEATS | set( + "sha512 asimdfhm dit uscat ilrcpc flagm jscvt fcma sha3 sm3 sm4 rng dcpodp i8mm bf16 dgh".split() ) -DEFAULT_G3_FEATURES_WITH_SVE_AND_PAC_5_10 = DEFAULT_G3_FEATURES_5_10 | set( - "paca pacg sve svebf16 svei8mm".split(" ") -) +G3_SVE_AND_PAC = set("paca pacg sve svebf16 svei8mm".split()) -DEFAULT_G3_FEATURES_V1N1 = DEFAULT_G2_FEATURES +def test_guest_cpu_features(uvm_any): + """Check the CPU features for a microvm with different CPU templates""" -def _check_cpu_features_arm(test_microvm, guest_kv, template_name=None): - expected_cpu_features = {"Flags": []} - match cpuid_utils.get_cpu_model_name(), guest_kv, template_name: - case CpuModel.ARM_NEOVERSE_N1, _, "v1n1": - expected_cpu_features = DEFAULT_G2_FEATURES - case CpuModel.ARM_NEOVERSE_N1, _, None: - expected_cpu_features = DEFAULT_G2_FEATURES + vm = uvm_any + expected_cpu_features = set() + match global_props.cpu_model, vm.cpu_template_name: + case CpuModel.ARM_NEOVERSE_N1, "v1n1": + expected_cpu_features = G2_FEATS + case CpuModel.ARM_NEOVERSE_N1, None: + expected_cpu_features = G2_FEATS # [cm]7g with guest kernel 5.10 and later - case CpuModel.ARM_NEOVERSE_V1, _, "v1n1": - expected_cpu_features = DEFAULT_G3_FEATURES_V1N1 - case CpuModel.ARM_NEOVERSE_V1, _, "aarch64_with_sve_and_pac": - expected_cpu_features = DEFAULT_G3_FEATURES_WITH_SVE_AND_PAC_5_10 - case CpuModel.ARM_NEOVERSE_V1, _, None: - expected_cpu_features = DEFAULT_G3_FEATURES_5_10 - - _, stdout, _ = test_microvm.ssh.check_output(CPU_FEATURES_CMD) - flags = set(stdout.strip().split(" ")) - assert flags == expected_cpu_features + case CpuModel.ARM_NEOVERSE_V1, "v1n1": + expected_cpu_features = G2_FEATS + case CpuModel.ARM_NEOVERSE_V1, "aarch64_with_sve_and_pac": + expected_cpu_features = G3_FEATS | G3_SVE_AND_PAC + case CpuModel.ARM_NEOVERSE_V1, None: + expected_cpu_features = G3_FEATS + guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) + assert guest_feats == expected_cpu_features -def get_cpu_template_dir(cpu_template): - """ - Utility function to return a valid string which will be used as - name of the directory where snapshot artifacts are stored during - snapshot test and loaded from during restore test. - """ - return cpu_template if cpu_template else "none" - - -@pytest.mark.skipif( - PLATFORM != "aarch64", - reason="This is aarch64 specific test.", -) -def test_host_vs_guest_cpu_features_aarch64(uvm_nano): +def test_host_vs_guest_cpu_features(uvm_nano): """Check CPU features host vs guest""" vm = uvm_nano vm.add_net_iface() vm.start() - host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.strip().split(" ")) - guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.strip().split(" ")) - - cpu_model = cpuid_utils.get_cpu_model_name() + host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.split()) + guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) + cpu_model = global_props.cpu_model match cpu_model: case CpuModel.ARM_NEOVERSE_N1: expected_guest_minus_host = set() @@ -141,79 +121,6 @@ def test_host_vs_guest_cpu_features_aarch64(uvm_nano): assert guest_feats - host_feats == expected_guest_minus_host case _: if os.environ.get("BUILDKITE") is not None: - assert False, f"Cpu model {cpu_model} is not supported" - - -@pytest.mark.skipif( - PLATFORM != "aarch64", - reason="This is aarch64 specific test.", -) -def test_default_cpu_features(microvm_factory, guest_kernel, rootfs): - """ - Check the CPU features for a microvm with the specified config. - """ - - vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) - vm.spawn() - vm.basic_config() - vm.add_net_iface() - vm.start() - guest_kv = re.search(r"vmlinux-(\d+\.\d+)", guest_kernel.name).group(1) - _check_cpu_features_arm(vm, guest_kv) - - -@pytest.mark.skipif( - PLATFORM != "aarch64", - reason="This is aarch64 specific test.", -) -def test_cpu_features_with_static_template( - microvm_factory, guest_kernel, rootfs, cpu_template -): - """ - Check the CPU features for a microvm with the specified config. - """ - - vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) - vm.spawn() - vm.basic_config(cpu_template=cpu_template) - vm.add_net_iface() - vm.start() - guest_kv = re.search(r"vmlinux-(\d+\.\d+)", guest_kernel.name).group(1) - _check_cpu_features_arm(vm, guest_kv, "v1n1") - - # Check that cpu features are still correct - # after snap/restore cycle. - snapshot = vm.snapshot_full() - restored_vm = microvm_factory.build() - restored_vm.spawn() - restored_vm.restore_from_snapshot(snapshot, resume=True) - _check_cpu_features_arm(restored_vm, guest_kv, "v1n1") - - -@pytest.mark.skipif( - PLATFORM != "aarch64", - reason="This is aarch64 specific test.", -) -def test_cpu_features_with_custom_template( - microvm_factory, guest_kernel, rootfs, custom_cpu_template -): - """ - Check the CPU features for a microvm with the specified config. - """ - - vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) - vm.spawn() - vm.basic_config() - vm.api.cpu_config.put(**custom_cpu_template["template"]) - vm.add_net_iface() - vm.start() - guest_kv = re.search(r"vmlinux-(\d+\.\d+)", guest_kernel.name).group(1) - _check_cpu_features_arm(vm, guest_kv, custom_cpu_template["name"]) - - # Check that cpu features are still correct - # after snap/restore cycle. - snapshot = vm.snapshot_full() - restored_vm = microvm_factory.build() - restored_vm.spawn() - restored_vm.restore_from_snapshot(snapshot, resume=True) - _check_cpu_features_arm(restored_vm, guest_kv, custom_cpu_template["name"]) + assert ( + False + ), f"Cpu model {cpu_model} is not supported, please onboard it." From da969fb7615a74cc1447d24decc74988a3a9b307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 18 Nov 2024 22:31:29 +0100 Subject: [PATCH 14/78] tests: skip x86_64 tests at module level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All tests in the file are x86_64 specific, so do the skip at the top-level, once. Signed-off-by: Pablo Barbáchano --- .../functional/test_cpu_features_x86_64.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/tests/integration_tests/functional/test_cpu_features_x86_64.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py index 84d84bd8659..bb86df2eade 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -30,6 +30,10 @@ ) DATA_FILES = Path("./data/msr") +pytestmark = pytest.mark.skipif( + global_props.cpu_architecture != "x86_64", reason="Only run in x86_64" +) + def read_msr_csv(fd): """Read a CSV of MSRs""" @@ -105,7 +109,6 @@ def skip_test_based_on_artifacts(snapshot_artifacts_dir): pytest.skip(re.sub(" +", " ", reason)) -@pytest.mark.skipif(PLATFORM != "x86_64", reason="CPUID is only supported on x86_64.") @pytest.mark.parametrize( "num_vcpus", [1, 2, 16], @@ -126,7 +129,6 @@ def test_cpuid(uvm_plain_any, num_vcpus, htt): _check_cpuid_x86(vm, num_vcpus, "true" if num_vcpus > 1 else "false") -@pytest.mark.skipif(PLATFORM != "x86_64", reason="CPUID is only supported on x86_64.") @pytest.mark.skipif( cpuid_utils.get_cpu_vendor() != cpuid_utils.CpuVendor.AMD, reason="L3 cache info is only present in 0x80000006 for AMD", @@ -143,9 +145,6 @@ def test_extended_cache_features(uvm_plain_any): _check_extended_cache_features(vm) -@pytest.mark.skipif( - PLATFORM != "x86_64", reason="The CPU brand string is masked only on x86_64." -) def test_brand_string(uvm_plain_any): """ Ensure good formatting for the guest brand string. @@ -204,10 +203,6 @@ def test_brand_string(uvm_plain_any): assert False -@pytest.mark.skipif( - PLATFORM != "x86_64", - reason="This is x86_64 specific test.", -) def test_host_vs_guest_cpu_features_x86_64(uvm_nano): """Check CPU features host vs guest""" @@ -929,9 +924,6 @@ def test_cpu_cpuid_restore(microvm_factory, guest_kernel, msr_cpu_template): ) -@pytest.mark.skipif( - PLATFORM != "x86_64", reason="CPU features are masked only on x86_64." -) @pytest.mark.parametrize("cpu_template", ["T2", "T2S", "C3"]) def test_cpu_template(uvm_plain_any, cpu_template, microvm_factory): """ @@ -1249,7 +1241,6 @@ def check_enabled_features(test_microvm, cpu_template): ) -@pytest.mark.skipif(PLATFORM != "x86_64", reason="This test is specific to x86_64.") def test_c3_on_skylake_show_warning(uvm_plain, cpu_template): """ This test verifies that the warning message about MMIO stale data mitigation From 409877aed9e7d29962ff399e13b55bc463d7a9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 18 Nov 2024 22:32:55 +0100 Subject: [PATCH 15/78] tests: refactor test_cpu_features_x86_64.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the common feature flags to get some clarity on what are the differences between the CPUs. Signed-off-by: Pablo Barbáchano --- .../functional/test_cpu_features_x86_64.py | 203 +++++------------- 1 file changed, 56 insertions(+), 147 deletions(-) diff --git a/tests/integration_tests/functional/test_cpu_features_x86_64.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py index bb86df2eade..f8bbe1ef52e 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -203,6 +203,57 @@ def test_brand_string(uvm_plain_any): assert False +INTEL_HOST_ONLY_FEATS = { + "acpi", + "aperfmperf", + "arch_perfmon", + "art", + "bts", + "cat_l3", + "cdp_l3", + "cqm", + "cqm_llc", + "cqm_mbm_local", + "cqm_mbm_total", + "cqm_occup_llc", + "dca", + "ds_cpl", + "dtes64", + "dtherm", + "dts", + "epb", + "ept", + "ept_ad", + "est", + "flexpriority", + "flush_l1d", + "hwp", + "hwp_act_window", + "hwp_epp", + "hwp_pkg_req", + "ida", + "intel_ppin", + "intel_pt", + "mba", + "monitor", + "pbe", + "pdcm", + "pebs", + "pln", + "pts", + "rdt_a", + "sdbg", + "smx", + "tm", + "tm2", + "tpr_shadow", + "vmx", + "vnmi", + "vpid", + "xtpr", +} + + def test_host_vs_guest_cpu_features_x86_64(uvm_nano): """Check CPU features host vs guest""" @@ -283,110 +334,14 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): "tsc_known_freq", } case CpuModel.INTEL_SKYLAKE: - assert host_feats - guest_feats == { - "acpi", - "aperfmperf", - "arch_perfmon", - "art", - "bts", - "cat_l3", - "cdp_l3", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "dca", - "ds_cpl", - "dtes64", - "dtherm", - "dts", - "epb", - "ept", - "ept_ad", - "est", - "flexpriority", - "flush_l1d", - "hwp", - "hwp_act_window", - "hwp_epp", - "hwp_pkg_req", - "ida", - "intel_ppin", - "intel_pt", - "mba", - "monitor", - "pbe", - "pdcm", - "pebs", - "pln", - "pts", - "rdt_a", - "sdbg", - "smx", - "tm", - "tm2", - "tpr_shadow", - "vmx", - "vnmi", - "vpid", - "xtpr", - } + assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS assert guest_feats - host_feats == { "hypervisor", "tsc_known_freq", "umip", } case CpuModel.INTEL_CASCADELAKE: - expected_host_minus_guest = { - "acpi", - "aperfmperf", - "arch_perfmon", - "art", - "bts", - "cat_l3", - "cdp_l3", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "dca", - "ds_cpl", - "dtes64", - "dtherm", - "dts", - "epb", - "ept", - "ept_ad", - "est", - "flexpriority", - "flush_l1d", - "hwp", - "hwp_act_window", - "hwp_epp", - "hwp_pkg_req", - "ida", - "intel_ppin", - "intel_pt", - "mba", - "monitor", - "pbe", - "pdcm", - "pebs", - "pln", - "pts", - "rdt_a", - "sdbg", - "smx", - "tm", - "tm2", - "tpr_shadow", - "vmx", - "vnmi", - "vpid", - "xtpr", - } + expected_host_minus_guest = INTEL_HOST_ONLY_FEATS expected_guest_minus_host = { "hypervisor", "tsc_known_freq", @@ -414,56 +369,10 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): assert host_feats - guest_feats == expected_host_minus_guest assert guest_feats - host_feats == expected_guest_minus_host case CpuModel.INTEL_ICELAKE: - host_guest_diff_5_10 = { - "dtes64", - "hwp_act_window", - "pdcm", - "acpi", - "aperfmperf", - "arch_perfmon", - "art", - "bts", - "cat_l3", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "dca", - "ds_cpl", - "dtherm", - "dts", - "epb", - "ept", - "ept_ad", - "est", - "flexpriority", - "flush_l1d", - "hwp", - "hwp_epp", - "hwp_pkg_req", - "ida", - "intel_ppin", - "intel_pt", - "mba", - "monitor", - "pbe", + host_guest_diff_5_10 = INTEL_HOST_ONLY_FEATS - {"cdp_l3"} | { "pconfig", - "pebs", - "pln", - "pts", - "rdt_a", - "sdbg", - "smx", - "split_lock_detect", - "tm", - "tm2", "tme", - "tpr_shadow", - "vmx", - "vnmi", - "vpid", - "xtpr", + "split_lock_detect", } host_guest_diff_6_1 = host_guest_diff_5_10 - { "bts", @@ -1261,7 +1170,7 @@ def test_c3_on_skylake_show_warning(uvm_plain, cpu_template): "does not apply the mitigation against MMIO stale data " "vulnerability." ) - if cpu_template == "C3" and global_props.cpu_codename == "INTEL_SKYLAKE": + if uvm.cpu_template_name == "c3" and global_props.cpu_codename == "INTEL_SKYLAKE": assert message in uvm.log_data else: assert message not in uvm.log_data From f4f7536eae69dce49895b476b0e58fa8fc597b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 18 Nov 2024 23:10:09 +0100 Subject: [PATCH 16/78] tests: move host vs guest cpu features into a single test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the same test spread over two files. Putting it together in a new file so they don't drift over time. Signed-off-by: Pablo Barbáchano --- .../functional/test_cpu_features_aarch64.py | 78 ----- .../test_cpu_features_host_vs_guest.py | 272 ++++++++++++++++++ .../functional/test_cpu_features_x86_64.py | 198 ------------- 3 files changed, 272 insertions(+), 276 deletions(-) create mode 100644 tests/integration_tests/functional/test_cpu_features_host_vs_guest.py diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index 1edcb39f151..2068194a894 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -2,11 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 """Tests for the CPU features for aarch64.""" -import os - import pytest -from framework import utils from framework.properties import global_props from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel @@ -49,78 +46,3 @@ def test_guest_cpu_features(uvm_any): guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) assert guest_feats == expected_cpu_features - - -def test_host_vs_guest_cpu_features(uvm_nano): - """Check CPU features host vs guest""" - - vm = uvm_nano - vm.add_net_iface() - vm.start() - host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.split()) - guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) - cpu_model = global_props.cpu_model - match cpu_model: - case CpuModel.ARM_NEOVERSE_N1: - expected_guest_minus_host = set() - expected_host_minus_guest = set() - - # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since - # they have an errata whereby an MSR to the SSBS special-purpose register does not - # affect subsequent speculative instructions, permitting speculative store bypassing for - # a window of time. - # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 - # - # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test - # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. - host_has_ssbs = global_props.host_os not in { - "amzn2", - "amzn2023", - } and global_props.host_linux_version_tpl < (6, 11) - guest_has_ssbs = vm.guest_kernel_version < (6, 11) - - if host_has_ssbs and not guest_has_ssbs: - expected_host_minus_guest |= {"ssbs"} - if not host_has_ssbs and guest_has_ssbs: - expected_guest_minus_host |= {"ssbs"} - - assert host_feats - guest_feats == expected_host_minus_guest - assert guest_feats - host_feats == expected_guest_minus_host - case CpuModel.ARM_NEOVERSE_V1: - expected_guest_minus_host = set() - # KVM does not enable PAC or SVE features by default - # and Firecracker does not enable them either. - expected_host_minus_guest = { - "paca", - "pacg", - "sve", - "svebf16", - "svei8mm", - } - - # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since - # they have an errata whereby an MSR to the SSBS special-purpose register does not - # affect subsequent speculative instructions, permitting speculative store bypassing for - # a window of time. - # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 - # - # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test - # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. - host_has_ssbs = global_props.host_os not in { - "amzn2", - "amzn2023", - } and global_props.host_linux_version_tpl < (6, 11) - guest_has_ssbs = vm.guest_kernel_version < (6, 11) - - if host_has_ssbs and not guest_has_ssbs: - expected_host_minus_guest |= {"ssbs"} - if not host_has_ssbs and guest_has_ssbs: - expected_guest_minus_host |= {"ssbs"} - - assert host_feats - guest_feats == expected_host_minus_guest - assert guest_feats - host_feats == expected_guest_minus_host - case _: - if os.environ.get("BUILDKITE") is not None: - assert ( - False - ), f"Cpu model {cpu_model} is not supported, please onboard it." diff --git a/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py new file mode 100644 index 00000000000..bbf4ed57d21 --- /dev/null +++ b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py @@ -0,0 +1,272 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +# pylint: disable=too-many-statements + +""" +Check CPU features in the host vs the guest. + +This test can highlight differences between the host and what the guest sees. + +No CPU templates as we are interested only on what is passed through to the guest by default. +For that, check test_feat_parity.py +""" + +import os + +from framework import utils +from framework.properties import global_props +from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel + +CPU_MODEL = global_props.cpu_codename + +INTEL_HOST_ONLY_FEATS = { + "acpi", + "aperfmperf", + "arch_perfmon", + "art", + "bts", + "cat_l3", + "cdp_l3", + "cqm", + "cqm_llc", + "cqm_mbm_local", + "cqm_mbm_total", + "cqm_occup_llc", + "dca", + "ds_cpl", + "dtes64", + "dtherm", + "dts", + "epb", + "ept", + "ept_ad", + "est", + "flexpriority", + "flush_l1d", + "hwp", + "hwp_act_window", + "hwp_epp", + "hwp_pkg_req", + "ida", + "intel_ppin", + "intel_pt", + "mba", + "monitor", + "pbe", + "pdcm", + "pebs", + "pln", + "pts", + "rdt_a", + "sdbg", + "smx", + "tm", + "tm2", + "tpr_shadow", + "vmx", + "vnmi", + "vpid", + "xtpr", +} + + +def test_host_vs_guest_cpu_features(uvm_nano): + """Check CPU features host vs guest""" + + vm = uvm_nano + vm.add_net_iface() + vm.start() + host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.split()) + guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) + + match CPU_MODEL: + case CpuModel.AMD_MILAN: + host_guest_diff_5_10 = { + "amd_ppin", + "aperfmperf", + "bpext", + "cat_l3", + "cdp_l3", + "cpb", + "cqm", + "cqm_llc", + "cqm_mbm_local", + "cqm_mbm_total", + "cqm_occup_llc", + "decodeassists", + "extapic", + "extd_apicid", + "flushbyasid", + "hw_pstate", + "ibs", + "irperf", + "lbrv", + "mba", + "monitor", + "mwaitx", + "overflow_recov", + "pausefilter", + "perfctr_llc", + "perfctr_nb", + "pfthreshold", + "rdpru", + "rdt_a", + "sev", + "sev_es", + "skinit", + "smca", + "sme", + "succor", + "svm_lock", + "tce", + "tsc_scale", + "v_vmsave_vmload", + "vgif", + "vmcb_clean", + "wdt", + } + + host_guest_diff_6_1 = host_guest_diff_5_10 - { + "lbrv", + "pausefilter", + "pfthreshold", + "sme", + "tsc_scale", + "v_vmsave_vmload", + "vgif", + "vmcb_clean", + } | {"brs", "rapl", "v_spec_ctrl"} + + if global_props.host_linux_version_tpl < (6, 1): + assert host_feats - guest_feats == host_guest_diff_5_10 + else: + assert host_feats - guest_feats == host_guest_diff_6_1 + + assert guest_feats - host_feats == { + "hypervisor", + "tsc_adjust", + "tsc_deadline_timer", + "tsc_known_freq", + } + + case CpuModel.INTEL_SKYLAKE: + assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS + assert guest_feats - host_feats == { + "hypervisor", + "tsc_known_freq", + "umip", + } + + case CpuModel.INTEL_CASCADELAKE: + expected_host_minus_guest = INTEL_HOST_ONLY_FEATS + expected_guest_minus_host = { + "hypervisor", + "tsc_known_freq", + "umip", + } + + # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests. + # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e + # + # Our test ubuntu host kernel is v6.8 and has the commit. + if global_props.host_linux_version_tpl >= (6, 4): + expected_host_minus_guest -= {"flush_l1d"} + + # Linux kernel v6.6+ drops the "invpcid_single" synthetic feature bit. + # https://github.com/torvalds/linux/commit/54e3d9434ef61b97fd3263c141b928dc5635e50d + # + # Our test ubuntu host kernel is v6.8 and has the commit. + host_has_invpcid_single = global_props.host_linux_version_tpl < (6, 6) + guest_has_invpcid_single = vm.guest_kernel_version < (6, 6) + if host_has_invpcid_single and not guest_has_invpcid_single: + expected_host_minus_guest |= {"invpcid_single"} + if not host_has_invpcid_single and guest_has_invpcid_single: + expected_guest_minus_host |= {"invpcid_single"} + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host + + case CpuModel.INTEL_ICELAKE: + host_guest_diff_5_10 = INTEL_HOST_ONLY_FEATS - {"cdp_l3"} | { + "pconfig", + "tme", + "split_lock_detect", + } + host_guest_diff_6_1 = host_guest_diff_5_10 - { + "bts", + "dtes64", + "dts", + "pebs", + } + + if global_props.host_linux_version_tpl < (6, 1): + assert host_feats - guest_feats == host_guest_diff_5_10 + else: + assert host_feats - guest_feats == host_guest_diff_6_1 + + assert guest_feats - host_feats == { + "hypervisor", + "tsc_known_freq", + } + + case CpuModel.ARM_NEOVERSE_N1: + expected_guest_minus_host = set() + expected_host_minus_guest = set() + + # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since + # they have an errata whereby an MSR to the SSBS special-purpose register does not + # affect subsequent speculative instructions, permitting speculative store bypassing for + # a window of time. + # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 + # + # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test + # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. + host_has_ssbs = global_props.host_os not in { + "amzn2", + "amzn2023", + } and global_props.host_linux_version_tpl < (6, 11) + guest_has_ssbs = vm.guest_kernel_version < (6, 11) + + if host_has_ssbs and not guest_has_ssbs: + expected_host_minus_guest |= {"ssbs"} + if not host_has_ssbs and guest_has_ssbs: + expected_guest_minus_host |= {"ssbs"} + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host + + case CpuModel.ARM_NEOVERSE_V1: + expected_guest_minus_host = set() + # KVM does not enable PAC or SVE features by default + # and Firecracker does not enable them either. + expected_host_minus_guest = {"paca", "pacg", "sve", "svebf16", "svei8mm"} + + # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since + # they have an errata whereby an MSR to the SSBS special-purpose register does not + # affect subsequent speculative instructions, permitting speculative store bypassing for + # a window of time. + # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 + # + # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test + # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. + host_has_ssbs = global_props.host_os not in { + "amzn2", + "amzn2023", + } and global_props.host_linux_version_tpl < (6, 11) + guest_has_ssbs = vm.guest_kernel_version < (6, 11) + + if host_has_ssbs and not guest_has_ssbs: + expected_host_minus_guest |= {"ssbs"} + if not host_has_ssbs and guest_has_ssbs: + expected_guest_minus_host |= {"ssbs"} + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host + + case _: + # only fail if running in CI + if os.environ.get("BUILDKITE") is not None: + assert ( + guest_feats == host_feats + ), f"Cpu model {CPU_MODEL} is not supported" diff --git a/tests/integration_tests/functional/test_cpu_features_x86_64.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py index f8bbe1ef52e..a966e253c46 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -22,7 +22,6 @@ from framework.defs import SUPPORTED_HOST_KERNELS from framework.properties import global_props from framework.utils_cpu_templates import SUPPORTED_CPU_TEMPLATES -from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel PLATFORM = platform.machine() UNSUPPORTED_HOST_KERNEL = ( @@ -203,203 +202,6 @@ def test_brand_string(uvm_plain_any): assert False -INTEL_HOST_ONLY_FEATS = { - "acpi", - "aperfmperf", - "arch_perfmon", - "art", - "bts", - "cat_l3", - "cdp_l3", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "dca", - "ds_cpl", - "dtes64", - "dtherm", - "dts", - "epb", - "ept", - "ept_ad", - "est", - "flexpriority", - "flush_l1d", - "hwp", - "hwp_act_window", - "hwp_epp", - "hwp_pkg_req", - "ida", - "intel_ppin", - "intel_pt", - "mba", - "monitor", - "pbe", - "pdcm", - "pebs", - "pln", - "pts", - "rdt_a", - "sdbg", - "smx", - "tm", - "tm2", - "tpr_shadow", - "vmx", - "vnmi", - "vpid", - "xtpr", -} - - -def test_host_vs_guest_cpu_features_x86_64(uvm_nano): - """Check CPU features host vs guest""" - - vm = uvm_nano - vm.add_net_iface() - vm.start() - host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.strip().split(" ")) - guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.strip().split(" ")) - - cpu_model = cpuid_utils.get_cpu_codename() - match cpu_model: - case CpuModel.AMD_MILAN: - host_guest_diff_5_10 = { - "amd_ppin", - "aperfmperf", - "bpext", - "cat_l3", - "cdp_l3", - "cpb", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "decodeassists", - "extapic", - "extd_apicid", - "flushbyasid", - "hw_pstate", - "ibs", - "irperf", - "lbrv", - "mba", - "monitor", - "mwaitx", - "overflow_recov", - "pausefilter", - "perfctr_llc", - "perfctr_nb", - "pfthreshold", - "rdpru", - "rdt_a", - "sev", - "sev_es", - "skinit", - "smca", - "sme", - "succor", - "svm_lock", - "tce", - "tsc_scale", - "v_vmsave_vmload", - "vgif", - "vmcb_clean", - "wdt", - } - - host_guest_diff_6_1 = host_guest_diff_5_10 - { - "lbrv", - "pausefilter", - "pfthreshold", - "sme", - "tsc_scale", - "v_vmsave_vmload", - "vgif", - "vmcb_clean", - } | {"brs", "rapl", "v_spec_ctrl"} - - if global_props.host_linux_version_tpl < (6, 1): - assert host_feats - guest_feats == host_guest_diff_5_10 - else: - assert host_feats - guest_feats == host_guest_diff_6_1 - - assert guest_feats - host_feats == { - "hypervisor", - "tsc_adjust", - "tsc_deadline_timer", - "tsc_known_freq", - } - case CpuModel.INTEL_SKYLAKE: - assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS - assert guest_feats - host_feats == { - "hypervisor", - "tsc_known_freq", - "umip", - } - case CpuModel.INTEL_CASCADELAKE: - expected_host_minus_guest = INTEL_HOST_ONLY_FEATS - expected_guest_minus_host = { - "hypervisor", - "tsc_known_freq", - "umip", - } - - # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests. - # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e - # - # Our test ubuntu host kernel is v6.8 and has the commit. - if global_props.host_linux_version_tpl >= (6, 4): - expected_host_minus_guest -= {"flush_l1d"} - - # Linux kernel v6.6+ drops the "invpcid_single" synthetic feature bit. - # https://github.com/torvalds/linux/commit/54e3d9434ef61b97fd3263c141b928dc5635e50d - # - # Our test ubuntu host kernel is v6.8 and has the commit. - host_has_invpcid_single = global_props.host_linux_version_tpl < (6, 6) - guest_has_invpcid_single = vm.guest_kernel_version < (6, 6) - if host_has_invpcid_single and not guest_has_invpcid_single: - expected_host_minus_guest |= {"invpcid_single"} - if not host_has_invpcid_single and guest_has_invpcid_single: - expected_guest_minus_host |= {"invpcid_single"} - - assert host_feats - guest_feats == expected_host_minus_guest - assert guest_feats - host_feats == expected_guest_minus_host - case CpuModel.INTEL_ICELAKE: - host_guest_diff_5_10 = INTEL_HOST_ONLY_FEATS - {"cdp_l3"} | { - "pconfig", - "tme", - "split_lock_detect", - } - host_guest_diff_6_1 = host_guest_diff_5_10 - { - "bts", - "dtes64", - "dts", - "pebs", - } - - if global_props.host_linux_version_tpl < (6, 1): - assert host_feats - guest_feats == host_guest_diff_5_10 - else: - assert host_feats - guest_feats == host_guest_diff_6_1 - - assert guest_feats - host_feats == { - "hypervisor", - "tsc_known_freq", - } - case CpuModel.AMD_GENOA: - # Return here to allow the test to pass until CPU features to enable are confirmed - return - case _: - if os.environ.get("BUILDKITE") is not None: - assert ( - guest_feats == host_feats - ), f"Cpu model {cpu_model} is not supported" - - # From the `Intel® 64 Architecture x2APIC Specification` # (https://courses.cs.washington.edu/courses/cse451/24wi/documentation/x2apic.pdf): # > The X2APIC MSRs cannot to be loaded and stored on VMX transitions. A VMX transition fails From 41f435929c647bb3dc7ad9acebccee3fde9c54a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sat, 23 Nov 2024 11:59:20 +0100 Subject: [PATCH 17/78] tests: add helper method MicrovmFactory.build_from_snapshot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a fairly common repeated pattern, so extract it into a method to make writing tests simpler. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 4 +- tests/framework/microvm.py | 7 +++ .../integration_tests/functional/test_api.py | 5 +- .../functional/test_balloon.py | 4 +- .../functional/test_cmd_line_parameters.py | 4 +- .../functional/test_snapshot_basic.py | 52 ++++++------------- .../functional/test_snapshot_editor.py | 4 +- .../test_snapshot_not_losing_dirty_pages.py | 7 +-- .../functional/test_vsock.py | 9 +--- 9 files changed, 31 insertions(+), 65 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index a2990a56c98..7cacedb9918 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -477,9 +477,7 @@ def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template): uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template) snapshot = uvm.snapshot_full() uvm.kill() - uvm2 = microvm_factory.build() - uvm2.spawn() - uvm2.restore_from_snapshot(snapshot, resume=True) + uvm2 = microvm_factory.build_from_snapshot(snapshot) uvm2.cpu_template_name = uvm.cpu_template_name return uvm2 diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 832f56a877e..572437c758b 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -1084,6 +1084,13 @@ def build(self, kernel=None, rootfs=None, **kwargs): vm.ssh_key = ssh_key return vm + def build_from_snapshot(self, snapshot: Snapshot): + """Build a microvm from a snapshot""" + vm = self.build() + vm.spawn() + vm.restore_from_snapshot(snapshot, resume=True) + return vm + def kill(self): """Clean up all built VMs""" for vm in self.vms: diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index 27366529c39..1e54c7b4fb1 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -1166,10 +1166,7 @@ def test_get_full_config_after_restoring_snapshot(microvm_factory, uvm_nano): ] snapshot = uvm_nano.snapshot_full() - uvm2 = microvm_factory.build() - uvm2.spawn() - uvm2.restore_from_snapshot(snapshot, resume=True) - + uvm2 = microvm_factory.build_from_snapshot(snapshot) expected_cfg = setup_cfg.copy() # We expect boot-source to be set with the following values diff --git a/tests/integration_tests/functional/test_balloon.py b/tests/integration_tests/functional/test_balloon.py index ee750dcac7d..2c59fd2e814 100644 --- a/tests/integration_tests/functional/test_balloon.py +++ b/tests/integration_tests/functional/test_balloon.py @@ -484,9 +484,7 @@ def test_balloon_snapshot(microvm_factory, guest_kernel, rootfs): assert first_reading > second_reading snapshot = vm.snapshot_full() - microvm = microvm_factory.build() - microvm.spawn() - microvm.restore_from_snapshot(snapshot, resume=True) + microvm = microvm_factory.build_from_snapshot(snapshot) # Get the firecracker from snapshot pid, and open an ssh connection. firecracker_pid = microvm.firecracker_pid diff --git a/tests/integration_tests/functional/test_cmd_line_parameters.py b/tests/integration_tests/functional/test_cmd_line_parameters.py index 25e47a50e17..79af938b1f7 100644 --- a/tests/integration_tests/functional/test_cmd_line_parameters.py +++ b/tests/integration_tests/functional/test_cmd_line_parameters.py @@ -96,9 +96,7 @@ def test_cli_metrics_if_resume_no_metrics(uvm_plain, microvm_factory): snapshot = uvm1.snapshot_full() # When: restoring from the snapshot - uvm2 = microvm_factory.build() - uvm2.spawn() - uvm2.restore_from_snapshot(snapshot) + uvm2 = microvm_factory.build_from_snapshot(snapshot) # Then: the old metrics configuration does not exist metrics2 = Path(uvm2.jailer.chroot_path()) / metrics_path.name diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index ac596440f67..4030bb4e981 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -50,39 +50,25 @@ def _get_guest_drive_size(ssh_connection, guest_dev_name="/dev/vdb"): return lines[1].strip() -def test_resume_after_restoration(uvm_nano, microvm_factory): - """Tests snapshot is resumable after restoration. +@pytest.mark.parametrize("resume_at_restore", [True, False]) +def test_resume(uvm_nano, microvm_factory, resume_at_restore): + """Tests snapshot is resumable at or after restoration. - Check that a restored microVM is resumable by calling PATCH /vm with Resumed - after PUT /snapshot/load with `resume_vm=False`. + Check that a restored microVM is resumable by either + a. PUT /snapshot/load with `resume_vm=False`, then calling PATCH /vm resume=True + b. PUT /snapshot/load with `resume_vm=True` """ vm = uvm_nano vm.add_net_iface() vm.start() - - snapshot = vm.snapshot_full() - - restored_vm = microvm_factory.build() - restored_vm.spawn() - restored_vm.restore_from_snapshot(snapshot) - restored_vm.resume() - - -def test_resume_at_restoration(uvm_nano, microvm_factory): - """Tests snapshot is resumable at restoration. - - Check that a restored microVM is resumable by calling PUT /snapshot/load - with `resume_vm=True`. - """ - vm = uvm_nano - vm.add_net_iface() - vm.start() - snapshot = vm.snapshot_full() - restored_vm = microvm_factory.build() restored_vm.spawn() - restored_vm.restore_from_snapshot(snapshot, resume=True) + restored_vm.restore_from_snapshot(snapshot, resume=resume_at_restore) + if not resume_at_restore: + assert restored_vm.state == "Paused" + restored_vm.resume() + assert restored_vm.state == "Running" def test_snapshot_current_version(uvm_nano): @@ -228,9 +214,7 @@ def test_patch_drive_snapshot(uvm_nano, microvm_factory): # Load snapshot in a new Firecracker microVM. logger.info("Load snapshot, mem %s", snapshot.mem) - vm = microvm_factory.build() - vm.spawn() - vm.restore_from_snapshot(snapshot, resume=True) + vm = microvm_factory.build_from_snapshot(snapshot) # Attempt to connect to resumed microvm and verify the new microVM has the # right scratch drive. @@ -319,9 +303,7 @@ def test_negative_postload_api(uvm_plain, microvm_factory): basevm.kill() # Do not resume, just load, so we can still call APIs that work. - microvm = microvm_factory.build() - microvm.spawn() - microvm.restore_from_snapshot(snapshot, resume=True) + microvm = microvm_factory.build_from_snapshot(snapshot) fail_msg = "The requested operation is not supported after starting the microVM" with pytest.raises(RuntimeError, match=fail_msg): @@ -486,9 +468,7 @@ def test_diff_snapshot_overlay(guest_kernel, rootfs, microvm_factory): assert not filecmp.cmp(merged_snapshot.mem, first_snapshot_backup, shallow=False) - new_vm = microvm_factory.build() - new_vm.spawn() - new_vm.restore_from_snapshot(merged_snapshot, resume=True) + _ = microvm_factory.build_from_snapshot(merged_snapshot) # Check that the restored VM works @@ -510,9 +490,7 @@ def test_snapshot_overwrite_self(guest_kernel, rootfs, microvm_factory): snapshot = base_vm.snapshot_full() base_vm.kill() - vm = microvm_factory.build() - vm.spawn() - vm.restore_from_snapshot(snapshot, resume=True) + vm = microvm_factory.build_from_snapshot(snapshot) # When restoring a snapshot, vm.restore_from_snapshot first copies # the memory file (inside of the jailer) to /mem.src diff --git a/tests/integration_tests/functional/test_snapshot_editor.py b/tests/integration_tests/functional/test_snapshot_editor.py index 4d466a441ce..9323695628c 100644 --- a/tests/integration_tests/functional/test_snapshot_editor.py +++ b/tests/integration_tests/functional/test_snapshot_editor.py @@ -68,6 +68,4 @@ def test_remove_regs(uvm_nano, microvm_factory): assert MIDR_EL1 not in stdout # test that we can restore from a snapshot - new_vm = microvm_factory.build() - new_vm.spawn() - new_vm.restore_from_snapshot(snapshot, resume=True) + _ = microvm_factory.build_from_snapshot(snapshot) diff --git a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py index 5584cfceac8..79366f13f0b 100644 --- a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py +++ b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py @@ -63,9 +63,6 @@ def test_diff_snapshot_works_after_error( # Now there is enough space for it to work snap2 = uvm.snapshot_diff() - - vm2 = microvm_factory.build() - vm2.spawn() - vm2.restore_from_snapshot(snap2, resume=True) - uvm.kill() + + _vm2 = microvm_factory.build_from_snapshot(snap2) diff --git a/tests/integration_tests/functional/test_vsock.py b/tests/integration_tests/functional/test_vsock.py index 2d540b8f934..dfa02510b37 100644 --- a/tests/integration_tests/functional/test_vsock.py +++ b/tests/integration_tests/functional/test_vsock.py @@ -199,10 +199,7 @@ def test_vsock_transport_reset_h2g( test_vm.kill() # Load snapshot. - - vm2 = microvm_factory.build() - vm2.spawn() - vm2.restore_from_snapshot(snapshot, resume=True) + vm2 = microvm_factory.build_from_snapshot(snapshot) # Check that vsock device still works. # Test guest-initiated connections. @@ -231,9 +228,7 @@ def test_vsock_transport_reset_g2h(uvm_nano, microvm_factory): for _ in range(5): # Load snapshot. - new_vm = microvm_factory.build() - new_vm.spawn() - new_vm.restore_from_snapshot(snapshot, resume=True) + new_vm = microvm_factory.build_from_snapshot(snapshot) # After snap restore all vsock connections should be # dropped. This means guest socat should exit same way From 54ae107941077f2444617d84fa8b8d6f973eb146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sat, 23 Nov 2024 12:03:31 +0100 Subject: [PATCH 18/78] tests: refactor test_rng with uvm_any MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite test_rng using uvm_any. Signed-off-by: Pablo Barbáchano --- .../integration_tests/functional/test_rng.py | 68 ++++++++++--------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/tests/integration_tests/functional/test_rng.py b/tests/integration_tests/functional/test_rng.py index b40aa66033d..1893230c51a 100644 --- a/tests/integration_tests/functional/test_rng.py +++ b/tests/integration_tests/functional/test_rng.py @@ -8,11 +8,9 @@ from host_tools.network import SSHConnection -@pytest.fixture(params=[None]) -def uvm_with_rng(uvm_plain, request): - """Fixture of a microvm with virtio-rng configured""" - rate_limiter = request.param - uvm = uvm_plain +def uvm_with_rng_booted(microvm_factory, guest_kernel, rootfs, rate_limiter): + """Return a booted microvm with virtio-rng configured""" + uvm = microvm_factory.build(guest_kernel, rootfs) uvm.spawn(log_level="INFO") uvm.basic_config(vcpu_count=2, mem_size_mib=256) uvm.add_net_iface() @@ -23,6 +21,34 @@ def uvm_with_rng(uvm_plain, request): return uvm +def uvm_with_rng_restored(microvm_factory, guest_kernel, rootfs, rate_limiter): + """Return a restored uvm with virtio-rng configured""" + uvm = uvm_with_rng_booted(microvm_factory, guest_kernel, rootfs, rate_limiter) + snapshot = uvm.snapshot_full() + uvm.kill() + uvm2 = microvm_factory.build_from_snapshot(snapshot) + uvm2.rng_rate_limiter = uvm.rng_rate_limiter + return uvm2 + + +@pytest.fixture(params=[uvm_with_rng_booted, uvm_with_rng_restored]) +def uvm_ctor(request): + """Fixture to return uvms with different constructors""" + return request.param + + +@pytest.fixture(params=[None]) +def rate_limiter(request): + """Fixture to return different rate limiters""" + return request.param + + +@pytest.fixture +def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, rate_limiter): + """Return booted and restored uvms""" + return uvm_ctor(microvm_factory, guest_kernel, rootfs, rate_limiter) + + def list_rng_available(ssh_connection: SSHConnection) -> list[str]: """Returns a list of rng devices available in the VM""" return ( @@ -62,35 +88,17 @@ def test_rng_not_present(uvm_nano): ), "virtio_rng device should not be available in the uvm" -def test_rng_present(uvm_with_rng): +def test_rng_present(uvm_any): """ Test a guest microVM with an entropy defined configured and ensure that we can access `/dev/hwrng` """ - vm = uvm_with_rng + vm = uvm_any assert_virtio_rng_is_current_hwrng_device(vm.ssh) check_entropy(vm.ssh) -def test_rng_snapshot(uvm_with_rng, microvm_factory): - """ - Test that a virtio-rng device is functional after resuming from - a snapshot - """ - - vm = uvm_with_rng - assert_virtio_rng_is_current_hwrng_device(vm.ssh) - check_entropy(vm.ssh) - snapshot = vm.snapshot_full() - - new_vm = microvm_factory.build() - new_vm.spawn() - new_vm.restore_from_snapshot(snapshot, resume=True) - assert_virtio_rng_is_current_hwrng_device(new_vm.ssh) - check_entropy(new_vm.ssh) - - def _get_percentage_difference(measured, base): """Return the percentage delta between the arguments.""" if measured == base: @@ -199,7 +207,7 @@ def _rate_limiter_id(rate_limiter): # parametrize the RNG rate limiter @pytest.mark.parametrize( - "uvm_with_rng", + "rate_limiter", [ {"bandwidth": {"size": 1000, "refill_time": 100}}, {"bandwidth": {"size": 10000, "refill_time": 100}}, @@ -208,16 +216,14 @@ def _rate_limiter_id(rate_limiter): indirect=True, ids=_rate_limiter_id, ) -def test_rng_bw_rate_limiter(uvm_with_rng): +@pytest.mark.parametrize("uvm_ctor", [uvm_with_rng_booted], indirect=True) +def test_rng_bw_rate_limiter(uvm_any): """ Test that rate limiter without initial burst budget works """ - vm = uvm_with_rng - # _start_vm_with_rng(vm, rate_limiter) - + vm = uvm_any size = vm.rng_rate_limiter["bandwidth"]["size"] refill_time = vm.rng_rate_limiter["bandwidth"]["refill_time"] - expected_kbps = size / refill_time assert_virtio_rng_is_current_hwrng_device(vm.ssh) From 80591e0d8af9c6ffcef0744d34246adf00b7c781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sat, 23 Nov 2024 13:55:58 +0100 Subject: [PATCH 19/78] tests: drop unused static cpu_templates fixture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixture is not used anymore, as it is mostly superseded by cpu_template_any. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 7 ------- .../functional/test_cpu_features_x86_64.py | 15 +++++++-------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 7cacedb9918..b599ffc79ab 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -292,13 +292,6 @@ def microvm_factory(request, record_property, results_dir): uvm_factory.kill() -@pytest.fixture(params=static_cpu_templates_params()) -def cpu_template(request, record_property): - """Return all static CPU templates supported by the vendor.""" - record_property("static_cpu_template", request.param) - return request.param - - @pytest.fixture(params=custom_cpu_templates_params()) def custom_cpu_template(request, record_property): """Return all dummy custom CPU templates supported by the vendor.""" diff --git a/tests/integration_tests/functional/test_cpu_features_x86_64.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py index a966e253c46..1af6a39f83a 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -952,18 +952,16 @@ def check_enabled_features(test_microvm, cpu_template): ) -def test_c3_on_skylake_show_warning(uvm_plain, cpu_template): +def test_c3_on_skylake_show_warning(uvm_plain, cpu_template_any): """ This test verifies that the warning message about MMIO stale data mitigation - is displayed only on Intel Skylake with C3 template. + is displayed only on Intel Skylake with static C3 template. """ uvm = uvm_plain uvm.spawn() - uvm.basic_config( - vcpu_count=2, - mem_size_mib=256, - cpu_template=cpu_template, - ) + uvm.basic_config(vcpu_count=2, mem_size_mib=256) + uvm.add_net_iface() + uvm.set_cpu_template(cpu_template_any) uvm.start() message = ( @@ -972,7 +970,8 @@ def test_c3_on_skylake_show_warning(uvm_plain, cpu_template): "does not apply the mitigation against MMIO stale data " "vulnerability." ) - if uvm.cpu_template_name == "c3" and global_props.cpu_codename == "INTEL_SKYLAKE": + + if cpu_template_any == "C3" and global_props.cpu_codename == "INTEL_SKYLAKE": assert message in uvm.log_data else: assert message not in uvm.log_data From b0cc581bb090a5c41df95c3d2276dc93ca179b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 28 Nov 2024 23:25:56 +0100 Subject: [PATCH 20/78] tests: simplify rootfs fixture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we only have one rootfs, simplify the fixture to return a single value. This will have also not show it as part of the test instance name. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 23 ++++++++++++----------- tests/framework/artifacts.py | 10 ++-------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index b599ffc79ab..5ed61083014 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -35,7 +35,7 @@ import host_tools.cargo_build as build_tools from framework import defs, utils -from framework.artifacts import kernel_params, rootfs_params +from framework.artifacts import disks, kernel_params from framework.microvm import MicroVMFactory from framework.properties import global_props from framework.utils_cpu_templates import ( @@ -354,13 +354,6 @@ def guest_kernel_fxt(request, record_property): return kernel -def rootfs_fxt(request, record_property): - """Return all supported rootfs.""" - fs = request.param - record_property("rootfs", fs.name) - return fs - - # Fixtures for all guest kernels, and specific versions guest_kernel = pytest.fixture(guest_kernel_fxt, params=kernel_params("vmlinux-*")) guest_kernel_acpi = pytest.fixture( @@ -380,9 +373,17 @@ def rootfs_fxt(request, record_property): params=kernel_params("vmlinux-6.1*"), ) -# Fixtures for all Ubuntu rootfs, and specific versions -rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("ubuntu-24*.squashfs")) -rootfs_rw = pytest.fixture(rootfs_fxt, params=rootfs_params("*.ext4")) + +@pytest.fixture +def rootfs(): + """Return an Ubuntu 24.04 read-only rootfs""" + return disks("ubuntu-24.04.squashfs")[0] + + +@pytest.fixture +def rootfs_rw(): + """Return an Ubuntu 24.04 ext4 rootfs""" + return disks("ubuntu-24.04.ext4")[0] @pytest.fixture diff --git a/tests/framework/artifacts.py b/tests/framework/artifacts.py index 77584f02129..0ed27c16b61 100644 --- a/tests/framework/artifacts.py +++ b/tests/framework/artifacts.py @@ -44,9 +44,9 @@ def kernels(glob, artifact_dir: Path = ARTIFACT_DIR) -> Iterator: break -def disks(glob) -> Iterator: +def disks(glob) -> list: """Return supported rootfs""" - yield from sorted(ARTIFACT_DIR.glob(glob)) + return sorted(ARTIFACT_DIR.glob(glob)) def kernel_params( @@ -57,12 +57,6 @@ def kernel_params( yield pytest.param(kernel, id=kernel.name) -def rootfs_params(glob="ubuntu-*.squashfs") -> Iterator: - """Return supported rootfs as pytest parameters""" - for rootfs in disks(glob=glob): - yield pytest.param(rootfs, id=rootfs.name) - - @dataclass(frozen=True, repr=True) class FirecrackerArtifact: """Utility class for Firecracker binary artifacts.""" From d7734e2c3faca1a1870588ae01b8667f5cef254c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 29 Nov 2024 09:32:07 +0100 Subject: [PATCH 21/78] tests: parametrize uvm_any fixture family with vcpus and memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a parameter so that we can control vcpu number and memory. Right now it uses a hardcoded value, but it can be overridden per test. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 54 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 5ed61083014..ac73b4bd8ab 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -455,20 +455,34 @@ def uvm_with_initrd( yield uvm -def uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template): +@pytest.fixture +def vcpu_count(): + """Return default vcpu_count. Use indirect parametrization to override.""" + return 2 + + +@pytest.fixture +def mem_size_mib(): + """Return memory size. Use indirect parametrization to override.""" + return 256 + + +def uvm_booted( + microvm_factory, guest_kernel, rootfs, cpu_template, vcpu_count=2, mem_size_mib=256 +): """Return a booted uvm""" uvm = microvm_factory.build(guest_kernel, rootfs) uvm.spawn() - uvm.basic_config(vcpu_count=2, mem_size_mib=256) + uvm.basic_config(vcpu_count=vcpu_count, mem_size_mib=mem_size_mib) uvm.set_cpu_template(cpu_template) uvm.add_net_iface() uvm.start() return uvm -def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template): +def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs): """Return a restored uvm""" - uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template) + uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs) snapshot = uvm.snapshot_full() uvm.kill() uvm2 = microvm_factory.build_from_snapshot(snapshot) @@ -483,12 +497,36 @@ def uvm_ctor(request): @pytest.fixture -def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, cpu_template_any): +def uvm_any( + microvm_factory, + uvm_ctor, + guest_kernel, + rootfs, + cpu_template_any, + vcpu_count, + mem_size_mib, +): """Return booted and restored uvms""" - return uvm_ctor(microvm_factory, guest_kernel, rootfs, cpu_template_any) + return uvm_ctor( + microvm_factory, + guest_kernel, + rootfs, + cpu_template_any, + vcpu_count=vcpu_count, + mem_size_mib=mem_size_mib, + ) @pytest.fixture -def uvm_any_booted(microvm_factory, guest_kernel, rootfs, cpu_template_any): +def uvm_any_booted( + microvm_factory, guest_kernel, rootfs, cpu_template_any, vcpu_count, mem_size_mib +): """Return booted uvms""" - return uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template_any) + return uvm_booted( + microvm_factory, + guest_kernel, + rootfs, + cpu_template_any, + vcpu_count=vcpu_count, + mem_size_mib=mem_size_mib, + ) From 1f94a59b1b04626e14a02dbd4bcbbdf3b79fefd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 6 Dec 2024 11:24:30 +0100 Subject: [PATCH 22/78] fix(tests): save snapshot metadata when saving to disk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We missed saving metadata when saving to disk Fixes: 426790e4001ac7315554f876637298fb37fb85a8 Signed-off-by: Pablo Barbáchano --- tests/framework/microvm.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 572437c758b..91b88cc4c28 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -150,6 +150,7 @@ def save_to(self, dst: Path): "disks": new_disks, "ssh_key": self.ssh_key.name, "snapshot_type": self.snapshot_type.value, + "meta": self.meta, } snap_json = dst / "snapshot.json" snap_json.write_text(json.dumps(obj)) @@ -937,7 +938,7 @@ def make_snapshot( ssh_key=self.ssh_key, snapshot_type=snapshot_type, meta={ - "kernel_file": self.kernel_file, + "kernel_file": str(self.kernel_file), }, ) @@ -978,6 +979,8 @@ def restore_from_snapshot( for key, value in snapshot.meta.items(): setattr(self, key, value) + # Adjust things just in case + self.kernel_file = Path(self.kernel_file) self.api.snapshot_load.put( mem_backend=mem_backend, From 761909de71d2e4a8c110334cde928fab34831f61 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 6 Dec 2024 13:53:02 +0000 Subject: [PATCH 23/78] fix(tests): add switch case for AMD_GENOA to the cpu features test During previous refactoring, this switch was accidentally removed. Signed-off-by: Egor Lazarchuk --- .../functional/test_cpu_features_host_vs_guest.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py index bbf4ed57d21..71e61262c69 100644 --- a/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py +++ b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py @@ -150,6 +150,10 @@ def test_host_vs_guest_cpu_features(uvm_nano): "tsc_known_freq", } + case CpuModel.AMD_GENOA: + # Return here to allow the test to pass until CPU features to enable are confirmed + return + case CpuModel.INTEL_SKYLAKE: assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS assert guest_feats - host_feats == { From f59717cfd19ae0634962b70fed14bf71c6b269aa Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Tue, 3 Dec 2024 07:25:11 +0000 Subject: [PATCH 24/78] doc: Use a valid bitmap for vcpu_features As seen in #4925, setting the least significant bits of vcpu_features field to 0 make secondary CPUs not work. There is no reason to use such an invalid example in doc. The sample in doc intended to enable PAC (Pointer Authentication) since it checks capabilities 171 and 172 [2]. Thus, not set the other bits than bits 5 and 6. [1]: https://elixir.bootlin.com/linux/v6.12.1/source/include/uapi/linux/kvm.h#L868-L869 [2]: https://elixir.bootlin.com/linux/v6.12.1/source/arch/arm64/include/uapi/asm/kvm.h#L108-L109 Signed-off-by: Takahiro Itazuri --- docs/cpu_templates/cpu-templates.md | 2 +- docs/cpu_templates/schema.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/cpu_templates/cpu-templates.md b/docs/cpu_templates/cpu-templates.md index e00e71f26e2..a2d8b06fceb 100644 --- a/docs/cpu_templates/cpu-templates.md +++ b/docs/cpu_templates/cpu-templates.md @@ -180,7 +180,7 @@ curl --unix-socket /tmp/firecracker.socket -i \ -H 'Content-Type: application/json' \ -d '{ "kvm_capabilities": ["171", "172"], - "vcpu_features": [{ "index": 0, "bitmap": "0b1100000" }] + "vcpu_features": [{ "index": 0, "bitmap": "0b11xxxxx" }] "reg_modifiers": [ { "addr": "0x603000000013c020", diff --git a/docs/cpu_templates/schema.json b/docs/cpu_templates/schema.json index 76a11697e06..27844756941 100644 --- a/docs/cpu_templates/schema.json +++ b/docs/cpu_templates/schema.json @@ -26,7 +26,7 @@ "bitmap": { "description": "Bitmap for modifying the 32 bit field in kvm_vcpu_init::features. Must be in the format `0b[01x]{1,32}`. Corresponding bits will be cleared (`0`), set (`1`) or left intact (`x`). (`_`) can be used as a separator.", "type": "string", - "examples": ["0b1100000"] + "examples": ["0b11xxxxx"] } } } From da1c3b37f3170af1e03d69daa8ce106d56b8511b Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 4 Dec 2024 07:49:40 +0000 Subject: [PATCH 25/78] test: Check all vCPUs are online As seen in #4925, a bad CPU template made secondary CPUs not come up. To catch similar bugs of CPU templates, check all the vCPUs are online from guests' perspective. Signed-off-by: Takahiro Itazuri --- tests/framework/microvm.py | 1 + .../functional/test_cpu_multiple.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/integration_tests/functional/test_cpu_multiple.py diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 91b88cc4c28..eb755ffc5fa 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -939,6 +939,7 @@ def make_snapshot( snapshot_type=snapshot_type, meta={ "kernel_file": str(self.kernel_file), + "vcpus_count": self.vcpus_count, }, ) diff --git a/tests/integration_tests/functional/test_cpu_multiple.py b/tests/integration_tests/functional/test_cpu_multiple.py new file mode 100644 index 00000000000..8d150950a38 --- /dev/null +++ b/tests/integration_tests/functional/test_cpu_multiple.py @@ -0,0 +1,18 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Test all vCPUs are configured correctly and work properly. + +This test suite aims to catch bugs of Firecracker's vCPU configuration and +CPU templates especially under multi-vCPU setup, by checking that all vCPUs +are operating identically, except for the expected differences. +""" + + +def test_all_vcpus_online(uvm_any): + """Check all vCPUs are online inside guest""" + assert ( + uvm_any.ssh.check_output("cat /sys/devices/system/cpu/online").stdout.strip() + == f"0-{uvm_any.vcpus_count - 1}" + ) From 21472d0e4ab5e2ac6b57710eaeaade02c1d85270 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 4 Dec 2024 08:37:54 +0000 Subject: [PATCH 26/78] test: Check all vCPUs have the same features inside guest The test ensures Firecracker or CPU templates don't configure CPU features differently between vCPUs. Note that whether the printed CPU features are expected or not should be tested in (arch-specific) test_cpu_features_*.py only for vCPU 0. Thus, we only test the equivalence of all CPUs in the same guest. Signed-off-by: Takahiro Itazuri --- .../functional/test_cpu_multiple.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/integration_tests/functional/test_cpu_multiple.py b/tests/integration_tests/functional/test_cpu_multiple.py index 8d150950a38..1dd38a10906 100644 --- a/tests/integration_tests/functional/test_cpu_multiple.py +++ b/tests/integration_tests/functional/test_cpu_multiple.py @@ -16,3 +16,21 @@ def test_all_vcpus_online(uvm_any): uvm_any.ssh.check_output("cat /sys/devices/system/cpu/online").stdout.strip() == f"0-{uvm_any.vcpus_count - 1}" ) + + +def test_all_vcpus_have_same_features(uvm_any): + """ + Check all vCPUs have the same features inside guest. + + This test ensures Firecracker or CPU templates don't configure CPU features + differently between vCPUs. + + Note that whether the shown CPU features are expected or not should be + tested in (arch-specific) test_cpu_features_*.py only for vCPU 0. Thus, we + only test the equivalence of all CPUs in the same guest. + """ + # Get a feature set for each CPU and deduplicate them. + unique_feature_lists = uvm_any.ssh.check_output( + 'grep -E "^(flags|Features)" /proc/cpuinfo | uniq' + ).stdout.splitlines() + assert len(unique_feature_lists) == 1 From db2e270d996b3e31037bcf5bd7e1292103f2f39a Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 6 Dec 2024 07:45:57 +0000 Subject: [PATCH 27/78] test: Remove test_max_cpus.py test_max_cpus.py tests vCPUs are online only on a microVM without CPU templates, which is now covered as part of test_all_vcpus_online(). Remove the test and use the maximum number of vCPUs in the new tests. Signed-off-by: Takahiro Itazuri --- .../{test_cpu_multiple.py => test_cpu_all.py} | 7 ++++++ .../functional/test_max_vcpus.py | 23 ------------------- 2 files changed, 7 insertions(+), 23 deletions(-) rename tests/integration_tests/functional/{test_cpu_multiple.py => test_cpu_all.py} (87%) delete mode 100644 tests/integration_tests/functional/test_max_vcpus.py diff --git a/tests/integration_tests/functional/test_cpu_multiple.py b/tests/integration_tests/functional/test_cpu_all.py similarity index 87% rename from tests/integration_tests/functional/test_cpu_multiple.py rename to tests/integration_tests/functional/test_cpu_all.py index 1dd38a10906..6b934ffa394 100644 --- a/tests/integration_tests/functional/test_cpu_multiple.py +++ b/tests/integration_tests/functional/test_cpu_all.py @@ -9,7 +9,13 @@ are operating identically, except for the expected differences. """ +import pytest +# Use the maximum number of vCPUs supported by Firecracker +MAX_VCPUS = 32 + + +@pytest.mark.parametrize("vcpu_count", [MAX_VCPUS]) def test_all_vcpus_online(uvm_any): """Check all vCPUs are online inside guest""" assert ( @@ -18,6 +24,7 @@ def test_all_vcpus_online(uvm_any): ) +@pytest.mark.parametrize("vcpu_count", [MAX_VCPUS]) def test_all_vcpus_have_same_features(uvm_any): """ Check all vCPUs have the same features inside guest. diff --git a/tests/integration_tests/functional/test_max_vcpus.py b/tests/integration_tests/functional/test_max_vcpus.py deleted file mode 100644 index 05c1f3c51ff..00000000000 --- a/tests/integration_tests/functional/test_max_vcpus.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -"""Tests scenario for microvms with max vcpus(32).""" - -MAX_VCPUS = 32 - - -def test_max_vcpus(uvm_plain): - """ - Test if all configured guest vcpus are online. - """ - microvm = uvm_plain - microvm.spawn() - - # Configure a microVM with 32 vCPUs. - microvm.basic_config(vcpu_count=MAX_VCPUS) - microvm.add_net_iface() - microvm.start() - - cmd = "nproc" - _, stdout, stderr = microvm.ssh.run(cmd) - assert stderr == "" - assert int(stdout) == MAX_VCPUS From 3b5f161ae236a7a4c5887959de0a011d245bca6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 6 Dec 2024 11:48:41 +0100 Subject: [PATCH 28/78] tests: flesh out the AMD Genoa host vs guest test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Record the differences wrt AMD Milan CPUs. Signed-off-by: Pablo Barbáchano --- .../test_cpu_features_host_vs_guest.py | 179 ++++++++++-------- 1 file changed, 98 insertions(+), 81 deletions(-) diff --git a/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py index 71e61262c69..d2fd4936328 100644 --- a/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py +++ b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # pylint: disable=too-many-statements +# pylint: disable=too-many-branches """ Check CPU features in the host vs the guest. @@ -70,6 +71,91 @@ "xtpr", } +INTEL_GUEST_ONLY_FEATS = { + "hypervisor", + "tsc_known_freq", + "umip", +} + +AMD_MILAN_HOST_ONLY_FEATS = { + "amd_ppin", + "aperfmperf", + "bpext", + "cat_l3", + "cdp_l3", + "cpb", + "cqm", + "cqm_llc", + "cqm_mbm_local", + "cqm_mbm_total", + "cqm_occup_llc", + "decodeassists", + "extapic", + "extd_apicid", + "flushbyasid", + "hw_pstate", + "ibs", + "irperf", + "lbrv", + "mba", + "monitor", + "mwaitx", + "overflow_recov", + "pausefilter", + "perfctr_llc", + "perfctr_nb", + "pfthreshold", + "rdpru", + "rdt_a", + "sev", + "sev_es", + "skinit", + "smca", + "sme", + "succor", + "svm_lock", + "tce", + "tsc_scale", + "v_vmsave_vmload", + "vgif", + "vmcb_clean", + "wdt", +} + +AMD_GUEST_ONLY_FEATS = { + "hypervisor", + "tsc_adjust", + "tsc_deadline_timer", + "tsc_known_freq", +} + +AMD_MILAN_HOST_ONLY_FEATS_6_1 = AMD_MILAN_HOST_ONLY_FEATS - { + "lbrv", + "pausefilter", + "pfthreshold", + "sme", + "tsc_scale", + "v_vmsave_vmload", + "vgif", + "vmcb_clean", +} | {"brs", "rapl", "v_spec_ctrl"} + +AMD_GENOA_HOST_ONLY_FEATS = AMD_MILAN_HOST_ONLY_FEATS | { + "avic", + "flush_l1d", + "ibrs_enhanced", +} + +AMD_GENOA_HOST_ONLY_FEATS_6_1 = AMD_MILAN_HOST_ONLY_FEATS_6_1 - {"brs"} | { + "avic", + "amd_lbr_v2", + "cppc", + "flush_l1d", + "ibrs_enhanced", + "perfmon_v2", + "x2avic", +} + def test_host_vs_guest_cpu_features(uvm_nano): """Check CPU features host vs guest""" @@ -82,93 +168,28 @@ def test_host_vs_guest_cpu_features(uvm_nano): match CPU_MODEL: case CpuModel.AMD_MILAN: - host_guest_diff_5_10 = { - "amd_ppin", - "aperfmperf", - "bpext", - "cat_l3", - "cdp_l3", - "cpb", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "decodeassists", - "extapic", - "extd_apicid", - "flushbyasid", - "hw_pstate", - "ibs", - "irperf", - "lbrv", - "mba", - "monitor", - "mwaitx", - "overflow_recov", - "pausefilter", - "perfctr_llc", - "perfctr_nb", - "pfthreshold", - "rdpru", - "rdt_a", - "sev", - "sev_es", - "skinit", - "smca", - "sme", - "succor", - "svm_lock", - "tce", - "tsc_scale", - "v_vmsave_vmload", - "vgif", - "vmcb_clean", - "wdt", - } - - host_guest_diff_6_1 = host_guest_diff_5_10 - { - "lbrv", - "pausefilter", - "pfthreshold", - "sme", - "tsc_scale", - "v_vmsave_vmload", - "vgif", - "vmcb_clean", - } | {"brs", "rapl", "v_spec_ctrl"} - if global_props.host_linux_version_tpl < (6, 1): - assert host_feats - guest_feats == host_guest_diff_5_10 + assert host_feats - guest_feats == AMD_MILAN_HOST_ONLY_FEATS else: - assert host_feats - guest_feats == host_guest_diff_6_1 + assert host_feats - guest_feats == AMD_MILAN_HOST_ONLY_FEATS_6_1 - assert guest_feats - host_feats == { - "hypervisor", - "tsc_adjust", - "tsc_deadline_timer", - "tsc_known_freq", - } + assert guest_feats - host_feats == AMD_GUEST_ONLY_FEATS case CpuModel.AMD_GENOA: - # Return here to allow the test to pass until CPU features to enable are confirmed - return + if global_props.host_linux_version_tpl < (6, 1): + assert host_feats - guest_feats == AMD_GENOA_HOST_ONLY_FEATS + else: + assert host_feats - guest_feats == AMD_GENOA_HOST_ONLY_FEATS_6_1 + + assert guest_feats - host_feats == AMD_GUEST_ONLY_FEATS case CpuModel.INTEL_SKYLAKE: assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS - assert guest_feats - host_feats == { - "hypervisor", - "tsc_known_freq", - "umip", - } + assert guest_feats - host_feats == INTEL_GUEST_ONLY_FEATS case CpuModel.INTEL_CASCADELAKE: expected_host_minus_guest = INTEL_HOST_ONLY_FEATS - expected_guest_minus_host = { - "hypervisor", - "tsc_known_freq", - "umip", - } + expected_guest_minus_host = INTEL_GUEST_ONLY_FEATS # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests. # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e @@ -208,11 +229,7 @@ def test_host_vs_guest_cpu_features(uvm_nano): assert host_feats - guest_feats == host_guest_diff_5_10 else: assert host_feats - guest_feats == host_guest_diff_6_1 - - assert guest_feats - host_feats == { - "hypervisor", - "tsc_known_freq", - } + assert guest_feats - host_feats == INTEL_GUEST_ONLY_FEATS - {"umip"} case CpuModel.ARM_NEOVERSE_N1: expected_guest_minus_host = set() From 83c57e92408537d48b988624222d264b3678f911 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 12:29:59 +0000 Subject: [PATCH 29/78] build(deps): Bump the firecracker group across 1 directory with 10 updates Bumps the firecracker group with 8 updates in the / directory: | Package | From | To | | --- | --- | --- | | [thiserror](https://github.com/dtolnay/thiserror) | `2.0.3` | `2.0.6` | | [zerocopy](https://github.com/google/zerocopy) | `0.8.11` | `0.8.13` | | [clap](https://github.com/clap-rs/clap) | `4.5.21` | `4.5.23` | | [libc](https://github.com/rust-lang/libc) | `0.2.167` | `0.2.168` | | [cargo_toml](https://gitlab.com/lib.rs/cargo_toml) | `0.20.5` | `0.21.0` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.2` | `1.2.3` | | [rustix](https://github.com/bytecodealliance/rustix) | `0.38.41` | `0.38.42` | | [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.13` | `1.0.14` | Updates `thiserror` from 2.0.3 to 2.0.6 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/2.0.3...2.0.6) Updates `zerocopy` from 0.8.11 to 0.8.13 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.11...v0.8.13) Updates `clap` from 4.5.21 to 4.5.23 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.21...clap_complete-v4.5.23) Updates `libc` from 0.2.167 to 0.2.168 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.168/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.167...0.2.168) Updates `cargo_toml` from 0.20.5 to 0.21.0 - [Commits](https://gitlab.com/lib.rs/cargo_toml/commits/main) Updates `cc` from 1.2.2 to 1.2.3 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.2...cc-v1.2.3) Updates `clap_builder` from 4.5.21 to 4.5.23 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.21...v4.5.23) Updates `clap_lex` from 0.7.3 to 0.7.4 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_lex-v0.7.3...clap_lex-v0.7.4) Updates `rustix` from 0.38.41 to 0.38.42 - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.41...v0.38.42) Updates `unicode-ident` from 1.0.13 to 1.0.14 - [Release notes](https://github.com/dtolnay/unicode-ident/releases) - [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.13...1.0.14) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cargo_toml dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_builder dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_lex dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: rustix dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: unicode-ident dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 76 +++++++++++++++--------------- src/acpi-tables/Cargo.toml | 4 +- src/clippy-tracing/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 6 +-- src/firecracker/Cargo.toml | 8 ++-- src/jailer/Cargo.toml | 4 +- src/rebase-snap/Cargo.toml | 4 +- src/seccompiler/Cargo.toml | 4 +- src/snapshot-editor/Cargo.toml | 6 +-- src/utils/Cargo.toml | 4 +- src/vmm/Cargo.toml | 6 +-- 11 files changed, 62 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 521552d3f87..f31b84f68c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,9 +7,9 @@ name = "acpi_tables" version = "0.1.0" dependencies = [ "displaydoc", - "thiserror 2.0.3", + "thiserror 2.0.6", "vm-memory", - "zerocopy 0.8.11", + "zerocopy 0.8.13", ] [[package]] @@ -244,9 +244,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cargo_toml" -version = "0.20.5" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88da5a13c620b4ca0078845707ea9c3faf11edbc3ffd8497d11d686211cd1ac0" +checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472" dependencies = [ "serde", "toml", @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "jobserver", "libc", @@ -340,9 +340,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -359,9 +359,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clippy-tracing" @@ -425,7 +425,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "vmm", "vmm-sys-util", ] @@ -619,7 +619,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "timerfd", "userfaultfd", "utils", @@ -805,7 +805,7 @@ dependencies = [ "log-instrument", "nix 0.29.0", "regex", - "thiserror 2.0.3", + "thiserror 2.0.6", "utils", "vmm-sys-util", ] @@ -856,9 +856,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.167" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libloading" @@ -1138,7 +1138,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.3", + "thiserror 2.0.6", "utils", "vmm-sys-util", ] @@ -1180,15 +1180,15 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1216,7 +1216,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "utils", "vmm-sys-util", ] @@ -1296,7 +1296,7 @@ dependencies = [ "libc", "log-instrument", "semver", - "thiserror 2.0.3", + "thiserror 2.0.6", "utils", "vmm", "vmm-sys-util", @@ -1336,11 +1336,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.6", ] [[package]] @@ -1356,9 +1356,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" dependencies = [ "proc-macro2", "quote", @@ -1432,9 +1432,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-xid" @@ -1499,7 +1499,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "vm-memory", "vmm-sys-util", ] @@ -1613,7 +1613,7 @@ dependencies = [ "serde", "serde_json", "slab", - "thiserror 2.0.3", + "thiserror 2.0.6", "timerfd", "userfaultfd", "utils", @@ -1623,7 +1623,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.11", + "zerocopy 0.8.13", ] [[package]] @@ -1800,11 +1800,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.11" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce3b5629d87654b53a49002acc2ce64aa5aa7255f5c718374a37ac7fd98c218" +checksum = "67914ab451f3bfd2e69e5e9d2ef3858484e7074d63f204fd166ec391b54de21d" dependencies = [ - "zerocopy-derive 0.8.11", + "zerocopy-derive 0.8.13", ] [[package]] @@ -1820,9 +1820,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.11" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a82c26c3986af2623ec9eb890ff4aa19c006e30a1133dc9bd1830ec1612e20" +checksum = "7988d73a4303ca289df03316bc490e934accf371af6bc745393cf3c2c5c4f25d" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 39b8f1574c9..87b2e7ed626 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -8,9 +8,9 @@ license = "Apache-2.0" [dependencies] displaydoc = "0.2.5" -thiserror = "2.0.3" +thiserror = "2.0.6" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.11", features = ["derive"] } +zerocopy = { version = "0.8.13", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index e22cd6a1eae..e112095226a 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -10,7 +10,7 @@ name = "clippy-tracing" bench = false [dependencies] -clap = { version = "4.5.21", features = ["derive"] } +clap = { version = "4.5.23", features = ["derive"] } itertools = "0.13.0" proc-macro2 = { version = "1.0.92", features = ["span-locations"] } quote = "1.0.37" diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index eb7c16472e0..0e665f8f521 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,13 +10,13 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.21", features = ["derive", "string"] } +clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" -thiserror = "2.0.3" +thiserror = "2.0.6" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 6cd237aaabe..ec20799e798 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -18,7 +18,7 @@ bench = false [dependencies] displaydoc = "0.2.5" event-manager = "0.4.0" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } @@ -26,15 +26,15 @@ seccompiler = { path = "../seccompiler" } serde = { version = "1.0.215", features = ["derive"] } serde_derive = "1.0.136" serde_json = "1.0.133" -thiserror = "2.0.3" +thiserror = "2.0.6" timerfd = "1.6.0" utils = { path = "../utils" } vmm = { path = "../vmm" } vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } [dev-dependencies] -cargo_toml = "0.20.5" -libc = "0.2.167" +cargo_toml = "0.21.0" +libc = "0.2.168" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index ef9162027be..f486944ac3b 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -12,11 +12,11 @@ name = "jailer" bench = false [dependencies] -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } nix = { version = "0.29.0", default-features = false, features = ["dir"] } regex = { version = "1.11.1", default-features = false, features = ["std"] } -thiserror = "2.0.3" +thiserror = "2.0.6" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index 1615260b03b..8409430340e 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -11,9 +11,9 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.3" +thiserror = "2.0.6" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 90477e3e025..93be7082920 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -18,11 +18,11 @@ bench = false [dependencies] bincode = "1.2.1" displaydoc = "0.2.5" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" -thiserror = "2.0.3" +thiserror = "2.0.6" utils = { path = "../utils" } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 91bbebf7f27..0e42cd11859 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,14 +10,14 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.21", features = ["derive", "string"] } +clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } semver = "1.0.23" -thiserror = "2.0.3" +thiserror = "2.0.6" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index 7f57e5081a0..923155c265e 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -11,10 +11,10 @@ bench = false [dependencies] derive_more = { version = "1.0.0", default-features = false, features = ["from"] } displaydoc = "0.2.5" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } -thiserror = "2.0.3" +thiserror = "2.0.6" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vmm-sys-util = "0.12.1" diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 283a47a5982..31acb7362a8 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -25,7 +25,7 @@ gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.19.0" lazy_static = "1.5.0" -libc = "0.2.167" +libc = "0.2.168" linux-loader = "0.13.0" log = { version = "0.4.22", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } @@ -37,7 +37,7 @@ semver = { version = "1.0.23", features = ["serde"] } serde = { version = "1.0.215", features = ["derive", "rc"] } serde_json = "1.0.133" slab = "0.4.7" -thiserror = "2.0.3" +thiserror = "2.0.6" timerfd = "1.5.0" userfaultfd = "0.8.1" utils = { path = "../utils" } @@ -46,7 +46,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.11" } +zerocopy = { version = "0.8.13" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From f90cc5c19e075cb11bda5f8d237bf22636e4ef1d Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 16:41:57 +0000 Subject: [PATCH 30/78] chore: update deny.toml the unicode-ident crates changed license from Unicode-DFS-2016 to Unicode-3.0 Signed-off-by: Patrick Roy --- deny.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index 5cd62715860..be3a1040463 100644 --- a/deny.toml +++ b/deny.toml @@ -5,7 +5,7 @@ allow = [ "Apache-2.0", "BSD-3-Clause", "ISC", - "Unicode-DFS-2016", + "Unicode-3.0", "OpenSSL" ] From 68b7c9923456aa469042b53bc797afaf9d82b765 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 25 Nov 2024 16:54:29 +0000 Subject: [PATCH 31/78] chore(devctr): update rust version to 1.83 Update Rust to 1.83 version Signed-off-by: Egor Lazarchuk Signed-off-by: Patrick Roy --- rust-toolchain.toml | 2 +- tools/devctr/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index ff74857c81d..af10d0da481 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -11,7 +11,7 @@ # allowlisted using a toolchain that requires it, causing the A/B-test to # always fail. [toolchain] -channel = "1.79.0" +channel = "1.83.0" targets = ["x86_64-unknown-linux-musl", "aarch64-unknown-linux-musl"] profile = "minimal" diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index f0c7c36f759..bebf1309e00 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -4,7 +4,7 @@ FROM public.ecr.aws/lts/ubuntu:24.04 # The Rust toolchain layer will get updated most frequently, but we could keep the system # dependencies layer intact for much longer. -ARG RUST_TOOLCHAIN="1.79.0" +ARG RUST_TOOLCHAIN="1.83.0" ARG TMP_BUILD_DIR=/tmp/build ARG DEBIAN_FRONTEND=noninteractive ARG PIP_BREAK_SYSTEM_PACKAGES=1 From c5e5794e414a6a377fae64a56ec6f956bcdeda9c Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 28 Nov 2024 21:52:20 +0000 Subject: [PATCH 32/78] chore(clippy): update code with new lints From: Egor Lazarchuk With a new Rust version, new Clippy entered our repository. This commit aligns our codebase with guidance provided by new lints. Also remove a `deny(clippy::pedantic)`, because I'm not fixing those. Signed-off-by: Egor Lazarchuk Co-authored-by: Patrick Roy Signed-off-by: Patrick Roy --- Cargo.toml | 1 + src/acpi-tables/src/aml.rs | 30 +++++++++---------- src/clippy-tracing/src/main.rs | 2 -- .../src/api_server/request/actions.rs | 3 +- .../src/api_server/request/boot_source.rs | 3 +- .../src/api_server/request/drive.rs | 6 ++-- .../src/api_server/request/logger.rs | 3 +- .../request/machine_configuration.rs | 6 ++-- .../src/api_server/request/metrics.rs | 3 +- .../src/api_server/request/mmds.rs | 9 ++---- src/firecracker/src/api_server/request/net.rs | 6 ++-- .../src/api_server/request/vsock.rs | 3 +- src/seccompiler/src/backend.rs | 2 +- src/seccompiler/src/compiler.rs | 4 +-- src/vmm/benches/queue.rs | 4 +-- src/vmm/src/acpi/mod.rs | 4 +-- src/vmm/src/arch/x86_64/layout.rs | 2 +- src/vmm/src/builder.rs | 2 +- src/vmm/src/cpu_config/mod.rs | 2 +- src/vmm/src/cpu_config/templates.rs | 2 +- src/vmm/src/cpu_config/test_utils.rs | 2 +- src/vmm/src/devices/legacy/serial.rs | 2 +- src/vmm/src/devices/virtio/balloon/metrics.rs | 2 +- .../devices/virtio/block/virtio/metrics.rs | 3 +- .../devices/virtio/block/virtio/request.rs | 2 +- src/vmm/src/devices/virtio/iovec.rs | 12 ++++---- src/vmm/src/devices/virtio/mmio.rs | 4 +-- src/vmm/src/devices/virtio/net/device.rs | 3 +- src/vmm/src/devices/virtio/net/metrics.rs | 3 +- src/vmm/src/devices/virtio/net/tap.rs | 2 +- src/vmm/src/devices/virtio/queue.rs | 13 ++++---- src/vmm/src/devices/virtio/rng/device.rs | 3 +- src/vmm/src/devices/virtio/rng/metrics.rs | 2 +- src/vmm/src/devices/virtio/test_utils.rs | 2 +- .../src/devices/virtio/vhost_user_metrics.rs | 3 +- .../src/devices/virtio/vsock/event_handler.rs | 2 +- src/vmm/src/devices/virtio/vsock/metrics.rs | 2 +- src/vmm/src/devices/virtio/vsock/packet.rs | 1 + .../src/devices/virtio/vsock/test_utils.rs | 2 +- .../src/devices/virtio/vsock/unix/muxer.rs | 11 +++---- .../devices/virtio/vsock/unix/muxer_rxq.rs | 1 + src/vmm/src/dumbo/pdu/arp.rs | 4 +-- src/vmm/src/dumbo/pdu/bytes.rs | 16 +++++----- src/vmm/src/dumbo/pdu/ethernet.rs | 4 +-- src/vmm/src/dumbo/pdu/ipv4.rs | 4 +-- src/vmm/src/dumbo/pdu/mod.rs | 3 +- src/vmm/src/dumbo/pdu/tcp.rs | 4 +-- src/vmm/src/dumbo/pdu/udp.rs | 4 +-- src/vmm/src/dumbo/tcp/endpoint.rs | 3 +- src/vmm/src/io_uring/mod.rs | 10 +++---- src/vmm/src/lib.rs | 9 ++---- src/vmm/src/logger/metrics.rs | 8 ++--- src/vmm/src/mmds/data_store.rs | 2 +- src/vmm/src/rate_limiter/mod.rs | 16 +++++----- src/vmm/src/resources.rs | 4 +-- src/vmm/src/rpc_interface.rs | 8 ++--- src/vmm/src/vmm_config/boot_source.rs | 2 +- src/vmm/src/vmm_config/net.rs | 6 +--- src/vmm/src/vstate/vcpu/mod.rs | 2 +- 59 files changed, 128 insertions(+), 155 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 914c4cdc87c..4f8cc3f5eb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ resolver = "2" [workspace.lints.rust] missing_debug_implementations = "warn" +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(kani)'] } [workspace.lints.clippy] ptr_as_ptr = "warn" diff --git a/src/acpi-tables/src/aml.rs b/src/acpi-tables/src/aml.rs index 8f839c258e0..69feb5b004f 100644 --- a/src/acpi-tables/src/aml.rs +++ b/src/acpi-tables/src/aml.rs @@ -180,7 +180,7 @@ pub struct Package<'a> { children: Vec<&'a dyn Aml>, } -impl<'a> Aml for Package<'a> { +impl Aml for Package<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = vec![self.children.len().try_into().unwrap()]; for child in &self.children { @@ -336,7 +336,7 @@ pub struct ResourceTemplate<'a> { children: Vec<&'a dyn Aml>, } -impl<'a> Aml for ResourceTemplate<'a> { +impl Aml for ResourceTemplate<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); // Add buffer data @@ -607,7 +607,7 @@ pub struct Device<'a> { children: Vec<&'a dyn Aml>, } -impl<'a> Aml for Device<'a> { +impl Aml for Device<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.path.append_aml_bytes(&mut tmp)?; @@ -637,7 +637,7 @@ pub struct Scope<'a> { children: Vec<&'a dyn Aml>, } -impl<'a> Aml for Scope<'a> { +impl Aml for Scope<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.path.append_aml_bytes(&mut tmp)?; @@ -678,7 +678,7 @@ impl<'a> Method<'a> { } } -impl<'a> Aml for Method<'a> { +impl Aml for Method<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.path.append_aml_bytes(&mut tmp)?; @@ -707,7 +707,7 @@ impl<'a> Return<'a> { } } -impl<'a> Aml for Return<'a> { +impl Aml for Return<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0xa4); // ReturnOp self.value.append_aml_bytes(bytes)?; @@ -850,7 +850,7 @@ impl<'a> If<'a> { } } -impl<'a> Aml for If<'a> { +impl Aml for If<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.predicate.append_aml_bytes(&mut tmp)?; @@ -878,7 +878,7 @@ impl<'a> Equal<'a> { } } -impl<'a> Aml for Equal<'a> { +impl Aml for Equal<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x93); // LEqualOp self.left.append_aml_bytes(bytes)?; @@ -898,7 +898,7 @@ impl<'a> LessThan<'a> { } } -impl<'a> Aml for LessThan<'a> { +impl Aml for LessThan<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x95); // LLessOp self.left.append_aml_bytes(bytes)?; @@ -942,7 +942,7 @@ impl<'a> Store<'a> { } } -impl<'a> Aml for Store<'a> { +impl Aml for Store<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x70); // StoreOp self.value.append_aml_bytes(bytes)?; @@ -1023,7 +1023,7 @@ impl<'a> Notify<'a> { } } -impl<'a> Aml for Notify<'a> { +impl Aml for Notify<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x86); // NotifyOp self.object.append_aml_bytes(bytes)?; @@ -1046,7 +1046,7 @@ impl<'a> While<'a> { } } -impl<'a> Aml for While<'a> { +impl Aml for While<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.predicate.append_aml_bytes(&mut tmp)?; @@ -1116,7 +1116,7 @@ impl<'a> MethodCall<'a> { } } -impl<'a> Aml for MethodCall<'a> { +impl Aml for MethodCall<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { self.name.append_aml_bytes(bytes)?; for arg in self.args.iter() { @@ -1169,7 +1169,7 @@ impl<'a, T> CreateField<'a, T> { } } -impl<'a> Aml for CreateField<'a, u64> { +impl Aml for CreateField<'_, u64> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x8f); // CreateQWordFieldOp self.buffer.append_aml_bytes(bytes)?; @@ -1178,7 +1178,7 @@ impl<'a> Aml for CreateField<'a, u64> { } } -impl<'a> Aml for CreateField<'a, u32> { +impl Aml for CreateField<'_, u32> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x8a); // CreateDWordFieldOp self.buffer.append_aml_bytes(bytes)?; diff --git a/src/clippy-tracing/src/main.rs b/src/clippy-tracing/src/main.rs index 61de2eee148..f39382f1324 100644 --- a/src/clippy-tracing/src/main.rs +++ b/src/clippy-tracing/src/main.rs @@ -1,8 +1,6 @@ // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#![warn(clippy::pedantic)] - //! A tool to add, remove and check for `tracing::instrument` in large projects where it is //! infeasible to manually add it to thousands of functions. diff --git a/src/firecracker/src/api_server/request/actions.rs b/src/firecracker/src/api_server/request/actions.rs index 7d7974571a9..a3b3f3f3a88 100644 --- a/src/firecracker/src/api_server/request/actions.rs +++ b/src/firecracker/src/api_server/request/actions.rs @@ -30,9 +30,8 @@ struct ActionBody { pub(crate) fn parse_put_actions(body: &Body) -> Result { METRICS.put_api_requests.actions_count.inc(); - let action_body = serde_json::from_slice::(body.raw()).map_err(|err| { + let action_body = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.actions_fails.inc(); - err })?; match action_body.action_type { diff --git a/src/firecracker/src/api_server/request/boot_source.rs b/src/firecracker/src/api_server/request/boot_source.rs index 16f3c1b5499..10e16148461 100644 --- a/src/firecracker/src/api_server/request/boot_source.rs +++ b/src/firecracker/src/api_server/request/boot_source.rs @@ -11,9 +11,8 @@ use super::Body; pub(crate) fn parse_put_boot_source(body: &Body) -> Result { METRICS.put_api_requests.boot_source_count.inc(); Ok(ParsedRequest::new_sync(VmmAction::ConfigureBootSource( - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.boot_source_fails.inc(); - err })?, ))) } diff --git a/src/firecracker/src/api_server/request/drive.rs b/src/firecracker/src/api_server/request/drive.rs index a74d3be69ff..4b2548b53c8 100644 --- a/src/firecracker/src/api_server/request/drive.rs +++ b/src/firecracker/src/api_server/request/drive.rs @@ -20,9 +20,8 @@ pub(crate) fn parse_put_drive( return Err(RequestError::EmptyID); }; - let device_cfg = serde_json::from_slice::(body.raw()).map_err(|err| { + let device_cfg = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.drive_fails.inc(); - err })?; if id != device_cfg.drive_id { @@ -51,9 +50,8 @@ pub(crate) fn parse_patch_drive( }; let block_device_update_cfg: BlockDeviceUpdateConfig = - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.patch_api_requests.drive_fails.inc(); - err })?; if id != block_device_update_cfg.drive_id { diff --git a/src/firecracker/src/api_server/request/logger.rs b/src/firecracker/src/api_server/request/logger.rs index 6355bf48beb..cda125ac71c 100644 --- a/src/firecracker/src/api_server/request/logger.rs +++ b/src/firecracker/src/api_server/request/logger.rs @@ -10,9 +10,8 @@ use super::Body; pub(crate) fn parse_put_logger(body: &Body) -> Result { METRICS.put_api_requests.logger_count.inc(); let res = serde_json::from_slice::(body.raw()); - let config = res.map_err(|err| { + let config = res.inspect_err(|_| { METRICS.put_api_requests.logger_fails.inc(); - err })?; Ok(ParsedRequest::new_sync(VmmAction::ConfigureLogger(config))) } diff --git a/src/firecracker/src/api_server/request/machine_configuration.rs b/src/firecracker/src/api_server/request/machine_configuration.rs index 344d9095b77..871bbda5ecc 100644 --- a/src/firecracker/src/api_server/request/machine_configuration.rs +++ b/src/firecracker/src/api_server/request/machine_configuration.rs @@ -15,9 +15,8 @@ pub(crate) fn parse_get_machine_config() -> Result pub(crate) fn parse_put_machine_config(body: &Body) -> Result { METRICS.put_api_requests.machine_cfg_count.inc(); - let config = serde_json::from_slice::(body.raw()).map_err(|err| { + let config = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.machine_cfg_fails.inc(); - err })?; // Check for the presence of deprecated `cpu_template` field. @@ -44,9 +43,8 @@ pub(crate) fn parse_put_machine_config(body: &Body) -> Result Result { METRICS.patch_api_requests.machine_cfg_count.inc(); let config_update = - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.patch_api_requests.machine_cfg_fails.inc(); - err })?; if config_update.is_empty() { diff --git a/src/firecracker/src/api_server/request/metrics.rs b/src/firecracker/src/api_server/request/metrics.rs index e6b361a49c1..054ece19422 100644 --- a/src/firecracker/src/api_server/request/metrics.rs +++ b/src/firecracker/src/api_server/request/metrics.rs @@ -11,9 +11,8 @@ use super::Body; pub(crate) fn parse_put_metrics(body: &Body) -> Result { METRICS.put_api_requests.metrics_count.inc(); Ok(ParsedRequest::new_sync(VmmAction::ConfigureMetrics( - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.metrics_fails.inc(); - err })?, ))) } diff --git a/src/firecracker/src/api_server/request/mmds.rs b/src/firecracker/src/api_server/request/mmds.rs index ced0a671e9b..2bc96512d3c 100644 --- a/src/firecracker/src/api_server/request/mmds.rs +++ b/src/firecracker/src/api_server/request/mmds.rs @@ -16,9 +16,8 @@ pub(crate) fn parse_get_mmds() -> Result { } fn parse_put_mmds_config(body: &Body) -> Result { - let config: MmdsConfig = serde_json::from_slice(body.raw()).map_err(|err| { + let config: MmdsConfig = serde_json::from_slice(body.raw()).inspect_err(|_| { METRICS.put_api_requests.mmds_fails.inc(); - err })?; // Construct the `ParsedRequest` object. let version = config.version; @@ -42,9 +41,8 @@ pub(crate) fn parse_put_mmds( METRICS.put_api_requests.mmds_count.inc(); match path_second_token { None => Ok(ParsedRequest::new_sync(VmmAction::PutMMDS( - serde_json::from_slice(body.raw()).map_err(|err| { + serde_json::from_slice(body.raw()).inspect_err(|_| { METRICS.put_api_requests.mmds_fails.inc(); - err })?, ))), Some("config") => parse_put_mmds_config(body), @@ -61,9 +59,8 @@ pub(crate) fn parse_put_mmds( pub(crate) fn parse_patch_mmds(body: &Body) -> Result { METRICS.patch_api_requests.mmds_count.inc(); Ok(ParsedRequest::new_sync(VmmAction::PatchMMDS( - serde_json::from_slice(body.raw()).map_err(|err| { + serde_json::from_slice(body.raw()).inspect_err(|_| { METRICS.patch_api_requests.mmds_fails.inc(); - err })?, ))) } diff --git a/src/firecracker/src/api_server/request/net.rs b/src/firecracker/src/api_server/request/net.rs index 0ab5377b0a1..5fced98635c 100644 --- a/src/firecracker/src/api_server/request/net.rs +++ b/src/firecracker/src/api_server/request/net.rs @@ -20,9 +20,8 @@ pub(crate) fn parse_put_net( return Err(RequestError::EmptyID); }; - let netif = serde_json::from_slice::(body.raw()).map_err(|err| { + let netif = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.network_fails.inc(); - err })?; if id != netif.iface_id.as_str() { METRICS.put_api_requests.network_fails.inc(); @@ -53,9 +52,8 @@ pub(crate) fn parse_patch_net( }; let netif = - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.patch_api_requests.network_fails.inc(); - err })?; if id != netif.iface_id { METRICS.patch_api_requests.network_count.inc(); diff --git a/src/firecracker/src/api_server/request/vsock.rs b/src/firecracker/src/api_server/request/vsock.rs index 67bf7b0a985..acf129d456c 100644 --- a/src/firecracker/src/api_server/request/vsock.rs +++ b/src/firecracker/src/api_server/request/vsock.rs @@ -10,9 +10,8 @@ use super::Body; pub(crate) fn parse_put_vsock(body: &Body) -> Result { METRICS.put_api_requests.vsock_count.inc(); - let vsock_cfg = serde_json::from_slice::(body.raw()).map_err(|err| { + let vsock_cfg = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.vsock_fails.inc(); - err })?; // Check for the presence of deprecated `vsock_id` field. diff --git a/src/seccompiler/src/backend.rs b/src/seccompiler/src/backend.rs index cc4b1d4c9e3..22de1cee501 100644 --- a/src/seccompiler/src/backend.rs +++ b/src/seccompiler/src/backend.rs @@ -868,7 +868,7 @@ mod tests { } impl SeccompCondition { - // Creates a new `SeccompCondition`. + /// Creates a new `SeccompCondition`. pub fn new( arg_number: u8, arg_len: SeccompCmpArgLen, diff --git a/src/seccompiler/src/compiler.rs b/src/seccompiler/src/compiler.rs index 73ff9f706ca..9194bc7e5bd 100644 --- a/src/seccompiler/src/compiler.rs +++ b/src/seccompiler/src/compiler.rs @@ -258,7 +258,7 @@ mod tests { }; impl Filter { - pub fn new( + fn new( default_action: SeccompAction, filter_action: SeccompAction, filter: Vec, @@ -272,7 +272,7 @@ mod tests { } impl SyscallRule { - pub fn new(syscall: String, conditions: Option>) -> SyscallRule { + fn new(syscall: String, conditions: Option>) -> SyscallRule { SyscallRule { syscall, conditions, diff --git a/src/vmm/benches/queue.rs b/src/vmm/benches/queue.rs index faff57b2ebf..1d19bcd3973 100644 --- a/src/vmm/benches/queue.rs +++ b/src/vmm/benches/queue.rs @@ -88,7 +88,7 @@ pub fn queue_benchmark(c: &mut Criterion) { for i in 0_u16..16_u16 { let index = std::hint::black_box(i); let len = std::hint::black_box(i + 1); - _ = queue.add_used(index as u16, len as u32); + _ = queue.add_used(index, len as u32); } }) }); @@ -100,7 +100,7 @@ pub fn queue_benchmark(c: &mut Criterion) { for i in 0_u16..256_u16 { let index = std::hint::black_box(i); let len = std::hint::black_box(i + 1); - _ = queue.add_used(index as u16, len as u32); + _ = queue.add_used(index, len as u32); } }) }); diff --git a/src/vmm/src/acpi/mod.rs b/src/vmm/src/acpi/mod.rs index 247c832e665..9542fad3902 100644 --- a/src/vmm/src/acpi/mod.rs +++ b/src/vmm/src/acpi/mod.rs @@ -48,7 +48,7 @@ struct AcpiTableWriter<'a> { resource_allocator: &'a mut ResourceAllocator, } -impl<'a> AcpiTableWriter<'a> { +impl AcpiTableWriter<'_> { /// Write a table in guest memory /// /// This will allocate enough space inside guest memory and write the table in the allocated @@ -181,7 +181,7 @@ pub(crate) fn create_acpi_tables( } #[cfg(test)] -pub mod tests { +mod tests { use acpi_tables::Sdt; use vm_memory::Bytes; diff --git a/src/vmm/src/arch/x86_64/layout.rs b/src/vmm/src/arch/x86_64/layout.rs index 01355b3018a..1e50bb9c235 100644 --- a/src/vmm/src/arch/x86_64/layout.rs +++ b/src/vmm/src/arch/x86_64/layout.rs @@ -5,7 +5,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. -/// Magic addresses externally used to lay out x86_64 VMs. +//! Magic addresses externally used to lay out x86_64 VMs. /// Initial stack for the boot CPU. pub const BOOT_STACK_POINTER: u64 = 0x8ff0; diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 3355633e3c8..8594da9f077 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -1023,7 +1023,7 @@ pub(crate) fn set_stdout_nonblocking() { } #[cfg(test)] -pub mod tests { +pub(crate) mod tests { use std::io::Write; use linux_loader::cmdline::Cmdline; diff --git a/src/vmm/src/cpu_config/mod.rs b/src/vmm/src/cpu_config/mod.rs index 3e438d07ef4..4c7404a14d3 100644 --- a/src/vmm/src/cpu_config/mod.rs +++ b/src/vmm/src/cpu_config/mod.rs @@ -15,4 +15,4 @@ pub mod x86_64; pub mod aarch64; #[cfg(test)] -pub mod test_utils; +pub(crate) mod test_utils; diff --git a/src/vmm/src/cpu_config/templates.rs b/src/vmm/src/cpu_config/templates.rs index 984fd8dcac2..fa883964ed8 100644 --- a/src/vmm/src/cpu_config/templates.rs +++ b/src/vmm/src/cpu_config/templates.rs @@ -83,7 +83,7 @@ impl From<&CpuTemplateType> for StaticCpuTemplate { } } -impl<'a> TryFrom<&'a [u8]> for CustomCpuTemplate { +impl TryFrom<&[u8]> for CustomCpuTemplate { type Error = serde_json::Error; fn try_from(value: &[u8]) -> Result { diff --git a/src/vmm/src/cpu_config/test_utils.rs b/src/vmm/src/cpu_config/test_utils.rs index de2e952522e..197c0c62cf6 100644 --- a/src/vmm/src/cpu_config/test_utils.rs +++ b/src/vmm/src/cpu_config/test_utils.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use crate::cpu_config::templates::CustomCpuTemplate; -// Get a static CPU template stored as a JSON file. +/// Get a static CPU template stored as a JSON file. pub fn get_json_template(filename: &str) -> CustomCpuTemplate { let json_path = [ env!("CARGO_MANIFEST_DIR"), diff --git a/src/vmm/src/devices/legacy/serial.rs b/src/vmm/src/devices/legacy/serial.rs index cd74159dbdc..278c15a4464 100644 --- a/src/vmm/src/devices/legacy/serial.rs +++ b/src/vmm/src/devices/legacy/serial.rs @@ -386,7 +386,7 @@ mod tests { ), input: None::, }; - serial.serial.raw_input(&[b'a', b'b', b'c']).unwrap(); + serial.serial.raw_input(b"abc").unwrap(); let invalid_reads_before = metrics.missed_read_count.count(); let mut v = [0x00; 2]; diff --git a/src/vmm/src/devices/virtio/balloon/metrics.rs b/src/vmm/src/devices/virtio/balloon/metrics.rs index da8f7a28520..0b438cae2d4 100644 --- a/src/vmm/src/devices/virtio/balloon/metrics.rs +++ b/src/vmm/src/devices/virtio/balloon/metrics.rs @@ -31,7 +31,7 @@ //! //! The system implements 1 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. use serde::ser::SerializeMap; use serde::{Serialize, Serializer}; diff --git a/src/vmm/src/devices/virtio/block/virtio/metrics.rs b/src/vmm/src/devices/virtio/block/virtio/metrics.rs index 69a521fde54..0abe2a58963 100644 --- a/src/vmm/src/devices/virtio/block/virtio/metrics.rs +++ b/src/vmm/src/devices/virtio/block/virtio/metrics.rs @@ -72,7 +72,8 @@ //! //! The system implements 1 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! //! We add BlockDeviceMetrics entries from block::metrics::METRICS into Block device instead of //! Block device having individual separate BlockDeviceMetrics entries because Block device is not //! accessible from signal handlers to flush metrics and block::metrics::METRICS is. diff --git a/src/vmm/src/devices/virtio/block/virtio/request.rs b/src/vmm/src/devices/virtio/block/virtio/request.rs index 4eb8d7e2efd..27df7c1d675 100644 --- a/src/vmm/src/devices/virtio/block/virtio/request.rs +++ b/src/vmm/src/devices/virtio/block/virtio/request.rs @@ -467,7 +467,7 @@ mod tests { assert_eq!(RequestType::from(42), RequestType::Unsupported(42)); } - impl<'a, 'b> RequestDescriptorChain<'a, 'b> { + impl RequestDescriptorChain<'_, '_> { fn check_parse_err(&self, _e: VirtioBlockError) { let mut q = self.driver_queue.create_queue(); let memory = self.driver_queue.memory(); diff --git a/src/vmm/src/devices/virtio/iovec.rs b/src/vmm/src/devices/virtio/iovec.rs index 2161d7273ef..9262dff661b 100644 --- a/src/vmm/src/devices/virtio/iovec.rs +++ b/src/vmm/src/devices/virtio/iovec.rs @@ -264,10 +264,11 @@ impl IoVecBufferMut { // We use get_slice instead of `get_host_address` here in order to have the whole // range of the descriptor chain checked, i.e. [addr, addr + len) is a valid memory // region in the GuestMemoryMmap. - let slice = mem.get_slice(desc.addr, desc.len as usize).map_err(|err| { - self.vecs.pop_back(nr_iovecs); - err - })?; + let slice = mem + .get_slice(desc.addr, desc.len as usize) + .inspect_err(|_| { + self.vecs.pop_back(nr_iovecs); + })?; // We need to mark the area of guest memory that will be mutated through this // IoVecBufferMut as dirty ahead of time, as we loose access to all // vm-memory related information after converting down to iovecs. @@ -288,9 +289,8 @@ impl IoVecBufferMut { length = length .checked_add(desc.len) .ok_or(IoVecError::OverflowedDescriptor) - .map_err(|err| { + .inspect_err(|_| { self.vecs.pop_back(nr_iovecs); - err })?; next_descriptor = desc.next_descriptor(); diff --git a/src/vmm/src/devices/virtio/mmio.rs b/src/vmm/src/devices/virtio/mmio.rs index f734058c5b1..63d7a80d84d 100644 --- a/src/vmm/src/devices/virtio/mmio.rs +++ b/src/vmm/src/devices/virtio/mmio.rs @@ -38,9 +38,9 @@ const MMIO_VERSION: u32 = 2; /// /// 1. Mmio reads and writes must be sent to this device at what is referred to here as MMIO base. /// 1. `Mmio::queue_evts` must be installed at `virtio::NOTIFY_REG_OFFSET` offset from the MMIO -/// base. Each event in the array must be signaled if the index is written at that offset. +/// base. Each event in the array must be signaled if the index is written at that offset. /// 1. `Mmio::interrupt_evt` must signal an interrupt that the guest driver is listening to when it -/// is written to. +/// is written to. /// /// Typically one page (4096 bytes) of MMIO address space is sufficient to handle this transport /// and inner virtio device. diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 818fed86a30..a17c25d7248 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -514,10 +514,9 @@ impl Net { NetError::VnetHeaderMissing })?; - let headers = frame_bytes_from_buf(&headers[..header_len]).map_err(|e| { + let headers = frame_bytes_from_buf(&headers[..header_len]).inspect_err(|_| { error!("VNET headers missing in TX frame"); net_metrics.tx_malformed_frames.inc(); - e })?; if let Some(ns) = mmds_ns { diff --git a/src/vmm/src/devices/virtio/net/metrics.rs b/src/vmm/src/devices/virtio/net/metrics.rs index dfdf69702a7..60e03f224de 100644 --- a/src/vmm/src/devices/virtio/net/metrics.rs +++ b/src/vmm/src/devices/virtio/net/metrics.rs @@ -75,7 +75,8 @@ //! //! The system implements 1 types of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! //! We use net::metrics::METRICS instead of adding an entry of NetDeviceMetrics //! in Net so that metrics are accessible to be flushed even from signal handlers. diff --git a/src/vmm/src/devices/virtio/net/tap.rs b/src/vmm/src/devices/virtio/net/tap.rs index 32c665e1c31..0f5b7e2d788 100644 --- a/src/vmm/src/devices/virtio/net/tap.rs +++ b/src/vmm/src/devices/virtio/net/tap.rs @@ -122,7 +122,7 @@ impl Tap { // string and verify the result. let fd = unsafe { libc::open( - b"/dev/net/tun\0".as_ptr().cast::(), + c"/dev/net/tun".as_ptr(), libc::O_RDWR | libc::O_NONBLOCK | libc::O_CLOEXEC, ) }; diff --git a/src/vmm/src/devices/virtio/queue.rs b/src/vmm/src/devices/virtio/queue.rs index 39ccef1f1ee..7c2c78d2407 100644 --- a/src/vmm/src/devices/virtio/queue.rs +++ b/src/vmm/src/devices/virtio/queue.rs @@ -172,9 +172,8 @@ impl Iterator for DescriptorIterator { type Item = DescriptorChain; fn next(&mut self) -> Option { - self.0.take().map(|desc| { + self.0.take().inspect(|desc| { self.0 = desc.next_descriptor(); - desc }) } } @@ -560,10 +559,9 @@ impl Queue { // index is bound by the queue size let desc_index = unsafe { self.avail_ring_ring_get(usize::from(idx)) }; - DescriptorChain::checked_new(self.desc_table_ptr, self.actual_size(), desc_index).map( - |dc| { + DescriptorChain::checked_new(self.desc_table_ptr, self.actual_size(), desc_index).inspect( + |_| { self.next_avail += Wrapping(1); - dc }, ) } @@ -575,9 +573,8 @@ impl Queue { } /// Write used element into used_ring ring. - /// - [`ring_index_offset`] is an offset added to - /// the current [`self.next_used`] to obtain actual index - /// into used_ring. + /// - [`ring_index_offset`] is an offset added to the current [`self.next_used`] to obtain + /// actual index into used_ring. pub fn write_used_element( &mut self, ring_index_offset: u16, diff --git a/src/vmm/src/devices/virtio/rng/device.rs b/src/vmm/src/devices/virtio/rng/device.rs index 96513e49b26..dca25999f3e 100644 --- a/src/vmm/src/devices/virtio/rng/device.rs +++ b/src/vmm/src/devices/virtio/rng/device.rs @@ -119,9 +119,8 @@ impl Entropy { } let mut rand_bytes = vec![0; self.buffer.len() as usize]; - rand::fill(&mut rand_bytes).map_err(|err| { + rand::fill(&mut rand_bytes).inspect_err(|_| { METRICS.host_rng_fails.inc(); - err })?; // It is ok to unwrap here. We are writing `iovec.len()` bytes at offset 0. diff --git a/src/vmm/src/devices/virtio/rng/metrics.rs b/src/vmm/src/devices/virtio/rng/metrics.rs index eb1dcbfacae..e02f5ce8cc4 100644 --- a/src/vmm/src/devices/virtio/rng/metrics.rs +++ b/src/vmm/src/devices/virtio/rng/metrics.rs @@ -31,7 +31,7 @@ //! //! The system implements 1 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. use serde::ser::SerializeMap; use serde::{Serialize, Serializer}; diff --git a/src/vmm/src/devices/virtio/test_utils.rs b/src/vmm/src/devices/virtio/test_utils.rs index 9bb66db82ae..aa1ede08e58 100644 --- a/src/vmm/src/devices/virtio/test_utils.rs +++ b/src/vmm/src/devices/virtio/test_utils.rs @@ -377,7 +377,7 @@ pub(crate) mod test { const QUEUE_SIZE: u16 = 16; // Helper function to create a set of Virtqueues for the device - fn create_virtqueues(mem: &'a GuestMemoryMmap, num_queues: usize) -> Vec { + fn create_virtqueues(mem: &'a GuestMemoryMmap, num_queues: usize) -> Vec> { (0..num_queues) .scan(GuestAddress(0), |next_addr, _| { let vqueue = VirtQueue::new(*next_addr, mem, Self::QUEUE_SIZE); diff --git a/src/vmm/src/devices/virtio/vhost_user_metrics.rs b/src/vmm/src/devices/virtio/vhost_user_metrics.rs index 73b41e6a86c..0a3c8cd3a6a 100644 --- a/src/vmm/src/devices/virtio/vhost_user_metrics.rs +++ b/src/vmm/src/devices/virtio/vhost_user_metrics.rs @@ -64,9 +64,10 @@ //! //! The system implements 2 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times activating a device failed). These metrics are reset upon flush. +//! (i.e the number of times activating a device failed). These metrics are reset upon flush. //! * Shared Store Metrics (SharedStoreMetrics) - are targeted at keeping a persistent value, it is //! `not` intended to act as a counter (i.e for measure the process start up time for example). +//! //! We add VhostUserDeviceMetrics entries from vhost_user_metrics::METRICS into vhost_user device //! instead of vhost_user device having individual separate VhostUserDeviceMetrics entries because //! vhost_user device is not accessible from signal handlers to flush metrics and diff --git a/src/vmm/src/devices/virtio/vsock/event_handler.rs b/src/vmm/src/devices/virtio/vsock/event_handler.rs index 40e75d1a9f5..59cf3fe0103 100755 --- a/src/vmm/src/devices/virtio/vsock/event_handler.rs +++ b/src/vmm/src/devices/virtio/vsock/event_handler.rs @@ -9,7 +9,7 @@ use std::fmt::Debug; /// The vsock object implements the runtime logic of our vsock device: /// 1. Respond to TX queue events by wrapping virtio buffers into `VsockPacket`s, then sending -/// those packets to the `VsockBackend`; +/// those packets to the `VsockBackend`; /// 2. Forward backend FD event notifications to the `VsockBackend`; /// 3. Fetch incoming packets from the `VsockBackend` and place them into the virtio RX queue; /// 4. Whenever we have processed some virtio buffers (either TX or RX), let the driver know by diff --git a/src/vmm/src/devices/virtio/vsock/metrics.rs b/src/vmm/src/devices/virtio/vsock/metrics.rs index 5307302f5ca..d626d5dca34 100644 --- a/src/vmm/src/devices/virtio/vsock/metrics.rs +++ b/src/vmm/src/devices/virtio/vsock/metrics.rs @@ -34,7 +34,7 @@ //! //! The system implements 1 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. use serde::ser::SerializeMap; use serde::{Serialize, Serializer}; diff --git a/src/vmm/src/devices/virtio/vsock/packet.rs b/src/vmm/src/devices/virtio/vsock/packet.rs index 213b5bb2b34..f19723d25cb 100644 --- a/src/vmm/src/devices/virtio/vsock/packet.rs +++ b/src/vmm/src/devices/virtio/vsock/packet.rs @@ -7,6 +7,7 @@ //! virtio queue: //! - the packet header; and //! - the packet data/buffer. +//! //! There is a 1:1 relation between descriptor chains and packets: the first (chain head) holds //! the header, and an optional second descriptor holds the data. The second descriptor is only //! present for data packets (VSOCK_OP_RW). diff --git a/src/vmm/src/devices/virtio/vsock/test_utils.rs b/src/vmm/src/devices/virtio/vsock/test_utils.rs index 4a5fdb2c941..804f0442559 100644 --- a/src/vmm/src/devices/virtio/vsock/test_utils.rs +++ b/src/vmm/src/devices/virtio/vsock/test_utils.rs @@ -190,7 +190,7 @@ pub struct EventHandlerContext<'a> { pub guest_evvq: GuestQ<'a>, } -impl<'a> EventHandlerContext<'a> { +impl EventHandlerContext<'_> { pub fn mock_activate(&mut self, mem: GuestMemoryMmap) { // Artificially activate the device. self.device.activate(mem).unwrap(); diff --git a/src/vmm/src/devices/virtio/vsock/unix/muxer.rs b/src/vmm/src/devices/virtio/vsock/unix/muxer.rs index 4d4b1996237..84273f45aba 100644 --- a/src/vmm/src/devices/virtio/vsock/unix/muxer.rs +++ b/src/vmm/src/devices/virtio/vsock/unix/muxer.rs @@ -24,11 +24,12 @@ /// destination port to which it wants to connect); /// 3. Some event was triggered for a connected Unix socket, that belongs to a /// `VsockConnection`. -/// The muxer gets notified about all of these events, because, as a `VsockEpollListener` -/// implementor, it gets to register a nested epoll FD into the main VMM epolling loop. All -/// other pollable FDs are then registered under this nested epoll FD. -/// To route all these events to their handlers, the muxer uses another `HashMap` object, -/// mapping `RawFd`s to `EpollListener`s. +/// +/// The muxer gets notified about all of these events, because, as a `VsockEpollListener` +/// implementor, it gets to register a nested epoll FD into the main VMM epolling loop. All +/// other pollable FDs are then registered under this nested epoll FD. +/// To route all these events to their handlers, the muxer uses another `HashMap` object, +/// mapping `RawFd`s to `EpollListener`s. use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::io::Read; diff --git a/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs b/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs index 8327882a3fb..77f7670af7d 100644 --- a/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs +++ b/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs @@ -67,6 +67,7 @@ impl MuxerRxQ { /// A push will fail when: /// - trying to push a connection key onto an out-of-sync, or full queue; or /// - trying to push an RST onto a queue already full of RSTs. + /// /// RSTs take precedence over connections, because connections can always be queried for /// pending RX data later. Aside from this queue, there is no other storage for RSTs, so /// failing to push one means that we have to drop the packet. diff --git a/src/vmm/src/dumbo/pdu/arp.rs b/src/vmm/src/dumbo/pdu/arp.rs index bccb32154a9..54286d281b7 100644 --- a/src/vmm/src/dumbo/pdu/arp.rs +++ b/src/vmm/src/dumbo/pdu/arp.rs @@ -71,7 +71,7 @@ pub struct EthIPv4ArpFrame<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> EthIPv4ArpFrame<'a, T> { +impl EthIPv4ArpFrame<'_, T> { /// Interprets the given bytes as an ARP frame, without doing any validity checks beforehand. /// /// # Panics @@ -184,7 +184,7 @@ impl<'a, T: NetworkBytes + Debug> EthIPv4ArpFrame<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> EthIPv4ArpFrame<'a, T> { +impl EthIPv4ArpFrame<'_, T> { #[allow(clippy::too_many_arguments)] fn write_raw( buf: T, diff --git a/src/vmm/src/dumbo/pdu/bytes.rs b/src/vmm/src/dumbo/pdu/bytes.rs index 9b87673c211..7d5e2346428 100644 --- a/src/vmm/src/dumbo/pdu/bytes.rs +++ b/src/vmm/src/dumbo/pdu/bytes.rs @@ -134,20 +134,20 @@ pub trait NetworkBytesMut: NetworkBytes + DerefMut { } } -impl<'a> NetworkBytes for &'a [u8] { +impl NetworkBytes for &[u8] { #[inline] fn shrink_unchecked(&mut self, len: usize) { *self = &self[..len]; } } -impl<'a> NetworkBytes for &'a mut [u8] { +impl NetworkBytes for &mut [u8] { #[inline] fn shrink_unchecked(&mut self, len: usize) { *self = &mut std::mem::take(self)[..len]; } } -impl<'a> NetworkBytesMut for &'a mut [u8] {} +impl NetworkBytesMut for &mut [u8] {} // This struct is used as a convenience for any type which contains a generic member implementing // NetworkBytes with a lifetime, so we don't have to also add the PhantomData member each time. We @@ -158,7 +158,7 @@ pub(super) struct InnerBytes<'a, T: 'a> { phantom: PhantomData<&'a T>, } -impl<'a, T: Debug> InnerBytes<'a, T> { +impl InnerBytes<'_, T> { /// Creates a new instance as a wrapper around `bytes`. #[inline] pub fn new(bytes: T) -> Self { @@ -169,7 +169,7 @@ impl<'a, T: Debug> InnerBytes<'a, T> { } } -impl<'a, T: Deref + Debug> Deref for InnerBytes<'a, T> { +impl + Debug> Deref for InnerBytes<'_, T> { type Target = [u8]; #[inline] @@ -178,21 +178,21 @@ impl<'a, T: Deref + Debug> Deref for InnerBytes<'a, T> { } } -impl<'a, T: DerefMut + Debug> DerefMut for InnerBytes<'a, T> { +impl + Debug> DerefMut for InnerBytes<'_, T> { #[inline] fn deref_mut(&mut self) -> &mut [u8] { self.bytes.deref_mut() } } -impl<'a, T: NetworkBytes + Debug> NetworkBytes for InnerBytes<'a, T> { +impl NetworkBytes for InnerBytes<'_, T> { #[inline] fn shrink_unchecked(&mut self, len: usize) { self.bytes.shrink_unchecked(len); } } -impl<'a, T: NetworkBytesMut + Debug> NetworkBytesMut for InnerBytes<'a, T> {} +impl NetworkBytesMut for InnerBytes<'_, T> {} #[cfg(test)] mod tests { diff --git a/src/vmm/src/dumbo/pdu/ethernet.rs b/src/vmm/src/dumbo/pdu/ethernet.rs index 8b3321ca4b8..f93a0c5d007 100644 --- a/src/vmm/src/dumbo/pdu/ethernet.rs +++ b/src/vmm/src/dumbo/pdu/ethernet.rs @@ -40,7 +40,7 @@ pub struct EthernetFrame<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> EthernetFrame<'a, T> { +impl EthernetFrame<'_, T> { /// Interprets `bytes` as an Ethernet frame without any validity checks. /// /// # Panics @@ -101,7 +101,7 @@ impl<'a, T: NetworkBytes + Debug> EthernetFrame<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> EthernetFrame<'a, T> { +impl EthernetFrame<'_, T> { /// Attempts to write an Ethernet frame using the given header fields to `buf`. fn new_with_header( buf: T, diff --git a/src/vmm/src/dumbo/pdu/ipv4.rs b/src/vmm/src/dumbo/pdu/ipv4.rs index 20d7694524e..f3da2b7b298 100644 --- a/src/vmm/src/dumbo/pdu/ipv4.rs +++ b/src/vmm/src/dumbo/pdu/ipv4.rs @@ -62,7 +62,7 @@ pub struct IPv4Packet<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> IPv4Packet<'a, T> { +impl IPv4Packet<'_, T> { /// Interpret `bytes` as an IPv4Packet without checking the validity of the header fields, and /// the length of the inner byte sequence. /// @@ -250,7 +250,7 @@ impl<'a, T: NetworkBytes + Debug> IPv4Packet<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> IPv4Packet<'a, T> { +impl IPv4Packet<'_, T> { /// Attempts to write an IPv4 packet header to `buf`, making sure there is enough space. /// /// This method returns an incomplete packet, because the size of the payload might be unknown diff --git a/src/vmm/src/dumbo/pdu/mod.rs b/src/vmm/src/dumbo/pdu/mod.rs index d700474ed02..fc6a24760a7 100644 --- a/src/vmm/src/dumbo/pdu/mod.rs +++ b/src/vmm/src/dumbo/pdu/mod.rs @@ -66,8 +66,7 @@ enum ChecksumProto { /// * `bytes` - Raw bytes of a TCP packet or a UDP datagram /// * `src_addr` - IPv4 source address /// * `dst_addr` - IPv4 destination address -/// * `protocol` - **must** be either `PROTOCOL_TCP` or `PROTOCOL_UDP` defined in -/// `ipv4` module +/// * `protocol` - **must** be either `PROTOCOL_TCP` or `PROTOCOL_UDP` defined in `ipv4` module /// /// More details about TCP checksum computation can be found [here]. /// diff --git a/src/vmm/src/dumbo/pdu/tcp.rs b/src/vmm/src/dumbo/pdu/tcp.rs index 2a884689f83..d5eade0c644 100644 --- a/src/vmm/src/dumbo/pdu/tcp.rs +++ b/src/vmm/src/dumbo/pdu/tcp.rs @@ -99,7 +99,7 @@ pub struct TcpSegment<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> TcpSegment<'a, T> { +impl TcpSegment<'_, T> { /// Returns the source port. #[inline] pub fn source_port(&self) -> u16 { @@ -314,7 +314,7 @@ impl<'a, T: NetworkBytes + Debug> TcpSegment<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> TcpSegment<'a, T> { +impl TcpSegment<'_, T> { /// Sets the source port. #[inline] pub fn set_source_port(&mut self, value: u16) -> &mut Self { diff --git a/src/vmm/src/dumbo/pdu/udp.rs b/src/vmm/src/dumbo/pdu/udp.rs index 43ad9c29cef..8acfc4509f4 100644 --- a/src/vmm/src/dumbo/pdu/udp.rs +++ b/src/vmm/src/dumbo/pdu/udp.rs @@ -46,7 +46,7 @@ pub struct UdpDatagram<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> UdpDatagram<'a, T> { +impl UdpDatagram<'_, T> { /// Interprets `bytes` as a UDP datagram without any validity checks. /// /// # Panics @@ -122,7 +122,7 @@ impl<'a, T: NetworkBytes + Debug> UdpDatagram<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> UdpDatagram<'a, T> { +impl UdpDatagram<'_, T> { /// Writes an incomplete UDP datagram, which is missing the `checksum`, `src_port` and /// `dst_port` fields. /// diff --git a/src/vmm/src/dumbo/tcp/endpoint.rs b/src/vmm/src/dumbo/tcp/endpoint.rs index 92058d83ee9..15fb10e10f9 100644 --- a/src/vmm/src/dumbo/tcp/endpoint.rs +++ b/src/vmm/src/dumbo/tcp/endpoint.rs @@ -281,9 +281,8 @@ impl Endpoint { tcp_payload_src, timestamp_cycles(), ) { - Ok(write_result) => write_result.map(|segment| { + Ok(write_result) => write_result.inspect(|segment| { self.response_seq += Wrapping(u32::from(segment.inner().payload_len())); - segment }), Err(_) => { METRICS.mmds.tx_errors.inc(); diff --git a/src/vmm/src/io_uring/mod.rs b/src/vmm/src/io_uring/mod.rs index 3466fd01aa5..f306148044c 100644 --- a/src/vmm/src/io_uring/mod.rs +++ b/src/vmm/src/io_uring/mod.rs @@ -97,8 +97,8 @@ impl IoUring { /// /// # Arguments /// - /// * `num_entries` - Requested number of entries in the ring. Will be rounded up to the - /// nearest power of two. + /// * `num_entries` - Requested number of entries in the ring. Will be rounded up to the nearest + /// power of two. /// * `files` - Files to be registered for IO. /// * `restrictions` - Vector of [`Restriction`](restriction/enum.Restriction.html)s /// * `eventfd` - Optional eventfd for receiving completion notifications. @@ -175,10 +175,9 @@ impl IoUring { } self.squeue .push(op.into_sqe(&mut self.slab)) - .map(|res| { + .inspect(|_| { // This is safe since self.num_ops < IORING_MAX_CQ_ENTRIES (65536) self.num_ops += 1; - res }) .map_err(|(sqe_err, user_data_key)| -> (IoUringError, T) { ( @@ -207,11 +206,10 @@ impl IoUring { self.cqueue .pop(&mut self.slab) .map(|maybe_cqe| { - maybe_cqe.map(|cqe| { + maybe_cqe.inspect(|_| { // This is safe since the pop-ed CQEs have been previously pushed. However // we use a saturating_sub for extra safety. self.num_ops = self.num_ops.saturating_sub(1); - cqe }) }) .map_err(IoUringError::CQueue) diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index c80f004e789..6a28e14f26b 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -368,15 +368,13 @@ impl Vmm { if let Some(stdin) = self.events_observer.as_mut() { // Set raw mode for stdin. - stdin.lock().set_raw_mode().map_err(|err| { + stdin.lock().set_raw_mode().inspect_err(|&err| { warn!("Cannot set raw mode for the terminal. {:?}", err); - err })?; // Set non blocking stdin. - stdin.lock().set_non_block(true).map_err(|err| { + stdin.lock().set_non_block(true).inspect_err(|&err| { warn!("Cannot set non block for the terminal. {:?}", err); - err })?; } @@ -906,9 +904,8 @@ impl Drop for Vmm { self.stop(self.shutdown_exit_code.unwrap_or(FcExitCode::Ok)); if let Some(observer) = self.events_observer.as_mut() { - let res = observer.lock().set_canon_mode().map_err(|err| { + let res = observer.lock().set_canon_mode().inspect_err(|&err| { warn!("Cannot set canonical mode for the terminal. {:?}", err); - err }); if let Err(err) = res { warn!("{}", VmmError::VmmObserverTeardown(err)); diff --git a/src/vmm/src/logger/metrics.rs b/src/vmm/src/logger/metrics.rs index bcde569115e..a911a53e8a9 100644 --- a/src/vmm/src/logger/metrics.rs +++ b/src/vmm/src/logger/metrics.rs @@ -46,10 +46,9 @@ //! //! The system implements 2 types of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. //! * Shared Store Metrics (SharedStoreMetrics) - are targeted at keeping a persistent value, it is -//! not -//! intended to act as a counter (i.e for measure the process start up time for example). +//! not intended to act as a counter (i.e for measure the process start up time for example). //! //! The current approach for the `SharedIncMetrics` type is to store two values (current and //! previous) and compute the delta between them each time we do a flush (i.e by serialization). @@ -58,6 +57,7 @@ //! to actual writing, so less synchronization effort is required. //! * We don't have to worry at all that much about losing some data if writing fails for a while //! (this could be a concern, I guess). +//! //! If if turns out this approach is not really what we want, it's pretty easy to resort to //! something else, while working behind the same interface. @@ -706,7 +706,7 @@ impl<'a> LatencyMetricsRecorder<'a> { } } } -impl<'a> Drop for LatencyMetricsRecorder<'a> { +impl Drop for LatencyMetricsRecorder<'_> { /// records aggregate (min/max/sum) for the given metric /// This captures delta between self.start_time and current time /// and updates min/max/sum metrics. diff --git a/src/vmm/src/mmds/data_store.rs b/src/vmm/src/mmds/data_store.rs index 1cbb2dfd088..41fe297ab06 100644 --- a/src/vmm/src/mmds/data_store.rs +++ b/src/vmm/src/mmds/data_store.rs @@ -281,7 +281,7 @@ mod tests { use super::*; impl Mmds { - pub fn get_data_str(&self) -> String { + fn get_data_str(&self) -> String { if self.data_store.is_null() { return String::from("{}"); } diff --git a/src/vmm/src/rate_limiter/mod.rs b/src/vmm/src/rate_limiter/mod.rs index b4c2a6d34ed..3ed5405bf01 100644 --- a/src/vmm/src/rate_limiter/mod.rs +++ b/src/vmm/src/rate_limiter/mod.rs @@ -328,15 +328,15 @@ impl RateLimiter { /// # Arguments /// /// * `bytes_total_capacity` - the total capacity of the `TokenType::Bytes` token bucket. - /// * `bytes_one_time_burst` - initial extra credit on top of `bytes_total_capacity`, - /// that does not replenish and which can be used for an initial burst of data. - /// * `bytes_complete_refill_time_ms` - number of milliseconds for the `TokenType::Bytes` - /// token bucket to go from zero Bytes to `bytes_total_capacity` Bytes. + /// * `bytes_one_time_burst` - initial extra credit on top of `bytes_total_capacity`, that does + /// not replenish and which can be used for an initial burst of data. + /// * `bytes_complete_refill_time_ms` - number of milliseconds for the `TokenType::Bytes` token + /// bucket to go from zero Bytes to `bytes_total_capacity` Bytes. /// * `ops_total_capacity` - the total capacity of the `TokenType::Ops` token bucket. - /// * `ops_one_time_burst` - initial extra credit on top of `ops_total_capacity`, - /// that does not replenish and which can be used for an initial burst of data. + /// * `ops_one_time_burst` - initial extra credit on top of `ops_total_capacity`, that does not + /// replenish and which can be used for an initial burst of data. /// * `ops_complete_refill_time_ms` - number of milliseconds for the `TokenType::Ops` token - /// bucket to go from zero Ops to `ops_total_capacity` Ops. + /// bucket to go from zero Ops to `ops_total_capacity` Ops. /// /// If either bytes/ops *size* or *refill_time* are **zero**, the limiter /// is **disabled** for that respective token type. @@ -794,7 +794,7 @@ pub(crate) mod tests { } // After a restore, we cannot be certain that the last_update field has the same value. - pub fn partial_eq(&self, other: &TokenBucket) -> bool { + pub(crate) fn partial_eq(&self, other: &TokenBucket) -> bool { (other.capacity() == self.capacity()) && (other.one_time_burst() == self.one_time_burst()) && (other.refill_time_ms() == self.refill_time_ms()) diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 0ad4df8aa19..0cde08a844d 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -1529,7 +1529,7 @@ mod tests { .as_cstring() .unwrap() .as_bytes_with_nul(), - [cmdline.as_bytes(), &[b'\0']].concat() + [cmdline.as_bytes(), b"\0"].concat() ); assert_ne!( boot_builder.kernel_file.metadata().unwrap().st_ino(), @@ -1554,7 +1554,7 @@ mod tests { .as_cstring() .unwrap() .as_bytes_with_nul(), - [cmdline.as_bytes(), &[b'\0']].concat() + [cmdline.as_bytes(), b"\0"].concat() ); assert_eq!( boot_source_builder.kernel_file.metadata().unwrap().st_ino(), diff --git a/src/vmm/src/rpc_interface.rs b/src/vmm/src/rpc_interface.rs index 566228fd53a..b0c95529f46 100644 --- a/src/vmm/src/rpc_interface.rs +++ b/src/vmm/src/rpc_interface.rs @@ -249,7 +249,7 @@ pub struct PrebootApiController<'a> { } // TODO Remove when `EventManager` implements `std::fmt::Debug`. -impl<'a> fmt::Debug for PrebootApiController<'a> { +impl fmt::Debug for PrebootApiController<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PrebootApiController") .field("seccomp_filters", &self.seccomp_filters) @@ -572,20 +572,18 @@ impl<'a> PrebootApiController<'a> { load_params, self.vm_resources, ) - .map_err(|err| { + .inspect_err(|_| { // If restore fails, we consider the process is too dirty to recover. self.fatal_error = Some(BuildMicrovmFromRequestsError::Restore); - err })?; // Resume VM if load_params.resume_vm { vmm.lock() .expect("Poisoned lock") .resume_vm() - .map_err(|err| { + .inspect_err(|_| { // If resume fails, we consider the process is too dirty to recover. self.fatal_error = Some(BuildMicrovmFromRequestsError::Resume); - err })?; } // Set the VM diff --git a/src/vmm/src/vmm_config/boot_source.rs b/src/vmm/src/vmm_config/boot_source.rs index c40a0fde014..1bfed7bad9c 100644 --- a/src/vmm/src/vmm_config/boot_source.rs +++ b/src/vmm/src/vmm_config/boot_source.rs @@ -119,7 +119,7 @@ pub(crate) mod tests { assert!(boot_cfg.initrd_file.is_none()); assert_eq!( boot_cfg.cmdline.as_cstring().unwrap().as_bytes_with_nul(), - [DEFAULT_KERNEL_CMDLINE.as_bytes(), &[b'\0']].concat() + [DEFAULT_KERNEL_CMDLINE.as_bytes(), b"\0"].concat() ); } diff --git a/src/vmm/src/vmm_config/net.rs b/src/vmm/src/vmm_config/net.rs index 4b917c2ca48..8ece4e7e494 100644 --- a/src/vmm/src/vmm_config/net.rs +++ b/src/vmm/src/vmm_config/net.rs @@ -183,13 +183,9 @@ mod tests { use crate::rate_limiter::RateLimiter; impl NetBuilder { - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { self.net_devices.len() } - - pub fn is_empty(&self) -> bool { - self.net_devices.len() == 0 - } } fn create_netif(id: &str, name: &str, mac: &str) -> NetworkInterfaceConfig { diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index cb63afa4579..73779fbd928 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -759,7 +759,7 @@ pub enum VcpuEmulation { } #[cfg(test)] -pub mod tests { +pub(crate) mod tests { #![allow(clippy::undocumented_unsafe_blocks)] #[cfg(target_arch = "x86_64")] From e3088afaaa7276bf7c983e3b16223996a0c16f97 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 28 Nov 2024 10:57:39 +0000 Subject: [PATCH 33/78] chore(devtool): run cmd_build in privileged container This is needed for CI to install previous version of the toolchain used on the main branch. This change will need to be reverted after this PR is merged. Signed-off-by: Egor Lazarchuk Signed-off-by: Patrick Roy --- tools/devtool | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 36406c61bda..662c2583450 100755 --- a/tools/devtool +++ b/tools/devtool @@ -509,13 +509,17 @@ cmd_build() { # We don't need any special privileges for the build phase, so we run the # container as the current user/group. run_devctr \ - --user "$(id -u):$(id -g)" \ + --privileged \ --workdir "$workdir" \ ${extra_args} \ -- \ ./tools/release.sh --libc $libc --profile $profile ret=$? + # Running as root would have created some root-owned files under the build + # dir. Let's fix that. + cmd_fix_perms + if [ ! -z "$revision" ]; then popd git branch -D $branch_name From 85ebd24d8bea947c61e10a8d373e183f40fdb4ba Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 25 Nov 2024 13:56:41 +0000 Subject: [PATCH 34/78] docker: add what's needed for static seccomp analysis Add the rust-src component and the $(uname -m)-unknown-linux-musl targets for the nightly toolchain, and install python3-seccomp and rustfilt. Since the python bindings for libseccomp are not published to pip, we have to install it into the global python installation via apt-get, and then copy into our venv. Signed-off-by: Patrick Roy --- tools/devctr/Dockerfile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index bebf1309e00..14867f3d9f1 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -76,6 +76,7 @@ RUN apt-get update \ tzdata \ tini \ squashfs-tools zstd \ + python3-seccomp \ # for aws-lc-rs cmake \ # for Qemu vhost-user-blk backend @@ -98,8 +99,13 @@ RUN cd /tmp/poetry \ ENV VIRTUAL_ENV=$VENV ENV PATH=$VENV/bin:$PATH +# apt-get installs it globally, to manually copy it into the venv +RUN cp /usr/lib/python3/dist-packages/seccomp.cpython-312-"$ARCH"-linux-gnu.so "$VENV"/lib/python3.12/site-packages/ + # Running the three as a single dockerfile command to avoid inflation of the image: -# - Install the Rust toolchain. Kani only work on x86, so only try to install it there +# - Install the Rust toolchain. +# - Kani always installs _some_ nightly toolchain, we reuse it for the seccomp filter analysis test. Dynamically +# determine the exact toolchain name, and install more components into it. # - Build and install crosvm (used as vhost-user-blk backend) # - Clean up cargo compilation directories # - Always install both x86_64 and aarch64 musl targets, as our rust-toolchain.toml would force on-the-fly installation of both anyway @@ -110,6 +116,10 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too && cargo install --locked cargo-audit cargo-deny@0.16.1 grcov cargo-sort cargo-afl \ && cargo install --locked kani-verifier && cargo kani setup \ \ + && NIGHTLY_TOOLCHAIN=$(rustup toolchain list | grep nightly | tr -d '\n') \ + && rustup component add rust-src --toolchain "$NIGHTLY_TOOLCHAIN" \ + && rustup target add "$ARCH"-unknown-linux-musl --toolchain "$NIGHTLY_TOOLCHAIN" \ + \ && apt-get update \ && apt-get -y install --no-install-recommends \ libcap-dev \ From de8076806d490abb8eb501a6606112da09b77317 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 25 Nov 2024 16:54:29 +0000 Subject: [PATCH 35/78] chore(devctr): add libseccomp to devctr Build static version of libseccomp with `musl-gcc`. This is needed for our musl builds as the version shipped in the ubuntu package is not compiled with `musl-gcc` and produces linker errors. Signed-off-by: Egor Lazarchuk Signed-off-by: Patrick Roy --- tools/devctr/Dockerfile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index 14867f3d9f1..153b34fc6ee 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -147,6 +147,22 @@ RUN cd /usr/include/$ARCH-linux-musl \ && ln -s ../linux linux \ && ln -s ../asm-generic asm-generic +# Install static version of libseccomp +# +RUN apt-get update \ + && apt-get -y install \ + libtool gperf \ + && git clone https://github.com/seccomp/libseccomp /tmp/libseccomp \ + && cd /tmp/libseccomp \ + && ./autogen.sh \ + && CC="musl-gcc -static" ./configure --enable-static=yes --enable-shared=false \ + && make install \ + && cd \ + && apt-get purge -y \ + libtool gperf \ + && apt-get autoremove -y \ + && rm -rf /tmp/libseccomp + # Build iperf3-vsock RUN mkdir "$TMP_BUILD_DIR" && cd "$TMP_BUILD_DIR" \ && git clone https://github.com/stefano-garzarella/iperf-vsock \ From 3592d48ce1733a15acccfe79555836f3002288d6 Mon Sep 17 00:00:00 2001 From: Jonathan Woollett-Light Date: Wed, 4 Oct 2023 11:30:33 +0100 Subject: [PATCH 36/78] build: Add `cargo-udeps` to devctr From: Jonathan Woollett-Light Adds `cargo-udeps` and the Rust `nightly` toolchain to support it, to dev container. Signed-off-by: Jonathan Woollett-Light Co-authored-by: Patrick Roy Signed-off-by: Patrick Roy --- tools/devctr/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index 153b34fc6ee..9340c4c9c98 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -119,6 +119,7 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too && NIGHTLY_TOOLCHAIN=$(rustup toolchain list | grep nightly | tr -d '\n') \ && rustup component add rust-src --toolchain "$NIGHTLY_TOOLCHAIN" \ && rustup target add "$ARCH"-unknown-linux-musl --toolchain "$NIGHTLY_TOOLCHAIN" \ + && cargo +"$NIGHTLY_TOOLCHAIN" install cargo-udeps \ \ && apt-get update \ && apt-get -y install --no-install-recommends \ From ce95642296a7b638b91bbbfa7e5935206572d995 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 10:54:48 +0000 Subject: [PATCH 37/78] poetry: add fabric and netns dependencies These python dependencies are used for an upcoming PR about reusing SSH connection in our SSH tests. Signed-off-by: Patrick Roy --- tools/devctr/poetry.lock | 2123 +++++++++++++++++++++-------------- tools/devctr/pyproject.toml | 2 + 2 files changed, 1253 insertions(+), 872 deletions(-) diff --git a/tools/devctr/poetry.lock b/tools/devctr/poetry.lock index 96f1d0c990a..eb969e9eda2 100644 --- a/tools/devctr/poetry.lock +++ b/tools/devctr/poetry.lock @@ -1,114 +1,99 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" -version = "2.4.0" +version = "2.4.4" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.4.0-py3-none-any.whl", hash = "sha256:7ce92076e249169a13c2f49320d1967425eaf1f407522d707d59cac7628d62bd"}, - {file = "aiohappyeyeballs-2.4.0.tar.gz", hash = "sha256:55a1714f084e63d49639800f95716da97a1f173d46a16dfcfda0016abb93b6b2"}, + {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, + {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, ] [[package]] name = "aiohttp" -version = "3.10.11" +version = "3.11.10" description = "Async http client/server framework (asyncio)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"}, - {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"}, - {file = "aiohttp-3.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffbfde2443696345e23a3c597049b1dd43049bb65337837574205e7368472177"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b3d9e416774d41813bc02fdc0663379c01817b0874b932b81c7f777f67b217"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b943011b45ee6bf74b22245c6faab736363678e910504dd7531a58c76c9015a"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48bc1d924490f0d0b3658fe5c4b081a4d56ebb58af80a6729d4bd13ea569797a"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e12eb3f4b1f72aaaf6acd27d045753b18101524f72ae071ae1c91c1cd44ef115"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f14ebc419a568c2eff3c1ed35f634435c24ead2fe19c07426af41e7adb68713a"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:72b191cdf35a518bfc7ca87d770d30941decc5aaf897ec8b484eb5cc8c7706f3"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ab2328a61fdc86424ee540d0aeb8b73bbcad7351fb7cf7a6546fc0bcffa0038"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aa93063d4af05c49276cf14e419550a3f45258b6b9d1f16403e777f1addf4519"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:30283f9d0ce420363c24c5c2421e71a738a2155f10adbb1a11a4d4d6d2715cfc"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e5358addc8044ee49143c546d2182c15b4ac3a60be01c3209374ace05af5733d"}, - {file = "aiohttp-3.10.11-cp310-cp310-win32.whl", hash = "sha256:e1ffa713d3ea7cdcd4aea9cddccab41edf6882fa9552940344c44e59652e1120"}, - {file = "aiohttp-3.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:778cbd01f18ff78b5dd23c77eb82987ee4ba23408cbed233009fd570dda7e674"}, - {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:80ff08556c7f59a7972b1e8919f62e9c069c33566a6d28586771711e0eea4f07"}, - {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c8f96e9ee19f04c4914e4e7a42a60861066d3e1abf05c726f38d9d0a466e695"}, - {file = "aiohttp-3.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fb8601394d537da9221947b5d6e62b064c9a43e88a1ecd7414d21a1a6fba9c24"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea224cf7bc2d8856d6971cea73b1d50c9c51d36971faf1abc169a0d5f85a382"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db9503f79e12d5d80b3efd4d01312853565c05367493379df76d2674af881caa"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f449a50cc33f0384f633894d8d3cd020e3ccef81879c6e6245c3c375c448625"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82052be3e6d9e0c123499127782a01a2b224b8af8c62ab46b3f6197035ad94e9"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20063c7acf1eec550c8eb098deb5ed9e1bb0521613b03bb93644b810986027ac"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:489cced07a4c11488f47aab1f00d0c572506883f877af100a38f1fedaa884c3a"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea9b3bab329aeaa603ed3bf605f1e2a6f36496ad7e0e1aa42025f368ee2dc07b"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ca117819d8ad113413016cb29774b3f6d99ad23c220069789fc050267b786c16"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2dfb612dcbe70fb7cdcf3499e8d483079b89749c857a8f6e80263b021745c730"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9b615d3da0d60e7d53c62e22b4fd1c70f4ae5993a44687b011ea3a2e49051b8"}, - {file = "aiohttp-3.10.11-cp311-cp311-win32.whl", hash = "sha256:29103f9099b6068bbdf44d6a3d090e0a0b2be6d3c9f16a070dd9d0d910ec08f9"}, - {file = "aiohttp-3.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:236b28ceb79532da85d59aa9b9bf873b364e27a0acb2ceaba475dc61cffb6f3f"}, - {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7480519f70e32bfb101d71fb9a1f330fbd291655a4c1c922232a48c458c52710"}, - {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f65267266c9aeb2287a6622ee2bb39490292552f9fbf851baabc04c9f84e048d"}, - {file = "aiohttp-3.10.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7400a93d629a0608dc1d6c55f1e3d6e07f7375745aaa8bd7f085571e4d1cee97"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f34b97e4b11b8d4eb2c3a4f975be626cc8af99ff479da7de49ac2c6d02d35725"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e7b825da878464a252ccff2958838f9caa82f32a8dbc334eb9b34a026e2c636"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9f92a344c50b9667827da308473005f34767b6a2a60d9acff56ae94f895f385"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f1ab987a27b83c5268a17218463c2ec08dbb754195113867a27b166cd6087"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1dc0f4ca54842173d03322793ebcf2c8cc2d34ae91cc762478e295d8e361e03f"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7ce6a51469bfaacff146e59e7fb61c9c23006495d11cc24c514a455032bcfa03"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aad3cd91d484d065ede16f3cf15408254e2469e3f613b241a1db552c5eb7ab7d"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f4df4b8ca97f658c880fb4b90b1d1ec528315d4030af1ec763247ebfd33d8b9a"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e4e18a0a2d03531edbc06c366954e40a3f8d2a88d2b936bbe78a0c75a3aab3e"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ce66780fa1a20e45bc753cda2a149daa6dbf1561fc1289fa0c308391c7bc0a4"}, - {file = "aiohttp-3.10.11-cp312-cp312-win32.whl", hash = "sha256:a919c8957695ea4c0e7a3e8d16494e3477b86f33067478f43106921c2fef15bb"}, - {file = "aiohttp-3.10.11-cp312-cp312-win_amd64.whl", hash = "sha256:b5e29706e6389a2283a91611c91bf24f218962717c8f3b4e528ef529d112ee27"}, - {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:703938e22434d7d14ec22f9f310559331f455018389222eed132808cd8f44127"}, - {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bc50b63648840854e00084c2b43035a62e033cb9b06d8c22b409d56eb098413"}, - {file = "aiohttp-3.10.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f0463bf8b0754bc744e1feb61590706823795041e63edf30118a6f0bf577461"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6c6dec398ac5a87cb3a407b068e1106b20ef001c344e34154616183fe684288"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcaf2d79104d53d4dcf934f7ce76d3d155302d07dae24dff6c9fffd217568067"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25fd5470922091b5a9aeeb7e75be609e16b4fba81cdeaf12981393fb240dd10e"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbde2ca67230923a42161b1f408c3992ae6e0be782dca0c44cb3206bf330dee1"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:249c8ff8d26a8b41a0f12f9df804e7c685ca35a207e2410adbd3e924217b9006"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:878ca6a931ee8c486a8f7b432b65431d095c522cbeb34892bee5be97b3481d0f"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8663f7777ce775f0413324be0d96d9730959b2ca73d9b7e2c2c90539139cbdd6"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd3f10b01f0c31481fba8d302b61603a2acb37b9d30e1d14e0f5a58b7b18a31"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e8d8aad9402d3aa02fdc5ca2fe68bcb9fdfe1f77b40b10410a94c7f408b664d"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38e3c4f80196b4f6c3a85d134a534a56f52da9cb8d8e7af1b79a32eefee73a00"}, - {file = "aiohttp-3.10.11-cp313-cp313-win32.whl", hash = "sha256:fc31820cfc3b2863c6e95e14fcf815dc7afe52480b4dc03393c4873bb5599f71"}, - {file = "aiohttp-3.10.11-cp313-cp313-win_amd64.whl", hash = "sha256:4996ff1345704ffdd6d75fb06ed175938c133425af616142e7187f28dc75f14e"}, - {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:74baf1a7d948b3d640badeac333af581a367ab916b37e44cf90a0334157cdfd2"}, - {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:473aebc3b871646e1940c05268d451f2543a1d209f47035b594b9d4e91ce8339"}, - {file = "aiohttp-3.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c2f746a6968c54ab2186574e15c3f14f3e7f67aef12b761e043b33b89c5b5f95"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d110cabad8360ffa0dec8f6ec60e43286e9d251e77db4763a87dcfe55b4adb92"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0099c7d5d7afff4202a0c670e5b723f7718810000b4abcbc96b064129e64bc7"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0316e624b754dbbf8c872b62fe6dcb395ef20c70e59890dfa0de9eafccd2849d"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a5f7ab8baf13314e6b2485965cbacb94afff1e93466ac4d06a47a81c50f9cca"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c891011e76041e6508cbfc469dd1a8ea09bc24e87e4c204e05f150c4c455a5fa"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9208299251370ee815473270c52cd3f7069ee9ed348d941d574d1457d2c73e8b"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:459f0f32c8356e8125f45eeff0ecf2b1cb6db1551304972702f34cd9e6c44658"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:14cdc8c1810bbd4b4b9f142eeee23cda528ae4e57ea0923551a9af4820980e39"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:971aa438a29701d4b34e4943e91b5e984c3ae6ccbf80dd9efaffb01bd0b243a9"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9a309c5de392dfe0f32ee57fa43ed8fc6ddf9985425e84bd51ed66bb16bce3a7"}, - {file = "aiohttp-3.10.11-cp38-cp38-win32.whl", hash = "sha256:9ec1628180241d906a0840b38f162a3215114b14541f1a8711c368a8739a9be4"}, - {file = "aiohttp-3.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:9c6e0ffd52c929f985c7258f83185d17c76d4275ad22e90aa29f38e211aacbec"}, - {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cdc493a2e5d8dc79b2df5bec9558425bcd39aff59fc949810cbd0832e294b106"}, - {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3e70f24e7d0405be2348da9d5a7836936bf3a9b4fd210f8c37e8d48bc32eca6"}, - {file = "aiohttp-3.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968b8fb2a5eee2770eda9c7b5581587ef9b96fbdf8dcabc6b446d35ccc69df01"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deef4362af9493d1382ef86732ee2e4cbc0d7c005947bd54ad1a9a16dd59298e"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:686b03196976e327412a1b094f4120778c7c4b9cff9bce8d2fdfeca386b89829"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bf6d027d9d1d34e1c2e1645f18a6498c98d634f8e373395221121f1c258ace8"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:099fd126bf960f96d34a760e747a629c27fb3634da5d05c7ef4d35ef4ea519fc"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c73c4d3dae0b4644bc21e3de546530531d6cdc88659cdeb6579cd627d3c206aa"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c5580f3c51eea91559db3facd45d72e7ec970b04528b4709b1f9c2555bd6d0b"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fdf6429f0caabfd8a30c4e2eaecb547b3c340e4730ebfe25139779b9815ba138"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d97187de3c276263db3564bb9d9fad9e15b51ea10a371ffa5947a5ba93ad6777"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0acafb350cfb2eba70eb5d271f55e08bd4502ec35e964e18ad3e7d34d71f7261"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c13ed0c779911c7998a58e7848954bd4d63df3e3575f591e321b19a2aec8df9f"}, - {file = "aiohttp-3.10.11-cp39-cp39-win32.whl", hash = "sha256:22b7c540c55909140f63ab4f54ec2c20d2635c0289cdd8006da46f3327f971b9"}, - {file = "aiohttp-3.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:7b26b1551e481012575dab8e3727b16fe7dd27eb2711d2e63ced7368756268fb"}, - {file = "aiohttp-3.10.11.tar.gz", hash = "sha256:9dc2b8f3dcab2e39e0fa309c8da50c3b55e6f34ab25f1a71d3288f24924d33a7"}, + {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cbad88a61fa743c5d283ad501b01c153820734118b65aee2bd7dbb735475ce0d"}, + {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80886dac673ceaef499de2f393fc80bb4481a129e6cb29e624a12e3296cc088f"}, + {file = "aiohttp-3.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61b9bae80ed1f338c42f57c16918853dc51775fb5cb61da70d590de14d8b5fb4"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e2e576caec5c6a6b93f41626c9c02fc87cd91538b81a3670b2e04452a63def6"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02c13415b5732fb6ee7ff64583a5e6ed1c57aa68f17d2bda79c04888dfdc2769"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfce37f31f20800a6a6620ce2cdd6737b82e42e06e6e9bd1b36f546feb3c44f"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bbbfff4c679c64e6e23cb213f57cc2c9165c9a65d63717108a644eb5a7398df"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49c7dbbc1a559ae14fc48387a115b7d4bbc84b4a2c3b9299c31696953c2a5219"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:68386d78743e6570f054fe7949d6cb37ef2b672b4d3405ce91fafa996f7d9b4d"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9ef405356ba989fb57f84cac66f7b0260772836191ccefbb987f414bcd2979d9"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5d6958671b296febe7f5f859bea581a21c1d05430d1bbdcf2b393599b1cdce77"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:99b7920e7165be5a9e9a3a7f1b680f06f68ff0d0328ff4079e5163990d046767"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0dc49f42422163efb7e6f1df2636fe3db72713f6cd94688e339dbe33fe06d61d"}, + {file = "aiohttp-3.11.10-cp310-cp310-win32.whl", hash = "sha256:40d1c7a7f750b5648642586ba7206999650208dbe5afbcc5284bcec6579c9b91"}, + {file = "aiohttp-3.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:68ff6f48b51bd78ea92b31079817aff539f6c8fc80b6b8d6ca347d7c02384e33"}, + {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:77c4aa15a89847b9891abf97f3d4048f3c2d667e00f8a623c89ad2dccee6771b"}, + {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:909af95a72cedbefe5596f0bdf3055740f96c1a4baa0dd11fd74ca4de0b4e3f1"}, + {file = "aiohttp-3.11.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:386fbe79863eb564e9f3615b959e28b222259da0c48fd1be5929ac838bc65683"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3de34936eb1a647aa919655ff8d38b618e9f6b7f250cc19a57a4bf7fd2062b6d"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c9527819b29cd2b9f52033e7fb9ff08073df49b4799c89cb5754624ecd98299"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a96e3e03300b41f261bbfd40dfdbf1c301e87eab7cd61c054b1f2e7c89b9e8"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f5635f7b74bcd4f6f72fcd85bea2154b323a9f05226a80bc7398d0c90763b0"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03b6002e20938fc6ee0918c81d9e776bebccc84690e2b03ed132331cca065ee5"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6362cc6c23c08d18ddbf0e8c4d5159b5df74fea1a5278ff4f2c79aed3f4e9f46"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3691ed7726fef54e928fe26344d930c0c8575bc968c3e239c2e1a04bd8cf7838"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31d5093d3acd02b31c649d3a69bb072d539d4c7659b87caa4f6d2bcf57c2fa2b"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8b3cf2dc0f0690a33f2d2b2cb15db87a65f1c609f53c37e226f84edb08d10f52"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbbaea811a2bba171197b08eea288b9402faa2bab2ba0858eecdd0a4105753a3"}, + {file = "aiohttp-3.11.10-cp311-cp311-win32.whl", hash = "sha256:4b2c7ac59c5698a7a8207ba72d9e9c15b0fc484a560be0788b31312c2c5504e4"}, + {file = "aiohttp-3.11.10-cp311-cp311-win_amd64.whl", hash = "sha256:974d3a2cce5fcfa32f06b13ccc8f20c6ad9c51802bb7f829eae8a1845c4019ec"}, + {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b78f053a7ecfc35f0451d961dacdc671f4bcbc2f58241a7c820e9d82559844cf"}, + {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab7485222db0959a87fbe8125e233b5a6f01f4400785b36e8a7878170d8c3138"}, + {file = "aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cf14627232dfa8730453752e9cdc210966490992234d77ff90bc8dc0dce361d5"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:076bc454a7e6fd646bc82ea7f98296be0b1219b5e3ef8a488afbdd8e81fbac50"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:482cafb7dc886bebeb6c9ba7925e03591a62ab34298ee70d3dd47ba966370d2c"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf3d1a519a324af764a46da4115bdbd566b3c73fb793ffb97f9111dbc684fc4d"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24213ba85a419103e641e55c27dc7ff03536c4873470c2478cce3311ba1eee7b"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b99acd4730ad1b196bfb03ee0803e4adac371ae8efa7e1cbc820200fc5ded109"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:14cdb5a9570be5a04eec2ace174a48ae85833c2aadc86de68f55541f66ce42ab"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7e97d622cb083e86f18317282084bc9fbf261801b0192c34fe4b1febd9f7ae69"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:012f176945af138abc10c4a48743327a92b4ca9adc7a0e078077cdb5dbab7be0"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44224d815853962f48fe124748227773acd9686eba6dc102578defd6fc99e8d9"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c87bf31b7fdab94ae3adbe4a48e711bfc5f89d21cf4c197e75561def39e223bc"}, + {file = "aiohttp-3.11.10-cp312-cp312-win32.whl", hash = "sha256:06a8e2ee1cbac16fe61e51e0b0c269400e781b13bcfc33f5425912391a542985"}, + {file = "aiohttp-3.11.10-cp312-cp312-win_amd64.whl", hash = "sha256:be2b516f56ea883a3e14dda17059716593526e10fb6303189aaf5503937db408"}, + {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8cc5203b817b748adccb07f36390feb730b1bc5f56683445bfe924fc270b8816"}, + {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ef359ebc6949e3a34c65ce20230fae70920714367c63afd80ea0c2702902ccf"}, + {file = "aiohttp-3.11.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9bca390cb247dbfaec3c664326e034ef23882c3f3bfa5fbf0b56cad0320aaca5"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811f23b3351ca532af598405db1093f018edf81368e689d1b508c57dcc6b6a32"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddf5f7d877615f6a1e75971bfa5ac88609af3b74796ff3e06879e8422729fd01"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ab29b8a0beb6f8eaf1e5049252cfe74adbaafd39ba91e10f18caeb0e99ffb34"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c49a76c1038c2dd116fa443eba26bbb8e6c37e924e2513574856de3b6516be99"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f3dc0e330575f5b134918976a645e79adf333c0a1439dcf6899a80776c9ab39"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:efb15a17a12497685304b2d976cb4939e55137df7b09fa53f1b6a023f01fcb4e"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:db1d0b28fcb7f1d35600150c3e4b490775251dea70f894bf15c678fdd84eda6a"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:15fccaf62a4889527539ecb86834084ecf6e9ea70588efde86e8bc775e0e7542"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:593c114a2221444f30749cc5e5f4012488f56bd14de2af44fe23e1e9894a9c60"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7852bbcb4d0d2f0c4d583f40c3bc750ee033265d80598d0f9cb6f372baa6b836"}, + {file = "aiohttp-3.11.10-cp313-cp313-win32.whl", hash = "sha256:65e55ca7debae8faaffee0ebb4b47a51b4075f01e9b641c31e554fd376595c6c"}, + {file = "aiohttp-3.11.10-cp313-cp313-win_amd64.whl", hash = "sha256:beb39a6d60a709ae3fb3516a1581777e7e8b76933bb88c8f4420d875bb0267c6"}, + {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0580f2e12de2138f34debcd5d88894786453a76e98febaf3e8fe5db62d01c9bf"}, + {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a55d2ad345684e7c3dd2c20d2f9572e9e1d5446d57200ff630e6ede7612e307f"}, + {file = "aiohttp-3.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04814571cb72d65a6899db6099e377ed00710bf2e3eafd2985166f2918beaf59"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e44a9a3c053b90c6f09b1bb4edd880959f5328cf63052503f892c41ea786d99f"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:502a1464ccbc800b4b1995b302efaf426e8763fadf185e933c2931df7db9a199"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:613e5169f8ae77b1933e42e418a95931fb4867b2991fc311430b15901ed67079"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cca22a61b7fe45da8fc73c3443150c3608750bbe27641fc7558ec5117b27fdf"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86a5dfcc39309470bd7b68c591d84056d195428d5d2e0b5ccadfbaf25b026ebc"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:77ae58586930ee6b2b6f696c82cf8e78c8016ec4795c53e36718365f6959dc82"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:78153314f26d5abef3239b4a9af20c229c6f3ecb97d4c1c01b22c4f87669820c"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:98283b94cc0e11c73acaf1c9698dea80c830ca476492c0fe2622bd931f34b487"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:53bf2097e05c2accc166c142a2090e4c6fd86581bde3fd9b2d3f9e93dda66ac1"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5532f0441fc09c119e1dca18fbc0687e64fbeb45aa4d6a87211ceaee50a74c4"}, + {file = "aiohttp-3.11.10-cp39-cp39-win32.whl", hash = "sha256:47ad15a65fb41c570cd0ad9a9ff8012489e68176e7207ec7b82a0940dddfd8be"}, + {file = "aiohttp-3.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:c6b9e6d7e41656d78e37ce754813fa44b455c3d0d0dced2a047def7dc5570b74"}, + {file = "aiohttp-3.11.10.tar.gz", hash = "sha256:b1fc6b45010a8d0ff9e88f9f2418c6fd408c99c211257334aff41597ebece42e"}, ] [package.dependencies] @@ -118,7 +103,8 @@ async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" -yarl = ">=1.12.0,<2.0" +propcache = ">=0.2.0" +yarl = ">=1.17.0,<2.0" [package.extras] speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] @@ -153,13 +139,13 @@ python-dateutil = ">=2.7.0" [[package]] name = "astroid" -version = "3.2.4" +version = "3.3.6" description = "An abstract syntax tree for Python with inference support." optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" files = [ - {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, - {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, + {file = "astroid-3.3.6-py3-none-any.whl", hash = "sha256:db676dc4f3ae6bfe31cda227dc60e03438378d7a896aec57422c95634e8d722f"}, + {file = "astroid-3.3.6.tar.gz", hash = "sha256:6aaea045f938c735ead292204afdb977a36e989522b7833ef6fea94de743f442"}, ] [package.dependencies] @@ -167,31 +153,28 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "asttokens" -version = "2.4.1" +version = "3.0.0" description = "Annotate AST trees with source code positions" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, - {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, + {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, + {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, ] -[package.dependencies] -six = ">=1.12.0" - [package.extras] -astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] -test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] +astroid = ["astroid (>=2,<4)"] +test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "async-timeout" -version = "4.0.3" +version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, - {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, + {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, + {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, ] [[package]] @@ -227,35 +210,73 @@ files = [ [package.dependencies] aiohttp = "*" +[[package]] +name = "bcrypt" +version = "4.2.1" +description = "Modern password hashing for your software and your servers" +optional = false +python-versions = ">=3.7" +files = [ + {file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dbd0747208912b1e4ce730c6725cb56c07ac734b3629b60d4398f082ea718ad"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:aaa2e285be097050dba798d537b6efd9b698aa88eef52ec98d23dcd6d7cf6fea"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:76d3e352b32f4eeb34703370e370997065d28a561e4a18afe4fef07249cb4396"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:b7703ede632dc945ed1172d6f24e9f30f27b1b1a067f32f68bf169c5f08d0425"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:89df2aea2c43be1e1fa066df5f86c8ce822ab70a30e4c210968669565c0f4685"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:04e56e3fe8308a88b77e0afd20bec516f74aecf391cdd6e374f15cbed32783d6"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cfdf3d7530c790432046c40cda41dfee8c83e29482e6a604f8930b9930e94139"}, + {file = "bcrypt-4.2.1-cp37-abi3-win32.whl", hash = "sha256:adadd36274510a01f33e6dc08f5824b97c9580583bd4487c564fc4617b328005"}, + {file = "bcrypt-4.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:8c458cd103e6c5d1d85cf600e546a639f234964d0228909d8f8dbeebff82d526"}, + {file = "bcrypt-4.2.1-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:8ad2f4528cbf0febe80e5a3a57d7a74e6635e41af1ea5675282a33d769fba413"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909faa1027900f2252a9ca5dfebd25fc0ef1417943824783d1c8418dd7d6df4a"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cde78d385d5e93ece5479a0a87f73cd6fa26b171c786a884f955e165032b262c"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:533e7f3bcf2f07caee7ad98124fab7499cb3333ba2274f7a36cf1daee7409d99"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:687cf30e6681eeda39548a93ce9bfbb300e48b4d445a43db4298d2474d2a1e54"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:041fa0155c9004eb98a232d54da05c0b41d4b8e66b6fc3cb71b4b3f6144ba837"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f85b1ffa09240c89aa2e1ae9f3b1c687104f7b2b9d2098da4e923f1b7082d331"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c6f5fa3775966cca251848d4d5393ab016b3afed251163c1436fefdec3b02c84"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:807261df60a8b1ccd13e6599c779014a362ae4e795f5c59747f60208daddd96d"}, + {file = "bcrypt-4.2.1-cp39-abi3-win32.whl", hash = "sha256:b588af02b89d9fad33e5f98f7838bf590d6d692df7153647724a7f20c186f6bf"}, + {file = "bcrypt-4.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:e84e0e6f8e40a242b11bce56c313edc2be121cec3e0ec2d76fce01f6af33c07c"}, + {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76132c176a6d9953cdc83c296aeaed65e1a708485fd55abf163e0d9f8f16ce0e"}, + {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e158009a54c4c8bc91d5e0da80920d048f918c61a581f0a63e4e93bb556d362f"}, + {file = "bcrypt-4.2.1.tar.gz", hash = "sha256:6765386e3ab87f569b276988742039baab087b2cdb01e809d74e74503c2faafe"}, +] + +[package.extras] +tests = ["pytest (>=3.2.1,!=3.3.0)"] +typecheck = ["mypy"] + [[package]] name = "black" -version = "24.8.0" +version = "24.10.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"}, - {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"}, - {file = "black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42"}, - {file = "black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a"}, - {file = "black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1"}, - {file = "black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af"}, - {file = "black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4"}, - {file = "black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af"}, - {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"}, - {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"}, - {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"}, - {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"}, - {file = "black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd"}, - {file = "black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2"}, - {file = "black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e"}, - {file = "black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920"}, - {file = "black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c"}, - {file = "black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e"}, - {file = "black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47"}, - {file = "black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb"}, - {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"}, - {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"}, + {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, + {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, + {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, + {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, + {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, + {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, + {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, + {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, + {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, + {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, + {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, + {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, + {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, + {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, + {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, + {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, + {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, + {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, + {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, + {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, + {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, + {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, ] [package.dependencies] @@ -269,7 +290,7 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -284,103 +305,197 @@ files = [ {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] +[[package]] +name = "cffi" +version = "1.17.1" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] + +[package.dependencies] +pycparser = "*" + [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] [[package]] @@ -408,6 +523,57 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "cryptography" +version = "44.0.0" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = "!=3.9.0,!=3.9.1,>=3.7" +files = [ + {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, + {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, + {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, + {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, + {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, + {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, + {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, +] + +[package.dependencies] +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] +docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +sdist = ["build (>=1.0.0)"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +test-randomorder = ["pytest-randomly"] + [[package]] name = "decorator" version = "5.1.1" @@ -419,15 +585,32 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "deprecated" +version = "1.2.15" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +files = [ + {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"}, + {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "jinja2 (>=3.0.3,<3.1.0)", "setuptools", "sphinx (<2)", "tox"] + [[package]] name = "dill" -version = "0.3.8" +version = "0.3.9" description = "serialize all of Python" optional = false python-versions = ">=3.8" files = [ - {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, - {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, + {file = "dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a"}, + {file = "dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c"}, ] [package.extras] @@ -476,106 +659,141 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] +[[package]] +name = "fabric" +version = "3.2.2" +description = "High level SSH command execution" +optional = false +python-versions = "*" +files = [ + {file = "fabric-3.2.2-py3-none-any.whl", hash = "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f"}, + {file = "fabric-3.2.2.tar.gz", hash = "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3"}, +] + +[package.dependencies] +decorator = ">=5" +deprecated = ">=1.2" +invoke = ">=2.0" +paramiko = ">=2.4" + +[package.extras] +pytest = ["pytest (>=7)"] + [[package]] name = "filelock" -version = "3.16.0" +version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.16.0-py3-none-any.whl", hash = "sha256:f6ed4c963184f4c84dd5557ce8fece759a3724b37b80c6c4f20a2f63a4dc6609"}, - {file = "filelock-3.16.0.tar.gz", hash = "sha256:81de9eb8453c769b63369f87f11131a7ab04e367f8d97ad39dc230daa07e3bec"}, + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.1.1)", "pytest (>=8.3.2)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.3)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "frozenlist" -version = "1.4.1" +version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" files = [ - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, - {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, - {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, - {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, - {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, - {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, - {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, - {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, - {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, + {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, + {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, + {file = "frozenlist-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5"}, + {file = "frozenlist-1.5.0-cp310-cp310-win32.whl", hash = "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb"}, + {file = "frozenlist-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4"}, + {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30"}, + {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5"}, + {file = "frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf"}, + {file = "frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942"}, + {file = "frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d"}, + {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21"}, + {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d"}, + {file = "frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f"}, + {file = "frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8"}, + {file = "frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f"}, + {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953"}, + {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0"}, + {file = "frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03"}, + {file = "frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c"}, + {file = "frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28"}, + {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca"}, + {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10"}, + {file = "frozenlist-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e"}, + {file = "frozenlist-1.5.0-cp38-cp38-win32.whl", hash = "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723"}, + {file = "frozenlist-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923"}, + {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972"}, + {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336"}, + {file = "frozenlist-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c"}, + {file = "frozenlist-1.5.0-cp39-cp39-win32.whl", hash = "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3"}, + {file = "frozenlist-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0"}, + {file = "frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3"}, + {file = "frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817"}, ] [[package]] @@ -622,15 +840,18 @@ trusted-deps = ["arrow (==1.2.3)", "click (==8.1.3)", "sh (==1.14.3)"] [[package]] name = "idna" -version = "3.8" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" files = [ - {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, - {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -642,15 +863,26 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "invoke" +version = "2.2.0" +description = "Pythonic task execution" +optional = false +python-versions = ">=3.6" +files = [ + {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, + {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, +] + [[package]] name = "ipython" -version = "8.27.0" +version = "8.30.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" files = [ - {file = "ipython-8.27.0-py3-none-any.whl", hash = "sha256:f68b3cb8bde357a5d7adc9598d57e22a45dfbea19eb6b98286fa3b288c9cd55c"}, - {file = "ipython-8.27.0.tar.gz", hash = "sha256:0b99a2dc9f15fd68692e898e5568725c6d49c527d36a9fb5960ffbdeaa82ff7e"}, + {file = "ipython-8.30.0-py3-none-any.whl", hash = "sha256:85ec56a7e20f6c38fce7727dcca699ae4ffc85985aa7b23635a8008f918ae321"}, + {file = "ipython-8.30.0.tar.gz", hash = "sha256:cb0a405a306d2995a5cbb9901894d240784a9f341394c6ba3f4fe8c6eb89ff6e"}, ] [package.dependencies] @@ -660,16 +892,16 @@ exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} -prompt-toolkit = ">=3.0.41,<3.1.0" +prompt_toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" -stack-data = "*" +stack_data = "*" traitlets = ">=5.13.0" -typing-extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} +typing_extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} [package.extras] all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "intersphinx-registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing_extensions"] kernel = ["ipykernel"] matplotlib = ["matplotlib"] nbconvert = ["nbconvert"] @@ -696,22 +928,22 @@ colors = ["colorama (>=0.4.6)"] [[package]] name = "jedi" -version = "0.19.1" +version = "0.19.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" files = [ - {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, - {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, + {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, + {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, ] [package.dependencies] -parso = ">=0.8.3,<0.9.0" +parso = ">=0.8.4,<0.9.0" [package.extras] docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"] [[package]] name = "jsonschema" @@ -883,13 +1115,13 @@ files = [ [[package]] name = "mdformat" -version = "0.7.17" +version = "0.7.19" description = "CommonMark compliant Markdown formatter" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "mdformat-0.7.17-py3-none-any.whl", hash = "sha256:91ffc5e203f5814a6ad17515c77767fd2737fc12ffd8b58b7bb1d8b9aa6effaa"}, - {file = "mdformat-0.7.17.tar.gz", hash = "sha256:a9dbb1838d43bb1e6f03bd5dca9412c552544a9bc42d6abb5dc32adfe8ae7c0d"}, + {file = "mdformat-0.7.19-py3-none-any.whl", hash = "sha256:5c360992adc118cf1479cbbe92bb3bd66dcd7f1a5a3a2ad6675915622c678cf1"}, + {file = "mdformat-0.7.19.tar.gz", hash = "sha256:a7d22df9802383432367864da907d2d147485b5cb6872e2d66937c1333e4d58a"}, ] [package.dependencies] @@ -937,13 +1169,13 @@ test = ["coverage", "pytest (>=7.3)", "pytest-cov"] [[package]] name = "mdformat-gfm" -version = "0.3.6" +version = "0.3.7" description = "Mdformat plugin for GitHub Flavored Markdown compatibility" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "mdformat_gfm-0.3.6-py3-none-any.whl", hash = "sha256:579e3619bedd3b7123df888b6929ab8ac5dfc8205d0b67153b1633262bdafc42"}, - {file = "mdformat_gfm-0.3.6.tar.gz", hash = "sha256:b405ebf651a15c186ca06712100e33bbe72afeafb02aa4a4a28ea26cc3219678"}, + {file = "mdformat_gfm-0.3.7-py3-none-any.whl", hash = "sha256:c40966ef26e334226961ab77908dc9697ed63668f6383a18c80cca1cb4bb5c10"}, + {file = "mdformat_gfm-0.3.7.tar.gz", hash = "sha256:7deb2cd1d5334541af5454e52e116639796fc441ddc08e4415f967955950fe10"}, ] [package.dependencies] @@ -1115,66 +1347,78 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "netns" +version = "1.0" +description = "Wrapper for the Linux setns() system call" +optional = false +python-versions = "*" +files = [ + {file = "netns-1.0.tar.gz", hash = "sha256:dc994c53e415baa739072784292630724d609566fb4a60ed8feef38dd9ecdca5"}, +] + [[package]] name = "numpy" -version = "2.1.1" +version = "2.2.0" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" files = [ - {file = "numpy-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8a0e34993b510fc19b9a2ce7f31cb8e94ecf6e924a40c0c9dd4f62d0aac47d9"}, - {file = "numpy-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7dd86dfaf7c900c0bbdcb8b16e2f6ddf1eb1fe39c6c8cca6e94844ed3152a8fd"}, - {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:5889dd24f03ca5a5b1e8a90a33b5a0846d8977565e4ae003a63d22ecddf6782f"}, - {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:59ca673ad11d4b84ceb385290ed0ebe60266e356641428c845b39cd9df6713ab"}, - {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13ce49a34c44b6de5241f0b38b07e44c1b2dcacd9e36c30f9c2fcb1bb5135db7"}, - {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913cc1d311060b1d409e609947fa1b9753701dac96e6581b58afc36b7ee35af6"}, - {file = "numpy-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:caf5d284ddea7462c32b8d4a6b8af030b6c9fd5332afb70e7414d7fdded4bfd0"}, - {file = "numpy-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:57eb525e7c2a8fdee02d731f647146ff54ea8c973364f3b850069ffb42799647"}, - {file = "numpy-2.1.1-cp310-cp310-win32.whl", hash = "sha256:9a8e06c7a980869ea67bbf551283bbed2856915f0a792dc32dd0f9dd2fb56728"}, - {file = "numpy-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:d10c39947a2d351d6d466b4ae83dad4c37cd6c3cdd6d5d0fa797da56f710a6ae"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0d07841fd284718feffe7dd17a63a2e6c78679b2d386d3e82f44f0108c905550"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b5613cfeb1adfe791e8e681128f5f49f22f3fcaa942255a6124d58ca59d9528f"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0b8cc2715a84b7c3b161f9ebbd942740aaed913584cae9cdc7f8ad5ad41943d0"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:b49742cdb85f1f81e4dc1b39dcf328244f4d8d1ded95dea725b316bd2cf18c95"}, - {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8d5f8a8e3bc87334f025194c6193e408903d21ebaeb10952264943a985066ca"}, - {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d51fc141ddbe3f919e91a096ec739f49d686df8af254b2053ba21a910ae518bf"}, - {file = "numpy-2.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:98ce7fb5b8063cfdd86596b9c762bf2b5e35a2cdd7e967494ab78a1fa7f8b86e"}, - {file = "numpy-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:24c2ad697bd8593887b019817ddd9974a7f429c14a5469d7fad413f28340a6d2"}, - {file = "numpy-2.1.1-cp311-cp311-win32.whl", hash = "sha256:397bc5ce62d3fb73f304bec332171535c187e0643e176a6e9421a6e3eacef06d"}, - {file = "numpy-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:ae8ce252404cdd4de56dcfce8b11eac3c594a9c16c231d081fb705cf23bd4d9e"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c803b7934a7f59563db459292e6aa078bb38b7ab1446ca38dd138646a38203e"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6435c48250c12f001920f0751fe50c0348f5f240852cfddc5e2f97e007544cbe"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3269c9eb8745e8d975980b3a7411a98976824e1fdef11f0aacf76147f662b15f"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:fac6e277a41163d27dfab5f4ec1f7a83fac94e170665a4a50191b545721c6521"}, - {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd8f556cdc8cfe35e70efb92463082b7f43dd7e547eb071ffc36abc0ca4699b"}, - {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b9cd92c8f8e7b313b80e93cedc12c0112088541dcedd9197b5dee3738c1201"}, - {file = "numpy-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:afd9c680df4de71cd58582b51e88a61feed4abcc7530bcd3d48483f20fc76f2a"}, - {file = "numpy-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8661c94e3aad18e1ea17a11f60f843a4933ccaf1a25a7c6a9182af70610b2313"}, - {file = "numpy-2.1.1-cp312-cp312-win32.whl", hash = "sha256:950802d17a33c07cba7fd7c3dcfa7d64705509206be1606f196d179e539111ed"}, - {file = "numpy-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:3fc5eabfc720db95d68e6646e88f8b399bfedd235994016351b1d9e062c4b270"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:046356b19d7ad1890c751b99acad5e82dc4a02232013bd9a9a712fddf8eb60f5"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6e5a9cb2be39350ae6c8f79410744e80154df658d5bea06e06e0ac5bb75480d5"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d4c57b68c8ef5e1ebf47238e99bf27657511ec3f071c465f6b1bccbef12d4136"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:8ae0fd135e0b157365ac7cc31fff27f07a5572bdfc38f9c2d43b2aff416cc8b0"}, - {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981707f6b31b59c0c24bcda52e5605f9701cb46da4b86c2e8023656ad3e833cb"}, - {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ca4b53e1e0b279142113b8c5eb7d7a877e967c306edc34f3b58e9be12fda8df"}, - {file = "numpy-2.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e097507396c0be4e547ff15b13dc3866f45f3680f789c1a1301b07dadd3fbc78"}, - {file = "numpy-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7506387e191fe8cdb267f912469a3cccc538ab108471291636a96a54e599556"}, - {file = "numpy-2.1.1-cp313-cp313-win32.whl", hash = "sha256:251105b7c42abe40e3a689881e1793370cc9724ad50d64b30b358bbb3a97553b"}, - {file = "numpy-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:f212d4f46b67ff604d11fff7cc62d36b3e8714edf68e44e9760e19be38c03eb0"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:920b0911bb2e4414c50e55bd658baeb78281a47feeb064ab40c2b66ecba85553"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bab7c09454460a487e631ffc0c42057e3d8f2a9ddccd1e60c7bb8ed774992480"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:cea427d1350f3fd0d2818ce7350095c1a2ee33e30961d2f0fef48576ddbbe90f"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:e30356d530528a42eeba51420ae8bf6c6c09559051887196599d96ee5f536468"}, - {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8dfa9e94fc127c40979c3eacbae1e61fda4fe71d84869cc129e2721973231ef"}, - {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910b47a6d0635ec1bd53b88f86120a52bf56dcc27b51f18c7b4a2e2224c29f0f"}, - {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:13cc11c00000848702322af4de0147ced365c81d66053a67c2e962a485b3717c"}, - {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53e27293b3a2b661c03f79aa51c3987492bd4641ef933e366e0f9f6c9bf257ec"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7be6a07520b88214ea85d8ac8b7d6d8a1839b0b5cb87412ac9f49fa934eb15d5"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:52ac2e48f5ad847cd43c4755520a2317f3380213493b9d8a4c5e37f3b87df504"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a95ca3560a6058d6ea91d4629a83a897ee27c00630aed9d933dff191f170cd"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:99f4a9ee60eed1385a86e82288971a51e71df052ed0b2900ed30bc840c0f2e39"}, - {file = "numpy-2.1.1.tar.gz", hash = "sha256:d0cf7d55b1051387807405b3898efafa862997b4cba8aa5dbe657be794afeafd"}, + {file = "numpy-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e25507d85da11ff5066269d0bd25d06e0a0f2e908415534f3e603d2a78e4ffa"}, + {file = "numpy-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a62eb442011776e4036af5c8b1a00b706c5bc02dc15eb5344b0c750428c94219"}, + {file = "numpy-2.2.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:b606b1aaf802e6468c2608c65ff7ece53eae1a6874b3765f69b8ceb20c5fa78e"}, + {file = "numpy-2.2.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:36b2b43146f646642b425dd2027730f99bac962618ec2052932157e213a040e9"}, + {file = "numpy-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fe8f3583e0607ad4e43a954e35c1748b553bfe9fdac8635c02058023277d1b3"}, + {file = "numpy-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:122fd2fcfafdefc889c64ad99c228d5a1f9692c3a83f56c292618a59aa60ae83"}, + {file = "numpy-2.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3f2f5cddeaa4424a0a118924b988746db6ffa8565e5829b1841a8a3bd73eb59a"}, + {file = "numpy-2.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7fe4bb0695fe986a9e4deec3b6857003b4cfe5c5e4aac0b95f6a658c14635e31"}, + {file = "numpy-2.2.0-cp310-cp310-win32.whl", hash = "sha256:b30042fe92dbd79f1ba7f6898fada10bdaad1847c44f2dff9a16147e00a93661"}, + {file = "numpy-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dc1d6d66f8d37843ed281773c7174f03bf7ad826523f73435deb88ba60d2d4"}, + {file = "numpy-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9874bc2ff574c40ab7a5cbb7464bf9b045d617e36754a7bc93f933d52bd9ffc6"}, + {file = "numpy-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0da8495970f6b101ddd0c38ace92edea30e7e12b9a926b57f5fabb1ecc25bb90"}, + {file = "numpy-2.2.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0557eebc699c1c34cccdd8c3778c9294e8196df27d713706895edc6f57d29608"}, + {file = "numpy-2.2.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:3579eaeb5e07f3ded59298ce22b65f877a86ba8e9fe701f5576c99bb17c283da"}, + {file = "numpy-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40deb10198bbaa531509aad0cd2f9fadb26c8b94070831e2208e7df543562b74"}, + {file = "numpy-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2aed8fcf8abc3020d6a9ccb31dbc9e7d7819c56a348cc88fd44be269b37427e"}, + {file = "numpy-2.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a222d764352c773aa5ebde02dd84dba3279c81c6db2e482d62a3fa54e5ece69b"}, + {file = "numpy-2.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4e58666988605e251d42c2818c7d3d8991555381be26399303053b58a5bbf30d"}, + {file = "numpy-2.2.0-cp311-cp311-win32.whl", hash = "sha256:4723a50e1523e1de4fccd1b9a6dcea750c2102461e9a02b2ac55ffeae09a4410"}, + {file = "numpy-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:16757cf28621e43e252c560d25b15f18a2f11da94fea344bf26c599b9cf54b73"}, + {file = "numpy-2.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cff210198bb4cae3f3c100444c5eaa573a823f05c253e7188e1362a5555235b3"}, + {file = "numpy-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58b92a5828bd4d9aa0952492b7de803135038de47343b2aa3cc23f3b71a3dc4e"}, + {file = "numpy-2.2.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:ebe5e59545401fbb1b24da76f006ab19734ae71e703cdb4a8b347e84a0cece67"}, + {file = "numpy-2.2.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e2b8cd48a9942ed3f85b95ca4105c45758438c7ed28fff1e4ce3e57c3b589d8e"}, + {file = "numpy-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57fcc997ffc0bef234b8875a54d4058afa92b0b0c4223fc1f62f24b3b5e86038"}, + {file = "numpy-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ad7d11b309bd132d74397fcf2920933c9d1dc865487128f5c03d580f2c3d03"}, + {file = "numpy-2.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cb24cca1968b21355cc6f3da1a20cd1cebd8a023e3c5b09b432444617949085a"}, + {file = "numpy-2.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0798b138c291d792f8ea40fe3768610f3c7dd2574389e37c3f26573757c8f7ef"}, + {file = "numpy-2.2.0-cp312-cp312-win32.whl", hash = "sha256:afe8fb968743d40435c3827632fd36c5fbde633b0423da7692e426529b1759b1"}, + {file = "numpy-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:3a4199f519e57d517ebd48cb76b36c82da0360781c6a0353e64c0cac30ecaad3"}, + {file = "numpy-2.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f8c8b141ef9699ae777c6278b52c706b653bf15d135d302754f6b2e90eb30367"}, + {file = "numpy-2.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0f0986e917aca18f7a567b812ef7ca9391288e2acb7a4308aa9d265bd724bdae"}, + {file = "numpy-2.2.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:1c92113619f7b272838b8d6702a7f8ebe5edea0df48166c47929611d0b4dea69"}, + {file = "numpy-2.2.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5a145e956b374e72ad1dff82779177d4a3c62bc8248f41b80cb5122e68f22d13"}, + {file = "numpy-2.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18142b497d70a34b01642b9feabb70156311b326fdddd875a9981f34a369b671"}, + {file = "numpy-2.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7d41d1612c1a82b64697e894b75db6758d4f21c3ec069d841e60ebe54b5b571"}, + {file = "numpy-2.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a98f6f20465e7618c83252c02041517bd2f7ea29be5378f09667a8f654a5918d"}, + {file = "numpy-2.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e09d40edfdb4e260cb1567d8ae770ccf3b8b7e9f0d9b5c2a9992696b30ce2742"}, + {file = "numpy-2.2.0-cp313-cp313-win32.whl", hash = "sha256:3905a5fffcc23e597ee4d9fb3fcd209bd658c352657548db7316e810ca80458e"}, + {file = "numpy-2.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:a184288538e6ad699cbe6b24859206e38ce5fba28f3bcfa51c90d0502c1582b2"}, + {file = "numpy-2.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7832f9e8eb00be32f15fdfb9a981d6955ea9adc8574c521d48710171b6c55e95"}, + {file = "numpy-2.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f0dd071b95bbca244f4cb7f70b77d2ff3aaaba7fa16dc41f58d14854a6204e6c"}, + {file = "numpy-2.2.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:b0b227dcff8cdc3efbce66d4e50891f04d0a387cce282fe1e66199146a6a8fca"}, + {file = "numpy-2.2.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ab153263a7c5ccaf6dfe7e53447b74f77789f28ecb278c3b5d49db7ece10d6d"}, + {file = "numpy-2.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e500aba968a48e9019e42c0c199b7ec0696a97fa69037bea163b55398e390529"}, + {file = "numpy-2.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:440cfb3db4c5029775803794f8638fbdbf71ec702caf32735f53b008e1eaece3"}, + {file = "numpy-2.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a55dc7a7f0b6198b07ec0cd445fbb98b05234e8b00c5ac4874a63372ba98d4ab"}, + {file = "numpy-2.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4bddbaa30d78c86329b26bd6aaaea06b1e47444da99eddac7bf1e2fab717bd72"}, + {file = "numpy-2.2.0-cp313-cp313t-win32.whl", hash = "sha256:30bf971c12e4365153afb31fc73f441d4da157153f3400b82db32d04de1e4066"}, + {file = "numpy-2.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d35717333b39d1b6bb8433fa758a55f1081543de527171543a2b710551d40881"}, + {file = "numpy-2.2.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e12c6c1ce84628c52d6367863773f7c8c8241be554e8b79686e91a43f1733773"}, + {file = "numpy-2.2.0-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:b6207dc8fb3c8cb5668e885cef9ec7f70189bec4e276f0ff70d5aa078d32c88e"}, + {file = "numpy-2.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a50aeff71d0f97b6450d33940c7181b08be1441c6c193e678211bff11aa725e7"}, + {file = "numpy-2.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:df12a1f99b99f569a7c2ae59aa2d31724e8d835fc7f33e14f4792e3071d11221"}, + {file = "numpy-2.2.0.tar.gz", hash = "sha256:140dd80ff8981a583a60980be1a655068f8adebf7a45a06a6858c873fcdcd4a0"}, ] [[package]] @@ -1212,15 +1456,36 @@ openapi-schema-validator = ">=0.6.0,<0.7.0" [[package]] name = "packaging" -version = "24.1" +version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] +[[package]] +name = "paramiko" +version = "3.5.0" +description = "SSH2 protocol library" +optional = false +python-versions = ">=3.6" +files = [ + {file = "paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"}, + {file = "paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"}, +] + +[package.dependencies] +bcrypt = ">=3.2" +cryptography = ">=3.3" +pynacl = ">=1.5" + +[package.extras] +all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] +gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] +invoke = ["invoke (>=2.0)"] + [[package]] name = "parso" version = "0.8.4" @@ -1274,13 +1539,13 @@ ptyprocess = ">=0.5" [[package]] name = "platformdirs" -version = "4.3.2" +version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.3.2-py3-none-any.whl", hash = "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617"}, - {file = "platformdirs-4.3.2.tar.gz", hash = "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] @@ -1305,13 +1570,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prompt-toolkit" -version = "3.0.47" +version = "3.0.48" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.47-py3-none-any.whl", hash = "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10"}, - {file = "prompt_toolkit-3.0.47.tar.gz", hash = "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360"}, + {file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"}, + {file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"}, ] [package.dependencies] @@ -1319,139 +1584,124 @@ wcwidth = "*" [[package]] name = "propcache" -version = "0.2.0" +version = "0.2.1" description = "Accelerated property cache" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, - {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, - {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, - {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, - {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, - {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, - {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, - {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, - {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, - {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, - {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, - {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, - {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, - {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, - {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, + {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, + {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, + {file = "propcache-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b"}, + {file = "propcache-0.2.1-cp310-cp310-win32.whl", hash = "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4"}, + {file = "propcache-0.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba"}, + {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"}, + {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"}, + {file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"}, + {file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"}, + {file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"}, + {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"}, + {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"}, + {file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"}, + {file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"}, + {file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"}, + {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"}, + {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"}, + {file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"}, + {file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"}, + {file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"}, + {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541"}, + {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e"}, + {file = "propcache-0.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587"}, + {file = "propcache-0.2.1-cp39-cp39-win32.whl", hash = "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb"}, + {file = "propcache-0.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1"}, + {file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"}, + {file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"}, ] [[package]] name = "psutil" -version = "6.0.0" +version = "6.1.0" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, - {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, - {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, - {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, - {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, - {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, - {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, - {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, - {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, - {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, - {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, - {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, - {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, - {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, + {file = "psutil-6.1.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ff34df86226c0227c52f38b919213157588a678d049688eded74c76c8ba4a5d0"}, + {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c0e0c00aa18ca2d3b2b991643b799a15fc8f0563d2ebb6040f64ce8dc027b942"}, + {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:000d1d1ebd634b4efb383f4034437384e44a6d455260aaee2eca1e9c1b55f047"}, + {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5cd2bcdc75b452ba2e10f0e8ecc0b57b827dd5d7aaffbc6821b2a9a242823a76"}, + {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:045f00a43c737f960d273a83973b2511430d61f283a44c96bf13a6e829ba8fdc"}, + {file = "psutil-6.1.0-cp27-none-win32.whl", hash = "sha256:9118f27452b70bb1d9ab3198c1f626c2499384935aaf55388211ad982611407e"}, + {file = "psutil-6.1.0-cp27-none-win_amd64.whl", hash = "sha256:a8506f6119cff7015678e2bce904a4da21025cc70ad283a53b099e7620061d85"}, + {file = "psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688"}, + {file = "psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e"}, + {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38"}, + {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b"}, + {file = "psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a"}, + {file = "psutil-6.1.0-cp36-cp36m-win32.whl", hash = "sha256:6d3fbbc8d23fcdcb500d2c9f94e07b1342df8ed71b948a2649b5cb060a7c94ca"}, + {file = "psutil-6.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1209036fbd0421afde505a4879dee3b2fd7b1e14fee81c0069807adcbbcca747"}, + {file = "psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e"}, + {file = "psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be"}, + {file = "psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a"}, ] [package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] +dev = ["black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "wheel"] +test = ["pytest", "pytest-xdist", "setuptools"] [[package]] name = "ptyprocess" @@ -1478,6 +1728,17 @@ files = [ [package.extras] tests = ["pytest"] +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + [[package]] name = "pygments" version = "2.18.0" @@ -1494,17 +1755,17 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" -version = "3.2.7" +version = "3.3.2" description = "python code static checker" optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" files = [ - {file = "pylint-3.2.7-py3-none-any.whl", hash = "sha256:02f4aedeac91be69fb3b4bea997ce580a4ac68ce58b89eaefeaf06749df73f4b"}, - {file = "pylint-3.2.7.tar.gz", hash = "sha256:1b7a721b575eaeaa7d39db076b6e7743c993ea44f57979127c517c6c572c803e"}, + {file = "pylint-3.3.2-py3-none-any.whl", hash = "sha256:77f068c287d49b8683cd7c6e624243c74f92890f767f106ffa1ddf3c0a54cb7a"}, + {file = "pylint-3.3.2.tar.gz", hash = "sha256:9ec054ec992cd05ad30a6df1676229739a73f8feeabf3912c995d17601052b01"}, ] [package.dependencies] -astroid = ">=3.2.4,<=3.3.0-dev0" +astroid = ">=3.3.5,<=3.4.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, @@ -1521,15 +1782,41 @@ tomlkit = ">=0.10.1" spelling = ["pyenchant (>=3.2,<4.0)"] testutils = ["gitpython (>3)"] +[[package]] +name = "pynacl" +version = "1.5.0" +description = "Python binding to the Networking and Cryptography (NaCl) library" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, + {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, +] + +[package.dependencies] +cffi = ">=1.4.1" + +[package.extras] +docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] +tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] + [[package]] name = "pytest" -version = "8.3.3" +version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, - {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, + {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, + {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, ] [package.dependencies] @@ -1767,114 +2054,114 @@ six = "*" [[package]] name = "rpds-py" -version = "0.20.0" +version = "0.22.3" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "rpds_py-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2"}, - {file = "rpds_py-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140"}, - {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f"}, - {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce"}, - {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94"}, - {file = "rpds_py-0.20.0-cp310-none-win32.whl", hash = "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee"}, - {file = "rpds_py-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399"}, - {file = "rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489"}, - {file = "rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3"}, - {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272"}, - {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad"}, - {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58"}, - {file = "rpds_py-0.20.0-cp311-none-win32.whl", hash = "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0"}, - {file = "rpds_py-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c"}, - {file = "rpds_py-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6"}, - {file = "rpds_py-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef"}, - {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821"}, - {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940"}, - {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174"}, - {file = "rpds_py-0.20.0-cp312-none-win32.whl", hash = "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139"}, - {file = "rpds_py-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585"}, - {file = "rpds_py-0.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29"}, - {file = "rpds_py-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f"}, - {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c"}, - {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2"}, - {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57"}, - {file = "rpds_py-0.20.0-cp313-none-win32.whl", hash = "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a"}, - {file = "rpds_py-0.20.0-cp313-none-win_amd64.whl", hash = "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2"}, - {file = "rpds_py-0.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24"}, - {file = "rpds_py-0.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8"}, - {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e"}, - {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253"}, - {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a"}, - {file = "rpds_py-0.20.0-cp38-none-win32.whl", hash = "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5"}, - {file = "rpds_py-0.20.0-cp38-none-win_amd64.whl", hash = "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232"}, - {file = "rpds_py-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22"}, - {file = "rpds_py-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580"}, - {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b"}, - {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420"}, - {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b"}, - {file = "rpds_py-0.20.0-cp39-none-win32.whl", hash = "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7"}, - {file = "rpds_py-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8"}, - {file = "rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121"}, + {file = "rpds_py-0.22.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967"}, + {file = "rpds_py-0.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf"}, + {file = "rpds_py-0.22.3-cp310-cp310-win32.whl", hash = "sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652"}, + {file = "rpds_py-0.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8"}, + {file = "rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f"}, + {file = "rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a"}, + {file = "rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64"}, + {file = "rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c"}, + {file = "rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e"}, + {file = "rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7"}, + {file = "rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627"}, + {file = "rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4"}, + {file = "rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84"}, + {file = "rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f"}, + {file = "rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de"}, + {file = "rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9"}, + {file = "rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333"}, + {file = "rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730"}, + {file = "rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf"}, + {file = "rpds_py-0.22.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea"}, + {file = "rpds_py-0.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520"}, + {file = "rpds_py-0.22.3-cp39-cp39-win32.whl", hash = "sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9"}, + {file = "rpds_py-0.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6"}, + {file = "rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d"}, ] [[package]] @@ -1897,61 +2184,52 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] [[package]] name = "ruamel-yaml-clib" -version = "0.2.8" +version = "0.2.12" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" files = [ - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"}, - {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"}, - {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b"}, + {file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"}, ] [[package]] @@ -2006,99 +2284,96 @@ test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.3 [[package]] name = "setproctitle" -version = "1.3.3" +version = "1.3.4" description = "A Python module to customize the process title" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "setproctitle-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:897a73208da48db41e687225f355ce993167079eda1260ba5e13c4e53be7f754"}, - {file = "setproctitle-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c331e91a14ba4076f88c29c777ad6b58639530ed5b24b5564b5ed2fd7a95452"}, - {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbbd6c7de0771c84b4aa30e70b409565eb1fc13627a723ca6be774ed6b9d9fa3"}, - {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c05ac48ef16ee013b8a326c63e4610e2430dbec037ec5c5b58fcced550382b74"}, - {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1342f4fdb37f89d3e3c1c0a59d6ddbedbde838fff5c51178a7982993d238fe4f"}, - {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc74e84fdfa96821580fb5e9c0b0777c1c4779434ce16d3d62a9c4d8c710df39"}, - {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9617b676b95adb412bb69645d5b077d664b6882bb0d37bfdafbbb1b999568d85"}, - {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6a249415f5bb88b5e9e8c4db47f609e0bf0e20a75e8d744ea787f3092ba1f2d0"}, - {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:38da436a0aaace9add67b999eb6abe4b84397edf4a78ec28f264e5b4c9d53cd5"}, - {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:da0d57edd4c95bf221b2ebbaa061e65b1788f1544977288bdf95831b6e44e44d"}, - {file = "setproctitle-1.3.3-cp310-cp310-win32.whl", hash = "sha256:a1fcac43918b836ace25f69b1dca8c9395253ad8152b625064415b1d2f9be4fb"}, - {file = "setproctitle-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:200620c3b15388d7f3f97e0ae26599c0c378fdf07ae9ac5a13616e933cbd2086"}, - {file = "setproctitle-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:334f7ed39895d692f753a443102dd5fed180c571eb6a48b2a5b7f5b3564908c8"}, - {file = "setproctitle-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:950f6476d56ff7817a8fed4ab207727fc5260af83481b2a4b125f32844df513a"}, - {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:195c961f54a09eb2acabbfc90c413955cf16c6e2f8caa2adbf2237d1019c7dd8"}, - {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f05e66746bf9fe6a3397ec246fe481096664a9c97eb3fea6004735a4daf867fd"}, - {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5901a31012a40ec913265b64e48c2a4059278d9f4e6be628441482dd13fb8b5"}, - {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64286f8a995f2cd934082b398fc63fca7d5ffe31f0e27e75b3ca6b4efda4e353"}, - {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:184239903bbc6b813b1a8fc86394dc6ca7d20e2ebe6f69f716bec301e4b0199d"}, - {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:664698ae0013f986118064b6676d7dcd28fefd0d7d5a5ae9497cbc10cba48fa5"}, - {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e5119a211c2e98ff18b9908ba62a3bd0e3fabb02a29277a7232a6fb4b2560aa0"}, - {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:417de6b2e214e837827067048f61841f5d7fc27926f2e43954567094051aff18"}, - {file = "setproctitle-1.3.3-cp311-cp311-win32.whl", hash = "sha256:6a143b31d758296dc2f440175f6c8e0b5301ced3b0f477b84ca43cdcf7f2f476"}, - {file = "setproctitle-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a680d62c399fa4b44899094027ec9a1bdaf6f31c650e44183b50d4c4d0ccc085"}, - {file = "setproctitle-1.3.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d4460795a8a7a391e3567b902ec5bdf6c60a47d791c3b1d27080fc203d11c9dc"}, - {file = "setproctitle-1.3.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bdfd7254745bb737ca1384dee57e6523651892f0ea2a7344490e9caefcc35e64"}, - {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477d3da48e216d7fc04bddab67b0dcde633e19f484a146fd2a34bb0e9dbb4a1e"}, - {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab2900d111e93aff5df9fddc64cf51ca4ef2c9f98702ce26524f1acc5a786ae7"}, - {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:088b9efc62d5aa5d6edf6cba1cf0c81f4488b5ce1c0342a8b67ae39d64001120"}, - {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6d50252377db62d6a0bb82cc898089916457f2db2041e1d03ce7fadd4a07381"}, - {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:87e668f9561fd3a457ba189edfc9e37709261287b52293c115ae3487a24b92f6"}, - {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:287490eb90e7a0ddd22e74c89a92cc922389daa95babc833c08cf80c84c4df0a"}, - {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:4fe1c49486109f72d502f8be569972e27f385fe632bd8895f4730df3c87d5ac8"}, - {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4a6ba2494a6449b1f477bd3e67935c2b7b0274f2f6dcd0f7c6aceae10c6c6ba3"}, - {file = "setproctitle-1.3.3-cp312-cp312-win32.whl", hash = "sha256:2df2b67e4b1d7498632e18c56722851ba4db5d6a0c91aaf0fd395111e51cdcf4"}, - {file = "setproctitle-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:f38d48abc121263f3b62943f84cbaede05749047e428409c2c199664feb6abc7"}, - {file = "setproctitle-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:816330675e3504ae4d9a2185c46b573105d2310c20b19ea2b4596a9460a4f674"}, - {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68f960bc22d8d8e4ac886d1e2e21ccbd283adcf3c43136161c1ba0fa509088e0"}, - {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00e6e7adff74796ef12753ff399491b8827f84f6c77659d71bd0b35870a17d8f"}, - {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53bc0d2358507596c22b02db079618451f3bd720755d88e3cccd840bafb4c41c"}, - {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad6d20f9541f5f6ac63df553b6d7a04f313947f550eab6a61aa758b45f0d5657"}, - {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c1c84beab776b0becaa368254801e57692ed749d935469ac10e2b9b825dbdd8e"}, - {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:507e8dc2891021350eaea40a44ddd887c9f006e6b599af8d64a505c0f718f170"}, - {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b1067647ac7aba0b44b591936118a22847bda3c507b0a42d74272256a7a798e9"}, - {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2e71f6365744bf53714e8bd2522b3c9c1d83f52ffa6324bd7cbb4da707312cd8"}, - {file = "setproctitle-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:7f1d36a1e15a46e8ede4e953abb104fdbc0845a266ec0e99cc0492a4364f8c44"}, - {file = "setproctitle-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9a402881ec269d0cc9c354b149fc29f9ec1a1939a777f1c858cdb09c7a261df"}, - {file = "setproctitle-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ff814dea1e5c492a4980e3e7d094286077054e7ea116cbeda138819db194b2cd"}, - {file = "setproctitle-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:accb66d7b3ccb00d5cd11d8c6e07055a4568a24c95cf86109894dcc0c134cc89"}, - {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:554eae5a5b28f02705b83a230e9d163d645c9a08914c0ad921df363a07cf39b1"}, - {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a911b26264dbe9e8066c7531c0591cfab27b464459c74385b276fe487ca91c12"}, - {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2982efe7640c4835f7355fdb4da313ad37fb3b40f5c69069912f8048f77b28c8"}, - {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df3f4274b80709d8bcab2f9a862973d453b308b97a0b423a501bcd93582852e3"}, - {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:af2c67ae4c795d1674a8d3ac1988676fa306bcfa1e23fddb5e0bd5f5635309ca"}, - {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:af4061f67fd7ec01624c5e3c21f6b7af2ef0e6bab7fbb43f209e6506c9ce0092"}, - {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:37a62cbe16d4c6294e84670b59cf7adcc73faafe6af07f8cb9adaf1f0e775b19"}, - {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a83ca086fbb017f0d87f240a8f9bbcf0809f3b754ee01cec928fff926542c450"}, - {file = "setproctitle-1.3.3-cp38-cp38-win32.whl", hash = "sha256:059f4ce86f8cc92e5860abfc43a1dceb21137b26a02373618d88f6b4b86ba9b2"}, - {file = "setproctitle-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:ab92e51cd4a218208efee4c6d37db7368fdf182f6e7ff148fb295ecddf264287"}, - {file = "setproctitle-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c7951820b77abe03d88b114b998867c0f99da03859e5ab2623d94690848d3e45"}, - {file = "setproctitle-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc94cf128676e8fac6503b37763adb378e2b6be1249d207630f83fc325d9b11"}, - {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f5d9027eeda64d353cf21a3ceb74bb1760bd534526c9214e19f052424b37e42"}, - {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e4a8104db15d3462e29d9946f26bed817a5b1d7a47eabca2d9dc2b995991503"}, - {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c32c41ace41f344d317399efff4cffb133e709cec2ef09c99e7a13e9f3b9483c"}, - {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbf16381c7bf7f963b58fb4daaa65684e10966ee14d26f5cc90f07049bfd8c1e"}, - {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e18b7bd0898398cc97ce2dfc83bb192a13a087ef6b2d5a8a36460311cb09e775"}, - {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69d565d20efe527bd8a9b92e7f299ae5e73b6c0470f3719bd66f3cd821e0d5bd"}, - {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ddedd300cd690a3b06e7eac90ed4452348b1348635777ce23d460d913b5b63c3"}, - {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:415bfcfd01d1fbf5cbd75004599ef167a533395955305f42220a585f64036081"}, - {file = "setproctitle-1.3.3-cp39-cp39-win32.whl", hash = "sha256:21112fcd2195d48f25760f0eafa7a76510871bbb3b750219310cf88b04456ae3"}, - {file = "setproctitle-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:5a740f05d0968a5a17da3d676ce6afefebeeeb5ce137510901bf6306ba8ee002"}, - {file = "setproctitle-1.3.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6b9e62ddb3db4b5205c0321dd69a406d8af9ee1693529d144e86bd43bcb4b6c0"}, - {file = "setproctitle-1.3.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e3b99b338598de0bd6b2643bf8c343cf5ff70db3627af3ca427a5e1a1a90dd9"}, - {file = "setproctitle-1.3.3-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ae9a02766dad331deb06855fb7a6ca15daea333b3967e214de12cfae8f0ef5"}, - {file = "setproctitle-1.3.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:200ede6fd11233085ba9b764eb055a2a191fb4ffb950c68675ac53c874c22e20"}, - {file = "setproctitle-1.3.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0d3a953c50776751e80fe755a380a64cb14d61e8762bd43041ab3f8cc436092f"}, - {file = "setproctitle-1.3.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5e08e232b78ba3ac6bc0d23ce9e2bee8fad2be391b7e2da834fc9a45129eb87"}, - {file = "setproctitle-1.3.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1da82c3e11284da4fcbf54957dafbf0655d2389cd3d54e4eaba636faf6d117a"}, - {file = "setproctitle-1.3.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:aeaa71fb9568ebe9b911ddb490c644fbd2006e8c940f21cb9a1e9425bd709574"}, - {file = "setproctitle-1.3.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:59335d000c6250c35989394661eb6287187854e94ac79ea22315469ee4f4c244"}, - {file = "setproctitle-1.3.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3ba57029c9c50ecaf0c92bb127224cc2ea9fda057b5d99d3f348c9ec2855ad3"}, - {file = "setproctitle-1.3.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d876d355c53d975c2ef9c4f2487c8f83dad6aeaaee1b6571453cb0ee992f55f6"}, - {file = "setproctitle-1.3.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:224602f0939e6fb9d5dd881be1229d485f3257b540f8a900d4271a2c2aa4e5f4"}, - {file = "setproctitle-1.3.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d7f27e0268af2d7503386e0e6be87fb9b6657afd96f5726b733837121146750d"}, - {file = "setproctitle-1.3.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5e7266498cd31a4572378c61920af9f6b4676a73c299fce8ba93afd694f8ae7"}, - {file = "setproctitle-1.3.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33c5609ad51cd99d388e55651b19148ea99727516132fb44680e1f28dd0d1de9"}, - {file = "setproctitle-1.3.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:eae8988e78192fd1a3245a6f4f382390b61bce6cfcc93f3809726e4c885fa68d"}, - {file = "setproctitle-1.3.3.tar.gz", hash = "sha256:c913e151e7ea01567837ff037a23ca8740192880198b7fbb90b16d181607caae"}, + {file = "setproctitle-1.3.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0f6661a69c68349172ba7b4d5dd65fec2b0917abc99002425ad78c3e58cf7595"}, + {file = "setproctitle-1.3.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:754bac5e470adac7f7ec2239c485cd0b75f8197ca8a5b86ffb20eb3a3676cc42"}, + {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7bc7088c15150745baf66db62a4ced4507d44419eb66207b609f91b64a682af"}, + {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a46ef3ecf61e4840fbc1145fdd38acf158d0da7543eda7b773ed2b30f75c2830"}, + {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcb09d5c0ffa043254ec9a734a73f3791fec8bf6333592f906bb2e91ed2af1a"}, + {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06c16b7a91cdc5d700271899e4383384a61aae83a3d53d0e2e5a266376083342"}, + {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9f9732e59863eaeedd3feef94b2b216cb86d40dda4fad2d0f0aaec3b31592716"}, + {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e152f4ab9ea1632b5fecdd87cee354f2b2eb6e2dfc3aceb0eb36a01c1e12f94c"}, + {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:020ea47a79b2bbd7bd7b94b85ca956ba7cb026e82f41b20d2e1dac4008cead25"}, + {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c52b12b10e4057fc302bd09cb3e3f28bb382c30c044eb3396e805179a8260e4"}, + {file = "setproctitle-1.3.4-cp310-cp310-win32.whl", hash = "sha256:a65a147f545f3fac86f11acb2d0b316d3e78139a9372317b7eb50561b2817ba0"}, + {file = "setproctitle-1.3.4-cp310-cp310-win_amd64.whl", hash = "sha256:66821fada6426998762a3650a37fba77e814a249a95b1183011070744aff47f6"}, + {file = "setproctitle-1.3.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0f749f07002c2d6fecf37cedc43207a88e6c651926a470a5f229070cf791879"}, + {file = "setproctitle-1.3.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:90ea8d302a5d30b948451d146e94674a3c5b020cc0ced9a1c28f8ddb0f203a5d"}, + {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f859c88193ed466bee4eb9d45fbc29d2253e6aa3ccd9119c9a1d8d95f409a60d"}, + {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3afa5a0ed08a477ded239c05db14c19af585975194a00adf594d48533b23701"}, + {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a78fce9018cc3e9a772b6537bbe3fe92380acf656c9f86db2f45e685af376e"}, + {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d758e2eed2643afac5f2881542fbb5aa97640b54be20d0a5ed0691d02f0867d"}, + {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ef133a1a2ee378d549048a12d56f4ef0e2b9113b0b25b6b77821e9af94d50634"}, + {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1d2a154b79d5fb42d1eff06e05e22f0e8091261d877dd47b37d31352b74ecc37"}, + {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:202eae632815571297833876a0f407d0d9c7ad9d843b38adbe687fe68c5192ee"}, + {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2b0080819859e80a7776ac47cf6accb4b7ad313baf55fabac89c000480dcd103"}, + {file = "setproctitle-1.3.4-cp311-cp311-win32.whl", hash = "sha256:9c9d7d1267dee8c6627963d9376efa068858cfc8f573c083b1b6a2d297a8710f"}, + {file = "setproctitle-1.3.4-cp311-cp311-win_amd64.whl", hash = "sha256:475986ddf6df65d619acd52188336a20f616589403f5a5ceb3fc70cdc137037a"}, + {file = "setproctitle-1.3.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d06990dcfcd41bb3543c18dd25c8476fbfe1f236757f42fef560f6aa03ac8dfc"}, + {file = "setproctitle-1.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:317218c9d8b17a010ab2d2f0851e8ef584077a38b1ba2b7c55c9e44e79a61e73"}, + {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb5fefb53b9d9f334a5d9ec518a36b92a10b936011ac8a6b6dffd60135f16459"}, + {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0855006261635e8669646c7c304b494b6df0a194d2626683520103153ad63cc9"}, + {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a88e466fcaee659679c1d64dcb2eddbcb4bfadffeb68ba834d9c173a25b6184"}, + {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f963b6ed8ba33eda374a98d979e8a0eaf21f891b6e334701693a2c9510613c4c"}, + {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:122c2e05697fa91f5d23f00bbe98a9da1bd457b32529192e934095fadb0853f1"}, + {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:1bba0a866f5895d5b769d8c36b161271c7fd407e5065862ab80ff91c29fbe554"}, + {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:97f1f861998e326e640708488c442519ad69046374b2c3fe9bcc9869b387f23c"}, + {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:726aee40357d4bdb70115442cb85ccc8e8bc554fc0bbbaa3a57cbe81df42287d"}, + {file = "setproctitle-1.3.4-cp312-cp312-win32.whl", hash = "sha256:04d6ba8b816dbb0bfd62000b0c3e583160893e6e8c4233e1dca1a9ae4d95d924"}, + {file = "setproctitle-1.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:9c76e43cb351ba8887371240b599925cdf3ecececc5dfb7125c71678e7722c55"}, + {file = "setproctitle-1.3.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d6e3b177e634aa6bbbfbf66d097b6d1cdb80fc60e912c7d8bace2e45699c07dd"}, + {file = "setproctitle-1.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6b17655a5f245b416e127e02087ea6347a48821cc4626bc0fd57101bfcd88afc"}, + {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa5057a86df920faab8ee83960b724bace01a3231eb8e3f2c93d78283504d598"}, + {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149fdfb8a26a555780c4ce53c92e6d3c990ef7b30f90a675eca02e83c6d5f76d"}, + {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ded03546938a987f463c68ab98d683af87a83db7ac8093bbc179e77680be5ba2"}, + {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ab9f5b7f2bbc1754bc6292d9a7312071058e5a891b0391e6d13b226133f36aa"}, + {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0b19813c852566fa031902124336fa1f080c51e262fc90266a8c3d65ca47b74c"}, + {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:db78b645dc63c0ccffca367a498f3b13492fb106a2243a1e998303ba79c996e2"}, + {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b669aaac70bd9f03c070270b953f78d9ee56c4af6f0ff9f9cd3e6d1878c10b40"}, + {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6dc3d656702791565994e64035a208be56b065675a5bc87b644c657d6d9e2232"}, + {file = "setproctitle-1.3.4-cp313-cp313-win32.whl", hash = "sha256:091f682809a4d12291cf0205517619d2e7014986b7b00ebecfde3d76f8ae5a8f"}, + {file = "setproctitle-1.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:adcd6ba863a315702184d92d3d3bbff290514f24a14695d310f02ae5e28bd1f7"}, + {file = "setproctitle-1.3.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:acf41cf91bbc5a36d1fa4455a818bb02bf2a4ccfed2f892ba166ba2fcbb0ec8a"}, + {file = "setproctitle-1.3.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ceb3ce3262b0e8e088e4117175591b7a82b3bdc5e52e33b1e74778b5fb53fd38"}, + {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b2ef636a6a25fe7f3d5a064bea0116b74a4c8c7df9646b17dc7386c439a26cf"}, + {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28b8614de08679ae95bc4e8d6daaef6b61afdf027fa0d23bf13d619000286b3c"}, + {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24f3c8be826a7d44181eac2269b15b748b76d98cd9a539d4c69f09321dcb5c12"}, + {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc9d79b1bf833af63b7c720a6604eb16453ac1ad4e718eb8b59d1f97d986b98c"}, + {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fb693000b65842c85356b667d057ae0d0bac6519feca7e1c437cc2cfeb0afc59"}, + {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:a166251b8fbc6f2755e2ce9d3c11e9edb0c0c7d2ed723658ff0161fbce26ac1c"}, + {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:0361428e6378911a378841509c56ba472d991cbed1a7e3078ec0cacc103da44a"}, + {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:62d66e0423e3bd520b4c897063506b309843a8d07343fbfad04197e91a4edd28"}, + {file = "setproctitle-1.3.4-cp38-cp38-win32.whl", hash = "sha256:5edd01909348f3b0b2da329836d6b5419cd4869fec2e118e8ff3275b38af6267"}, + {file = "setproctitle-1.3.4-cp38-cp38-win_amd64.whl", hash = "sha256:59e0dda9ad245921af0328035a961767026e1fa94bb65957ab0db0a0491325d6"}, + {file = "setproctitle-1.3.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bdaaa81a6e95a0a19fba0285f10577377f3503ae4e9988b403feba79da3e2f80"}, + {file = "setproctitle-1.3.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ee5b19a2d794463bcc19153dfceede7beec784b4cf7967dec0bc0fc212ab3a3"}, + {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3058a1bb0c767b3a6ccbb38b27ef870af819923eb732e21e44a3f300370fe159"}, + {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a97d37ee4fe0d1c6e87d2a97229c27a88787a8f4ebfbdeee95f91b818e52efe"}, + {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e61dd7d05da11fc69bb86d51f1e0ee08f74dccf3ecf884c94de41135ffdc75d"}, + {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb115d53dc2a1299ae72f1119c96a556db36073bacb6da40c47ece5db0d9587"}, + {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:342570716e2647a51ea859b8a9126da9dc1a96a0153c9c0a3514effd60ab57ad"}, + {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0ad212ae2b03951367a69584af034579b34e1e4199a75d377ef9f8e08ee299b1"}, + {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4afcb38e22122465013f4621b7e9ff8d42a7a48ae0ffeb94133a806cb91b4aad"}, + {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:30bb223e6c3f95ad9e9bb2a113292759e947d1cfd60dbd4adb55851c370006b2"}, + {file = "setproctitle-1.3.4-cp39-cp39-win32.whl", hash = "sha256:5f0521ed3bb9f02e9486573ea95e2062cd6bf036fa44e640bd54a06f22d85f35"}, + {file = "setproctitle-1.3.4-cp39-cp39-win_amd64.whl", hash = "sha256:0baadeb27f9e97e65922b4151f818b19c311d30b9efdb62af0e53b3db4006ce2"}, + {file = "setproctitle-1.3.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:939d364a187b2adfbf6ae488664277e717d56c7951a4ddeb4f23b281bc50bfe5"}, + {file = "setproctitle-1.3.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb8a6a19be0cbf6da6fcbf3698b76c8af03fe83e4bd77c96c3922be3b88bf7da"}, + {file = "setproctitle-1.3.4-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:779006f9e1aade9522a40e8d9635115ab15dd82b7af8e655967162e9c01e2573"}, + {file = "setproctitle-1.3.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5519f2a7b8c535b0f1f77b30441476571373add72008230c81211ee17b423b57"}, + {file = "setproctitle-1.3.4-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:743836d484151334ebba1490d6907ca9e718fe815dcd5756f2a01bc3067d099c"}, + {file = "setproctitle-1.3.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abda20aff8d1751e48d7967fa8945fef38536b82366c49be39b83678d4be3893"}, + {file = "setproctitle-1.3.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a2041b5788ce52f218b5be94af458e04470f997ab46fdebd57cf0b8374cc20e"}, + {file = "setproctitle-1.3.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2c3b1ce68746557aa6e6f4547e76883925cdc7f8d7c7a9f518acd203f1265ca5"}, + {file = "setproctitle-1.3.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0b6a4cbabf024cb263a45bdef425760f14470247ff223f0ec51699ca9046c0fe"}, + {file = "setproctitle-1.3.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e55d7ecc68bdc80de5a553691a3ed260395d5362c19a266cf83cbb4e046551f"}, + {file = "setproctitle-1.3.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02ca3802902d91a89957f79da3ec44b25b5804c88026362cb85eea7c1fbdefd1"}, + {file = "setproctitle-1.3.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:47669fc8ed8b27baa2d698104732234b5389f6a59c37c046f6bcbf9150f7a94e"}, + {file = "setproctitle-1.3.4.tar.gz", hash = "sha256:3b40d32a3e1f04e94231ed6dfee0da9e43b4f9c6b5450d53e6dd7754c34e0c50"}, ] [package.extras] @@ -2116,24 +2391,24 @@ files = [ [[package]] name = "sh" -version = "2.0.7" +version = "2.1.0" description = "Python subprocess replacement" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "sh-2.0.7-py3-none-any.whl", hash = "sha256:2f2f79a65abd00696cf2e9ad26508cf8abb6dba5745f40255f1c0ded2876926d"}, - {file = "sh-2.0.7.tar.gz", hash = "sha256:029d45198902bfb967391eccfd13a88d92f7cebd200411e93f99ebacc6afbb35"}, + {file = "sh-2.1.0-py3-none-any.whl", hash = "sha256:bf5e44178dd96a542126c2774e9b7ab1d89bfe0e2ef84d92e6d0ed7358d63d01"}, + {file = "sh-2.1.0.tar.gz", hash = "sha256:7e27301c574bec8ca5bf6f211851357526455ee97cd27a7c4c6cc5e2375399cb"}, ] [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] @@ -2172,13 +2447,43 @@ test = ["pytest", "tornado (>=4.5)", "typeguard"] [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] @@ -2260,95 +2565,169 @@ files = [ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] +[[package]] +name = "wrapt" +version = "1.17.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +files = [ + {file = "wrapt-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301"}, + {file = "wrapt-1.17.0-cp310-cp310-win32.whl", hash = "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22"}, + {file = "wrapt-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575"}, + {file = "wrapt-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b"}, + {file = "wrapt-1.17.0-cp311-cp311-win32.whl", hash = "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346"}, + {file = "wrapt-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a"}, + {file = "wrapt-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4"}, + {file = "wrapt-1.17.0-cp312-cp312-win32.whl", hash = "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635"}, + {file = "wrapt-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7"}, + {file = "wrapt-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a"}, + {file = "wrapt-1.17.0-cp313-cp313-win32.whl", hash = "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045"}, + {file = "wrapt-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838"}, + {file = "wrapt-1.17.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab"}, + {file = "wrapt-1.17.0-cp313-cp313t-win32.whl", hash = "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf"}, + {file = "wrapt-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a"}, + {file = "wrapt-1.17.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f"}, + {file = "wrapt-1.17.0-cp38-cp38-win32.whl", hash = "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea"}, + {file = "wrapt-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed"}, + {file = "wrapt-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0"}, + {file = "wrapt-1.17.0-cp39-cp39-win32.whl", hash = "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88"}, + {file = "wrapt-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977"}, + {file = "wrapt-1.17.0-py3-none-any.whl", hash = "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371"}, + {file = "wrapt-1.17.0.tar.gz", hash = "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801"}, +] + [[package]] name = "yarl" -version = "1.17.2" +version = "1.18.3" description = "Yet another URL library" optional = false python-versions = ">=3.9" files = [ - {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff"}, - {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151"}, - {file = "yarl-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b"}, - {file = "yarl-1.17.2-cp310-cp310-win32.whl", hash = "sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673"}, - {file = "yarl-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071"}, - {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500"}, - {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6"}, - {file = "yarl-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0"}, - {file = "yarl-1.17.2-cp311-cp311-win32.whl", hash = "sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628"}, - {file = "yarl-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c"}, - {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9"}, - {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909"}, - {file = "yarl-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20"}, - {file = "yarl-1.17.2-cp312-cp312-win32.whl", hash = "sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b"}, - {file = "yarl-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3"}, - {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211"}, - {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c"}, - {file = "yarl-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2"}, - {file = "yarl-1.17.2-cp313-cp313-win32.whl", hash = "sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28"}, - {file = "yarl-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3"}, - {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa"}, - {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca"}, - {file = "yarl-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8"}, - {file = "yarl-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130"}, - {file = "yarl-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed"}, - {file = "yarl-1.17.2-py3-none-any.whl", hash = "sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b"}, - {file = "yarl-1.17.2.tar.gz", hash = "sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178"}, + {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, + {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, + {file = "yarl-1.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690"}, + {file = "yarl-1.18.3-cp310-cp310-win32.whl", hash = "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6"}, + {file = "yarl-1.18.3-cp310-cp310-win_amd64.whl", hash = "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8"}, + {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069"}, + {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193"}, + {file = "yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a"}, + {file = "yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1"}, + {file = "yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5"}, + {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50"}, + {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576"}, + {file = "yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285"}, + {file = "yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2"}, + {file = "yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477"}, + {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb"}, + {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa"}, + {file = "yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8"}, + {file = "yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d"}, + {file = "yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c"}, + {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04"}, + {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719"}, + {file = "yarl-1.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1"}, + {file = "yarl-1.18.3-cp39-cp39-win32.whl", hash = "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5"}, + {file = "yarl-1.18.3-cp39-cp39-win_amd64.whl", hash = "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9"}, + {file = "yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b"}, + {file = "yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1"}, ] [package.dependencies] @@ -2359,4 +2738,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.10.0" -content-hash = "e38bfcb8811fb9b774956ed4b0e82603dbe5b66d8cb5bc4af6ed86417a9d5d1d" +content-hash = "c3b6e2c1d9a0a7926b61ca38f9e91fd1c1c0519a1703d6eaa0fd07fcf5898cbd" diff --git a/tools/devctr/pyproject.toml b/tools/devctr/pyproject.toml index a4f7178aa5d..188a3b315bd 100644 --- a/tools/devctr/pyproject.toml +++ b/tools/devctr/pyproject.toml @@ -10,6 +10,7 @@ aws-embedded-metrics = "^3.1.0" black = "^24.3.0" # Gitlint locks this to 8.1.3. Lock from our side too to prevent different versions click = "8.1.3" +fabric = "^3.2.2" filelock = "^3.13.4" gitlint = "^0.19.1" ipython = "^8.15.0" @@ -18,6 +19,7 @@ mdformat = "^0.7.17" mdformat-gfm = "^0.3.5" mdformat-footnote = "^0.1.1" mdformat-frontmatter = "^2.0.8" +netns = "^1.0.0" openapi-spec-validator = "^0.7.1" psutil = "^6.0.0" pylint = "^3" From 36937ed30797a931fab133e3f63ec6eda4450a03 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 9 Dec 2024 17:38:01 +0000 Subject: [PATCH 38/78] chore: bump devctr version accumulate all the dockerfile changes into a new devctr version Signed-off-by: Patrick Roy --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 662c2583450..3b4d89ec392 100755 --- a/tools/devtool +++ b/tools/devtool @@ -68,7 +68,7 @@ DEVCTR_IMAGE_NO_TAG="public.ecr.aws/firecracker/fcuvm" # Development container tag -DEVCTR_IMAGE_TAG=${DEVCTR_IMAGE_TAG:-v75} +DEVCTR_IMAGE_TAG=${DEVCTR_IMAGE_TAG:-v76} # Development container image (name:tag) # This should be updated whenever we upgrade the development container. From 48be9c9a58b2dcca2888a0386db4e035516ef2ae Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 14:01:49 +0000 Subject: [PATCH 39/78] chore: update kvm-ioctls This is needed to work around a bug in `VmFd::create_device`, where undefined behavior caused a miscompilation on newer rust toolchains. Signed-off-by: Patrick Roy --- Cargo.lock | 6 +++--- src/vmm/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f31b84f68c9..28561608a6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "acpi_tables" @@ -832,9 +832,9 @@ dependencies = [ [[package]] name = "kvm-ioctls" -version = "0.19.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "337d1afa126368bbd6a5c328048f71a69a737e9afe7e436b392a8f8d770c9171" +checksum = "e013ae7fcd2c6a8f384104d16afe7ea02969301ea2bb2a56e44b011ebc907cab" dependencies = [ "bitflags 2.6.0", "kvm-bindings", diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 31acb7362a8..ec3137be748 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -23,7 +23,7 @@ event-manager = "0.4.0" gdbstub = { version = "0.7.3", optional = true } gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } -kvm-ioctls = "0.19.0" +kvm-ioctls = "0.19.1" lazy_static = "1.5.0" libc = "0.2.168" linux-loader = "0.13.0" From de0d42e8192316e9552621db684dbecd96068284 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 14:13:09 +0000 Subject: [PATCH 40/78] chore: suppress new pylint lint With the devctr's python dependencies update, we pulled in a new pylint version, which has a new `too-many-positional-arguments` lint. Fixing this would be a significant refactor, so just suppress it, as it seems low-value. Signed-off-by: Patrick Roy --- tests/integration_tests/style/test_python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_tests/style/test_python.py b/tests/integration_tests/style/test_python.py index 6a836dc4287..b04b93dace2 100644 --- a/tests/integration_tests/style/test_python.py +++ b/tests/integration_tests/style/test_python.py @@ -37,7 +37,7 @@ def test_python_pylint(): "fixme,too-many-instance-attributes,import-error," "too-many-locals,too-many-arguments,consider-using-f-string," "consider-using-with,implicit-str-concat,line-too-long,redefined-outer-name," - "broad-exception-raised,duplicate-code tests tools .buildkite/*.py" + "broad-exception-raised,duplicate-code,too-many-positional-arguments tests tools .buildkite/*.py" ) run( linter_cmd, From f735be33f667f35911f5410fe89318f45dd72387 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 11:40:22 +0000 Subject: [PATCH 41/78] fix: do not double close file descriptors in unittests With newer rust toolchains, rust will SIGABRT if an already closed file descriptor is closed in the the `Drop` implementation for `File`. This also applies to creating `File`s with invalid file descriptors. Thus fix tests that accidentally double-close fds, and remove those that explicitly construct `File`s with invalid file descriptors (they are redundant now anyway, because Rust would abort if this ever happened). Signed-off-by: Patrick Roy --- .../arch/aarch64/gic/gicv2/regs/dist_regs.rs | 3 ++ .../arch/aarch64/gic/gicv2/regs/icc_regs.rs | 3 ++ src/vmm/src/arch/aarch64/gic/gicv3/mod.rs | 3 ++ .../arch/aarch64/gic/gicv3/regs/dist_regs.rs | 3 ++ .../arch/aarch64/gic/gicv3/regs/icc_regs.rs | 3 ++ .../aarch64/gic/gicv3/regs/redist_regs.rs | 3 ++ src/vmm/src/arch/aarch64/vcpu.rs | 3 ++ .../src/devices/virtio/block/virtio/io/mod.rs | 29 ------------------- src/vmm/src/devices/virtio/net/device.rs | 6 ++++ src/vmm/src/devices/virtio/net/tap.rs | 13 --------- src/vmm/src/vstate/vcpu/aarch64.rs | 6 ++++ src/vmm/src/vstate/vcpu/x86_64.rs | 4 +-- 12 files changed, 34 insertions(+), 45 deletions(-) diff --git a/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs index 3ec73490038..a4179e895ae 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs @@ -162,5 +162,8 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 1)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } } diff --git a/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs index aea6cb722b6..be963a8327e 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs @@ -120,5 +120,8 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 2)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } } diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs b/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs index 21f9b94218d..50d2e5130db 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs @@ -220,5 +220,8 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), true, 4)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic); } } diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs index 6e0cc8aac23..5af3e9215c0 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs @@ -159,6 +159,9 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 1)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } #[test] diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs index e455e76ba43..d242bce8433 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs @@ -206,6 +206,9 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 6)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } #[test] diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs index 1909d9b453b..88af82e3cb2 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs @@ -120,5 +120,8 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 5)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } } diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index 5c08f95351a..80fc5a339df 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -299,5 +299,8 @@ mod tests { let res = set_mpstate(&vcpu, kvm_mp_state::default()); assert!(matches!(res, Err(VcpuError::SetMp(_))), "{:?}", res); + + // dropping vcpu would double close the fd, so leak it + std::mem::forget(vcpu); } } diff --git a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs index de970986da2..09e86b6968d 100644 --- a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs +++ b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs @@ -187,7 +187,6 @@ impl FileEngine { pub mod tests { #![allow(clippy::undocumented_unsafe_blocks)] use std::os::unix::ffi::OsStrExt; - use std::os::unix::io::FromRawFd; use vmm_sys_util::tempfile::TempFile; @@ -201,20 +200,6 @@ pub mod tests { // 2 pages of memory should be enough to test read/write ops and also dirty tracking. const MEM_LEN: usize = 8192; - macro_rules! assert_err { - ($expression:expr, $($pattern:tt)+) => { - match $expression { - Err(UserDataError { - user_data: _, - error: $($pattern)+, - }) => (), - ref err => { - panic!("expected `{}` but got `{:?}`", stringify!($($pattern)+), err); - } - } - }; - } - macro_rules! assert_sync_execution { ($expression:expr, $count:expr) => { match $expression { @@ -265,17 +250,7 @@ pub mod tests { #[test] fn test_sync() { - // Check invalid file let mem = create_mem(); - let file = unsafe { File::from_raw_fd(-2) }; - let mut engine = FileEngine::from_file(file, FileEngineType::Sync).unwrap(); - let res = engine.read(0, &mem, GuestAddress(0), 0, ()); - assert_err!(res, BlockIoError::Sync(sync_io::SyncIoError::Seek(_e))); - let res = engine.write(0, &mem, GuestAddress(0), 0, ()); - assert_err!(res, BlockIoError::Sync(sync_io::SyncIoError::Seek(_e))); - let res = engine.flush(()); - assert_err!(res, BlockIoError::Sync(sync_io::SyncIoError::SyncAll(_e))); - // Create backing file. let file = TempFile::new().unwrap().into_file(); let mut engine = FileEngine::from_file(file, FileEngineType::Sync).unwrap(); @@ -342,10 +317,6 @@ pub mod tests { #[test] fn test_async() { - // Check invalid file - let file = unsafe { File::from_raw_fd(-2) }; - FileEngine::<()>::from_file(file, FileEngineType::Async).unwrap_err(); - // Create backing file. let file = TempFile::new().unwrap().into_file(); let mut engine = FileEngine::<()>::from_file(file, FileEngineType::Async).unwrap(); diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index a17c25d7248..99941f5796a 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -1808,6 +1808,9 @@ pub mod tests { assert_eq!(th.txq.used.idx.get(), 1); assert!(&th.net().irq_trigger.has_pending_irq(IrqType::Vring)); th.txq.check_used_elem(0, 0, 0); + + // dropping th would double close the tap fd, so leak it + std::mem::forget(th); } #[test] @@ -2041,6 +2044,9 @@ pub mod tests { 1, th.simulate_event(NetEvent::Tap) ); + + // dropping th would double close the tap fd, so leak it + std::mem::forget(th); } #[test] diff --git a/src/vmm/src/devices/virtio/net/tap.rs b/src/vmm/src/devices/virtio/net/tap.rs index 0f5b7e2d788..776b5ba960e 100644 --- a/src/vmm/src/devices/virtio/net/tap.rs +++ b/src/vmm/src/devices/virtio/net/tap.rs @@ -277,19 +277,6 @@ pub mod tests { let tap = Tap::open_named("").unwrap(); tap.set_vnet_hdr_size(16).unwrap(); tap.set_offload(0).unwrap(); - - let faulty_tap = Tap { - tap_file: unsafe { File::from_raw_fd(-2) }, - if_name: [0x01; 16], - }; - assert_eq!( - faulty_tap.set_vnet_hdr_size(16).unwrap_err().to_string(), - TapError::SetSizeOfVnetHdr(IoError::from_raw_os_error(9)).to_string() - ); - assert_eq!( - faulty_tap.set_offload(0).unwrap_err().to_string(), - TapError::SetOffloadFlags(IoError::from_raw_os_error(9)).to_string() - ); } #[test] diff --git a/src/vmm/src/vstate/vcpu/aarch64.rs b/src/vmm/src/vstate/vcpu/aarch64.rs index 2e2bb36fb07..4e006f196d0 100644 --- a/src/vmm/src/vstate/vcpu/aarch64.rs +++ b/src/vmm/src/vstate/vcpu/aarch64.rs @@ -329,6 +329,9 @@ mod tests { err.err().unwrap().to_string(), "Error creating vcpu: Bad file descriptor (os error 9)".to_string() ); + + // dropping vm would double close the gic fd, so leak it + std::mem::forget(vm); } #[test] @@ -361,6 +364,9 @@ mod tests { kvm_ioctls::Error::new(9) )) ); + + // dropping vcpu would double close the gic fd, so leak it + std::mem::forget(vcpu); } #[test] diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index a1bb22d1bb7..4043691130d 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -715,8 +715,6 @@ impl Debug for VcpuState { mod tests { #![allow(clippy::undocumented_unsafe_blocks)] - use std::os::unix::io::AsRawFd; - use kvm_bindings::kvm_msr_entry; use kvm_ioctls::{Cap, Kvm}; @@ -874,7 +872,7 @@ mod tests { // Restore the state into the existing vcpu. let result1 = vcpu.restore_state(&state); assert!(result1.is_ok(), "{}", result1.unwrap_err()); - unsafe { libc::close(vcpu.fd.as_raw_fd()) }; + drop(vcpu); // Restore the state into a new vcpu. let (_vm, vcpu, _mem) = setup_vcpu(0x10000); From 73fe828ed624eefb16f4ac908b350d030f68eb76 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 14:41:56 +0000 Subject: [PATCH 42/78] chore: apply updated mdformat styles It seemingly finally got intelligent enough to realize we don't need all these backslashes on the brackets. Signed-off-by: Patrick Roy --- CHANGELOG.md | 101 ++++++++++++------------ FAQ.md | 9 +-- README.md | 18 ++--- docs/api_requests/actions.md | 2 +- docs/api_requests/block-io-engine.md | 2 +- docs/api_requests/block-vhost-user.md | 2 +- docs/formal-verification.md | 49 ++++++------ docs/hugepages.md | 2 +- docs/prod-host-setup.md | 8 +- docs/snapshotting/network-for-clones.md | 2 +- docs/snapshotting/snapshot-support.md | 2 +- tests/README.md | 37 ++++----- 12 files changed, 112 insertions(+), 122 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e7be8f518f..65ef73a1e1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## \[Unreleased\] +## [Unreleased] ### Added @@ -26,14 +26,14 @@ and this project adheres to - [#4921](https://github.com/firecracker-microvm/firecracker/pull/4921): Fixed swagger `CpuConfig` definition to include missing aarch64-specific fields. -## \[1.10.1\] +## [1.10.1] ### Changed - [#4907](https://github.com/firecracker-microvm/firecracker/pull/4907): Bumped the snapshot version to 4.0.0, so users need to regenerate snapshots. -## \[1.10.0\] +## [1.10.0] ### Added @@ -90,7 +90,7 @@ and this project adheres to in the restore path. This was leading to inability to connect to the restored VM if the offload features were used. -## \[1.9.0\] +## [1.9.0] ### Added @@ -134,7 +134,7 @@ and this project adheres to different assumptions. This PR fixes the emulation code to set the TAP features based on the features accepted by the guest. -## \[1.8.0\] +## [1.8.0] ### Added @@ -227,7 +227,7 @@ and this project adheres to could lead to them seemingly getting stuck in sleep-related syscalls (see also https://github.com/firecracker-microvm/firecracker/pull/4099). -## \[1.7.0\] +## [1.7.0] ### Added @@ -304,7 +304,7 @@ and this project adheres to content is empty, because the 'Content-Length' header field was missing in a response. -## \[1.6.0\] +## [1.6.0] ### Added @@ -396,7 +396,7 @@ and this project adheres to "write-back" of all memory that was updated since the snapshot was originally loaded. -## \[1.5.0\] +## [1.5.0] ### Added @@ -462,10 +462,10 @@ and this project adheres to - Fixed a change in behavior of normalize host brand string that breaks Firecracker on external instances. -- Fixed the T2A CPU template not to unset the MMX bit - (CPUID.80000001h:EDX\[23\]) and the FXSR bit (CPUID.80000001h:EDX\[24\]). +- Fixed the T2A CPU template not to unset the MMX bit (CPUID.80000001h:EDX[23]) + and the FXSR bit (CPUID.80000001h:EDX[24]). - Fixed the T2A CPU template to set the RstrFpErrPtrs bit - (CPUID.80000008h:EBX\[2\]). + (CPUID.80000008h:EBX[2]). - Fixed a bug where Firecracker would crash during boot if a guest set up a virtio queue that partially overlapped with the MMIO gap. Now Firecracker instead correctly refuses to activate the corresponding virtio device. @@ -484,7 +484,7 @@ and this project adheres to misspelled param ("nomodules") being present at the command line, since this param will no longer be passed. -## \[1.4.0\] +## [1.4.0] ### Added @@ -499,8 +499,8 @@ and this project adheres to ### Changed -- Set FDP_EXCPTN_ONLY bit (CPUID.7h.0:EBX\[6\]) and ZERO_FCS_FDS bit - (CPUID.7h.0:EBX\[13\]) in Intel's CPUID normalization process. +- Set FDP_EXCPTN_ONLY bit (CPUID.7h.0:EBX[6]) and ZERO_FCS_FDS bit + (CPUID.7h.0:EBX[13]) in Intel's CPUID normalization process. ### Fixed @@ -521,10 +521,9 @@ and this project adheres to - Fixed passing through cache information from host in CPUID leaf 0x80000005. - Fixed the T2A CPU template to disable SVM (nested virtualization). - Fixed the T2A CPU template to set EferLmsleUnsupported bit - (CPUID.80000008h:EBX\[20\]), which indicates that EFER\[LMSLE\] is not - supported. + (CPUID.80000008h:EBX[20]), which indicates that EFER[LMSLE] is not supported. -## \[1.3.0\] +## [1.3.0] ### Added @@ -544,7 +543,7 @@ and this project adheres to - Fixed feature flags in T2 CPU template on Intel Ice Lake. -## \[1.2.0\] +## [1.2.0] ### Added @@ -589,7 +588,7 @@ and this project adheres to of Firecracker \<= 1.1.3. - Improved stability and security when saving CPU MSRs in snapshots. -## \[1.1.0\] +## [1.1.0] ### Added @@ -651,7 +650,7 @@ and this project adheres to - Fixed incosistency in the swagger definition with the current state of the `/vm/config` endpoint. -## \[1.0.0\] +## [1.0.0] ### Added @@ -726,7 +725,7 @@ and this project adheres to - Fix jailer's cgroup implementation to accept properties that contain multiple dots. -## \[0.25.0\] +## [0.25.0] ### Added @@ -785,7 +784,7 @@ and this project adheres to Epoch, as the name suggests. It was previously using a monotonic clock with an undefined starting point. -## \[0.24.0\] +## [0.24.0] ### Added @@ -822,7 +821,7 @@ and this project adheres to - Fixed inconsistency in YAML file InstanceInfo definition -## \[0.23.0\] +## [0.23.0] ### Added @@ -873,7 +872,7 @@ and this project adheres to - Changed `devtool build` to build jailer binary for `musl` only targets. Building jailer binary for `non-musl` targets have been removed. -## \[0.22.0\] +## [0.22.0] ### Added @@ -937,7 +936,7 @@ and this project adheres to - Segregated MMDS documentation in MMDS design documentation and MMDS user guide documentation. -## \[0.21.0\] +## [0.21.0] ### Added @@ -973,7 +972,7 @@ and this project adheres to functionality is available through the PATCH /drives API. See `docs/api_requests/patch-block.md`. -## \[0.20.0\] +## [0.20.0] ### Added @@ -1001,7 +1000,7 @@ and this project adheres to - Decreased release binary size by 10%. -## \[0.19.0\] +## [0.19.0] ### Added @@ -1044,7 +1043,7 @@ and this project adheres to - Changed the vsock property `id` to `vsock_id` so that the API client can be successfully generated from the swagger definition. -## \[0.18.0\] +## [0.18.0] ### Added @@ -1071,7 +1070,7 @@ and this project adheres to - Removed experimental support for vhost-based vsock devices. -## \[0.17.0\] +## [0.17.0] ### Added @@ -1082,7 +1081,7 @@ and this project adheres to - Added a signal handler for `SIGBUS` and `SIGSEGV` that immediately terminates the process upon intercepting the signal. - Added documentation for signal handling utilities. -- Added \[alpha\] aarch64 support. +- Added [alpha] aarch64 support. - Added metrics for successful read and write operations of MMDS, Net and Block devices. @@ -1097,11 +1096,11 @@ and this project adheres to - Incorrect handling of bind mounts within the jailed rootfs. - Corrected the guide for `Alpine` guest setup. -## \[0.16.0\] +## [0.16.0] ### Added -- Added \[alpha\] AMD support. +- Added [alpha] AMD support. - New `devtool` command: `prepare_release`. This updates the Firecracker version, crate dependencies and credits in preparation for a new release. - New `devtool` command: `tag`. This creates a new git tag for the specified @@ -1127,13 +1126,13 @@ and this project adheres to - Removed the `seccomp.bad_syscalls` metric. -## \[0.15.2\] +## [0.15.2] ### Fixed - Corrected the conditional compilation of the seccomp rule for `madvise`. -## \[0.15.1\] +## [0.15.1] ### Fixed @@ -1141,7 +1140,7 @@ and this project adheres to list to prevent Firecracker from terminating abruptly when allocating memory in certain conditions. -## \[0.15.0\] +## [0.15.0] ### Added @@ -1166,7 +1165,7 @@ and this project adheres to - Vsock devices can be attached when starting Firecracker using the jailer. - Vsock devices work properly when seccomp filtering is enabled. -## \[0.14.0\] +## [0.14.0] ### Added @@ -1186,7 +1185,7 @@ and this project adheres to - Fixed build with the `vsock` feature. -## \[0.13.0\] +## [0.13.0] ### Added @@ -1213,7 +1212,7 @@ and this project adheres to - Removed `InstanceHalt` from the list of possible actions. -## \[0.12.0\] +## [0.12.0] ### Added @@ -1243,7 +1242,7 @@ and this project adheres to - Ensure MMDS compatibility with C5's IMDS implementation. - Corrected the swagger specification to ensure `OpenAPI 2.0` compatibility. -## \[0.11.0\] +## [0.11.0] ### Added @@ -1273,13 +1272,13 @@ and this project adheres to - Fixed bug in `PATCH /drives`, whereby the ID in the path was not checked against the ID in the body. -## \[0.10.1\] +## [0.10.1] ### Fixed - The Swagger definition was corrected. -## \[0.10.0\] +## [0.10.0] ### Added @@ -1305,7 +1304,7 @@ and this project adheres to - The microVM ID prefixes each Firecracker log line. This ID also appears in the process `cmdline` so it's now possible to `ps | grep ` for it. -## \[0.9.0\] +## [0.9.0] ### Added @@ -1339,7 +1338,7 @@ and this project adheres to - Remove the `action_id` parameter for `InstanceStart`, both from the URI and the JSON request body. -## \[0.8.0\] +## [0.8.0] ### Added @@ -1354,7 +1353,7 @@ and this project adheres to - Replaced the `permissions` property of `/drives` resources with a boolean. - Removed the `state` property of `/drives` resources. -## \[0.7.0\] +## [0.7.0] ### Added @@ -1379,7 +1378,7 @@ and this project adheres to guest kernel boot. - Fixed network emulation to improve IO performance. -## \[0.6.0\] +## [0.6.0] ### Added @@ -1408,7 +1407,7 @@ and this project adheres to - It is now possible to create more than one network tun/tap interface inside a jailed Firecracker. -## \[0.5.0\] +## [0.5.0] ### Added @@ -1447,7 +1446,7 @@ and this project adheres to - Removed a leftover file generated by the logger unit tests. - Removed `firecracker-v1.0.yaml`. -## \[0.4.0\] +## [0.4.0] ### Added @@ -1498,7 +1497,7 @@ and this project adheres to - Removed `--vmm-no-api` command line option. Firecracker can only be started via the API. -## \[0.3.0\] +## [0.3.0] ### Added @@ -1534,7 +1533,7 @@ and this project adheres to - Removed support for attaching vsock devices. - Removed support for building Firecracker with glibc. -## \[0.2.0\] +## [0.2.0] ### Added @@ -1572,7 +1571,7 @@ and this project adheres to - Removed `api/swagger/firecracker-mvp.yaml`. - Removed `api/swagger/limiters.yaml`. -## \[0.1.1\] +## [0.1.1] ### Changed @@ -1587,7 +1586,7 @@ and this project adheres to - Fixed an issue which caused compilation problems, due to a compatibility breaking transitive dependency in the tokio suite of crates. -## \[0.1.0\] +## [0.1.0] ### Added diff --git a/FAQ.md b/FAQ.md index 6697ac9f4d1..e2c011c3b7d 100644 --- a/FAQ.md +++ b/FAQ.md @@ -60,11 +60,10 @@ minimal required device model to the guest operating system while excluding non-essential functionality (only 6 emulated devices are available: virtio-net, virtio-balloon, virtio-block, virtio-vsock, serial console, and a minimal keyboard controller used only to stop the microVM). This, along with a -streamlined kernel loading process enables a \< 125 ms startup time and a \< 5 -MiB memory footprint. The Firecracker process also provides a RESTful control -API, handles resource rate limiting for microVMs, and provides a microVM -metadata service to enable the sharing of configuration data between the host -and guest. +streamlined kernel loading process enables a < 125 ms startup time and a < 5 MiB +memory footprint. The Firecracker process also provides a RESTful control API, +handles resource rate limiting for microVMs, and provides a microVM metadata +service to enable the sharing of configuration data between the host and guest. ### What operating systems are supported by Firecracker? diff --git a/README.md b/README.md index f98079fc81c..5805b76ba15 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ The **API endpoint** can be used to: - Add a [entropy device](docs/entropy.md) to the microVM. - Start the microVM using a given kernel image, root file system, and boot arguments. -- \[x86_64 only\] Stop the microVM. +- [x86_64 only] Stop the microVM. **Built-in Capabilities**: @@ -130,14 +130,14 @@ The **API endpoint** can be used to: We test all combinations of: -| Instance | Host OS & Kernel | Guest Rootfs | Guest Kernel | -| :-------- | :---------------- | :----------- | :----------- | -| c5n.metal | al2 linux_5.10 | ubuntu 24.04 | linux_5.10 | -| m5n.metal | al2023 linux_6.1 | | linux_6.1 | -| m6i.metal | | | | -| m6a.metal | | | | -| m6g.metal | | | | -| m7g.metal | | | | +| Instance | Host OS & Kernel | Guest Rootfs | Guest Kernel | +| :-------- | :--------------- | :----------- | :----------- | +| c5n.metal | al2 linux_5.10 | ubuntu 24.04 | linux_5.10 | +| m5n.metal | al2023 linux_6.1 | | linux_6.1 | +| m6i.metal | | | | +| m6a.metal | | | | +| m6g.metal | | | | +| m7g.metal | | | | ## Known issues and Limitations diff --git a/docs/api_requests/actions.md b/docs/api_requests/actions.md index c72f12372dc..40700c359de 100644 --- a/docs/api_requests/actions.md +++ b/docs/api_requests/actions.md @@ -31,7 +31,7 @@ curl --unix-socket /tmp/firecracker.socket -i \ -d '{ "action_type": "FlushMetrics" }' ``` -## \[Intel and AMD only\] SendCtrlAltDel +## [Intel and AMD only] SendCtrlAltDel This action will send the CTRL+ALT+DEL key sequence to the microVM. By convention, this sequence has been used to trigger a soft reboot and, as such, diff --git a/docs/api_requests/block-io-engine.md b/docs/api_requests/block-io-engine.md index 8d8521bca3b..733aa374acd 100644 --- a/docs/api_requests/block-io-engine.md +++ b/docs/api_requests/block-io-engine.md @@ -6,7 +6,7 @@ system calls. Firecracker 1.0.0 adds support for an asynchronous block device IO engine. -> \[!WARNING\] +> [!WARNING] > > Support is currently in **developer preview**. See > [this section](#developer-preview-status) for more info. diff --git a/docs/api_requests/block-vhost-user.md b/docs/api_requests/block-vhost-user.md index 8325992caf4..4a3a4dee918 100644 --- a/docs/api_requests/block-vhost-user.md +++ b/docs/api_requests/block-vhost-user.md @@ -1,6 +1,6 @@ # Vhost-user block device -> \[!WARNING\] +> [!WARNING] > > Support is currently in **developer preview**. See > [this section](../RELEASE_POLICY.md#developer-preview-features) for more info. diff --git a/docs/formal-verification.md b/docs/formal-verification.md index 29ef16636dd..6a0c2d07574 100644 --- a/docs/formal-verification.md +++ b/docs/formal-verification.md @@ -143,45 +143,40 @@ Verification Time: 0.19135727s ## FAQ **Q:** What is the Kani verifier?\ -**A:** The -[Kani Rust Verifier](https://github.com/model-checking/kani) is a bit-precise -model checker for Rust. Kani is particularly useful for verifying unsafe code -blocks in Rust, where the +**A:** The [Kani Rust Verifier](https://github.com/model-checking/kani) is a +bit-precise model checker for Rust. Kani is particularly useful for verifying +unsafe code blocks in Rust, where the “[unsafe superpowers](https://doc.rust-lang.org/stable/book/ch19-01-unsafe-rust.html#unsafe-superpowers)" are unchecked by the compiler. **Q:** What safety properties does Kani verify?\ -**A:** Kani verifies memory -safety properties (e.g., invalid-pointer dereferences, out-of-bounds array -access), user-specified assertions (i.e., `assert!(...)`), the absence of -`panic!()`s (e.g., `unwrap()` on `None` values), and the absence of some types -of unexpected behavior (e.g., arithmetic overflows). For a full overview, see -the +**A:** Kani verifies memory safety properties (e.g., invalid-pointer +dereferences, out-of-bounds array access), user-specified assertions (i.e., +`assert!(...)`), the absence of `panic!()`s (e.g., `unwrap()` on `None` values), +and the absence of some types of unexpected behavior (e.g., arithmetic +overflows). For a full overview, see the [Kani documentation](https://model-checking.github.io/kani/tutorial-kinds-of-failure.html). **Q:** Do we expect all contributors to write harnesses for newly introduced code?\ -**A:** No. Kani is complementary to unit testing, and we do not have -target for “proof coverage”. We employ formal verification in especially -critical code areas. Generally we do not expect someone who might not be -familiar with formal tools to contribute harnesses. We do expect all contributed -code to pass verification though, just like we expect it to pass unit test! +**A:** No. Kani is complementary to unit testing, and we do not have target for +“proof coverage”. We employ formal verification in especially critical code +areas. Generally we do not expect someone who might not be familiar with formal +tools to contribute harnesses. We do expect all contributed code to pass +verification though, just like we expect it to pass unit test! **Q:** How should I report issues related to any Firecracker harnesses?\ -**A:** -Our Kani harnesses verify safety critical invariants. If you discover a flaw in -a harness, please report it using the +**A:** Our Kani harnesses verify safety critical invariants. If you discover a +flaw in a harness, please report it using the [security issue disclosure process](https://github.com/firecracker-microvm/firecracker/blob/main/SECURITY.md). -**Q:** How do I know which properties I should prove in the Kani -harness?\ -**A:** Generally, these are given by some sort of specification. This -can either be the function contract described in its document (e.g. what -relation between input and output do callers expect?), or even something formal -such as the TCP/IP standard. Don't forget to mention the specification in your -proof harness! +**Q:** How do I know which properties I should prove in the Kani harness?\ +**A:** Generally, these are given by some sort of specification. This can either +be the function contract described in its document (e.g. what relation between +input and output do callers expect?), or even something formal such as the +TCP/IP standard. Don't forget to mention the specification in your proof +harness! **Q:** Where do I debug a broken proof?\ -**A:** Check out the Kani book section -on +**A:** Check out the Kani book section on [debugging verification failures](https://model-checking.github.io/kani/debugging-verification-failures.html). diff --git a/docs/hugepages.md b/docs/hugepages.md index 0b4b994e04f..05b4e25b399 100644 --- a/docs/hugepages.md +++ b/docs/hugepages.md @@ -1,6 +1,6 @@ # Backing Guest Memory by Huge Pages -> \[!WARNING\] +> [!WARNING] > > Support is currently in **developer preview**. See > [this section](RELEASE_POLICY.md#developer-preview-features) for more info. diff --git a/docs/prod-host-setup.md b/docs/prod-host-setup.md index acf06a1e3d4..f046e31c735 100644 --- a/docs/prod-host-setup.md +++ b/docs/prod-host-setup.md @@ -254,18 +254,18 @@ echo "swap partitions present (Recommendation: no swap)" \ ### Mitigating hardware vulnerabilities -> \[!CAUTION\] +> [!CAUTION] > > Firecracker is not able to mitigate host's hardware vulnerabilities. Adequate > mitigations need to be put in place when configuring the host. -> \[!CAUTION\] +> [!CAUTION] > > Firecracker is designed to provide isolation boundaries between microVMs > running in different Firecracker processes. It is strongly recommended that > each Firecracker process corresponds to a workload of a single tenant. -> \[!CAUTION\] +> [!CAUTION] > > For security and stability reasons it is highly recommended to load updated > microcode as soon as possible. Aside from keeping the system firmware @@ -328,7 +328,7 @@ For vendor-specific recommendations, please consult the resources below: - ARM: [Speculative Processor Vulnerability](https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability) -##### \[ARM only\] Physical counter directly passed through to the guest +##### [ARM only] Physical counter directly passed through to the guest On ARM, the physical counter (i.e `CNTPCT`) it is returning the [actual EL1 physical counter value of the host][1]. From the discussions before diff --git a/docs/snapshotting/network-for-clones.md b/docs/snapshotting/network-for-clones.md index d0a44e89413..b997ba3687e 100644 --- a/docs/snapshotting/network-for-clones.md +++ b/docs/snapshotting/network-for-clones.md @@ -3,7 +3,7 @@ This document presents a strategy to ensure continued network connectivity for multiple clones created from a single Firecracker microVM snapshot. -> \[!CAUTION\] +> [!CAUTION] > > This should be considered as just an example to get you started, and we don't > claim this is a performant or secure setup. diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index 75ffd306e25..c8d964ae89b 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -37,7 +37,7 @@ workload at that particular point in time. ### Supported platforms -> \[!WARNING\] +> [!WARNING] > > The Firecracker snapshot feature is in > [developer preview](../RELEASE_POLICY.md) on all CPU micro-architectures diff --git a/tests/README.md b/tests/README.md index bf7aba9a547..91fb2a9aeed 100644 --- a/tests/README.md +++ b/tests/README.md @@ -400,36 +400,33 @@ setting to achieve consistent performance. Please see the `test` section of `Q1:` *I have a shell script that runs my tests and I don't want to rewrite it.*\ -`A1:` Insofar as it makes sense, you should write it as a python test -function. However, you can always call the script from a shim python test -function. You can also add it as a microvm image resource in the s3 bucket (and -it will be made available under `microvm.slot.path`) or copy it over to a guest -filesystem as part of your test. +`A1:` Insofar as it makes sense, you should write it as a python test function. +However, you can always call the script from a shim python test function. You +can also add it as a microvm image resource in the s3 bucket (and it will be +made available under `microvm.slot.path`) or copy it over to a guest filesystem +as part of your test. `Q2:` *I want to add more tests that I don't want to commit to the Firecracker repository.*\ -`A2:` Before a testrun or test session, just add your test -directory under `tests/`. `pytest` will discover all tests in this tree. +`A2:` Before a testrun or test session, just add your test directory under +`tests/`. `pytest` will discover all tests in this tree. -`Q3:` *I want to have my own test fixtures, and not commit them in the -repo.*\ -`A3:` Add a `conftest.py` file in your test directory, and place your -fixtures there. `pytest` will bring them into scope for all your tests. +`Q3:` *I want to have my own test fixtures, and not commit them in the repo.*\ +`A3:` Add a `conftest.py` file in your test directory, and place your fixtures +there. `pytest` will bring them into scope for all your tests. `Q4:` *I want to use more/other microvm test images, but I don't want to add them to the common s3 bucket.*\ -`A4:` Add your custom images to the `build/img` -subdirectory in the Firecracker source tree. This directory is bind-mounted in -the container and used as a local image cache. +`A4:` Add your custom images to the `build/img` subdirectory in the Firecracker +source tree. This directory is bind-mounted in the container and used as a local +image cache. `Q5:` *How can I get live logger output from the tests?*\ -`A5:` Accessing -**pytest.ini** will allow you to modify logger settings. +`A5:` Accessing **pytest.ini** will allow you to modify logger settings. `Q6:` *Is there a way to speed up integration tests execution time?*\ -`A6:` You -can narrow down the test selection as described in the **Running** section. For -example: +`A6:` You can narrow down the test selection as described in the **Running** +section. For example: 1. Pass the `-k substring` option to pytest to only run a subset of tests by specifying a part of their name. @@ -643,6 +640,6 @@ sudo pip3 install pytest ipython requests psutil tenacity filelock "urllib3<2.0" sudo env PYTHONPATH=tests HOME=$HOME ~/.local/bin/ipython3 -i tools/sandbox.py -- --binary-dir ../repro/v1.4.1 ``` -> \[!WARNING\] +> [!WARNING] > > **Notice this runs as root!** From cdbfac04dd6719dd72856196ef9d045e8d37023e Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 15:40:44 +0000 Subject: [PATCH 43/78] fix: suppress dead code warnings in cache_info.rs The unittests here rely on the cfg(not(test)) antipattern for mocking, which new rust compiler interprets as the production version of the structs being dead-code when running unittests. Refactoring this to eliminate mocking is difficult, because fdt unit tests rely on the mocks removing all host-specific information from the cpu FDT nodes (particularly cache information, which in prod is read from the host sysfs, but in test mode is some dummy mock values). Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/cache_info.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vmm/src/arch/aarch64/cache_info.rs b/src/vmm/src/arch/aarch64/cache_info.rs index cd61cabeb02..fd7d6e0a2ea 100644 --- a/src/vmm/src/arch/aarch64/cache_info.rs +++ b/src/vmm/src/arch/aarch64/cache_info.rs @@ -45,6 +45,7 @@ pub(crate) struct CacheEntry { } #[derive(Debug)] +#[cfg_attr(test, allow(dead_code))] struct HostCacheStore { cache_dir: PathBuf, } @@ -206,6 +207,7 @@ impl CacheType { } } +#[cfg_attr(test, allow(unused))] fn readln_special>(file_path: &T) -> Result { let line = fs::read_to_string(file_path)?; Ok(line.trim_end().to_string()) From 70c295e586f8aa916d942c68176c453ccf6d6e2c Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 15:24:54 +0000 Subject: [PATCH 44/78] test: update changelog validation to match new mdformat with new mdformat we no longer need to wrap level 2 headings in escaped brackets, just normal brackets. Signed-off-by: Patrick Roy --- tests/integration_tests/style/test_repo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration_tests/style/test_repo.py b/tests/integration_tests/style/test_repo.py index 90a1e9450e1..299f89f6cdb 100644 --- a/tests/integration_tests/style/test_repo.py +++ b/tests/integration_tests/style/test_repo.py @@ -44,8 +44,8 @@ def test_repo_validate_changelog(): errors = [] for lineno, line in enumerate(changelog, start=1): if line.startswith("## "): - if not re.match(r"^## \\\[.+\\\]$", line): - msg = "Level 2 headings (versions) should be wrapped in \\[\\]" + if not re.match(r"^## \[.+\]$", line): + msg = "Level 2 headings (versions) should be wrapped in []" errors.append((lineno, msg, line)) if line.startswith("### "): if not re.match(r"^### (Added|Changed|Deprecated|Removed|Fixed)$", line): From c8fa501fb24eabcb8dc239a6cd1b9fd6e32199f0 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 17:27:32 +0000 Subject: [PATCH 45/78] chore: update release-prepare.sh to deal with less escaped markdown Thanks to mdformat no longer escaping brackets everywhere, we can simplify a regex. Signed-off-by: Patrick Roy --- tools/release-prepare.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/release-prepare.sh b/tools/release-prepare.sh index 30c32316944..f74334443ee 100755 --- a/tools/release-prepare.sh +++ b/tools/release-prepare.sh @@ -54,7 +54,7 @@ $FC_TOOLS_DIR/update-credits.sh # Update changelog. say "Updating changelog..." -sed -i "s/\\\\\[Unreleased\\\\\]/\\\\\[$version\\\\\]/g" "$FC_ROOT_DIR/CHANGELOG.md" +sed -i "s/\[Unreleased\]/\[$version\]/g" "$FC_ROOT_DIR/CHANGELOG.md" # Add all changed files git add -u From 17846a3c9cef95a8571f221bc571f58c10a281bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 2 Dec 2024 22:21:03 +0100 Subject: [PATCH 46/78] tests: move pylint config to pyproject.toml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It makes it easier to configure pylint Signed-off-by: Pablo Barbáchano --- tests/integration_tests/style/test_python.py | 12 +---- tests/pyproject.toml | 47 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/tests/integration_tests/style/test_python.py b/tests/integration_tests/style/test_python.py index b04b93dace2..447a1969daa 100644 --- a/tests/integration_tests/style/test_python.py +++ b/tests/integration_tests/style/test_python.py @@ -28,17 +28,7 @@ def test_python_pylint(): Test that python code passes linter checks. """ # List of linter commands that should be executed for each file - linter_cmd = ( - # Pylint - "pylint --jobs=0 --persistent=no --score=no " - '--output-format=colorized --attr-rgx="[a-z_][a-z0-9_]{1,30}$" ' - '--argument-rgx="[a-z_][a-z0-9_]{1,35}$" ' - '--variable-rgx="[a-z_][a-z0-9_]{1,30}$" --disable=' - "fixme,too-many-instance-attributes,import-error," - "too-many-locals,too-many-arguments,consider-using-f-string," - "consider-using-with,implicit-str-concat,line-too-long,redefined-outer-name," - "broad-exception-raised,duplicate-code,too-many-positional-arguments tests tools .buildkite/*.py" - ) + linter_cmd = "pylint --rcfile tests/pyproject.toml --output-format=colorized tests/ tools/ .buildkite/*.py" run( linter_cmd, # we let pytest capture stdout/stderr for us diff --git a/tests/pyproject.toml b/tests/pyproject.toml index a81f188f996..19a77b5e190 100644 --- a/tests/pyproject.toml +++ b/tests/pyproject.toml @@ -8,3 +8,50 @@ exclude = "/(\\.direnv|\\.eggs|\\.git|\\.hg|\\.mypy_cache|\\.nox|\\.tox|\\.venv| # https://pycqa.github.io/isort/docs/configuration/multi_line_output_modes.html multi_line_output = 3 profile = "black" + +[tool.pylint.main] + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use, and will cap the count on Windows to +# avoid hangs. +jobs = 0 + +score = false + +# Pickle collected data for later comparisons. +persistent = false + +# Disable the message, report, category or checker with the given id(s). You can +# either give multiple identifiers separated by comma (,) or put this option +# multiple times (only on the command line, not in the configuration file where +# it should appear only once). You can also use "--disable=all" to disable +# everything first and then re-enable specific checks. For example, if you want +# to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable = [ + "raw-checker-failed", + "bad-inline-option", + "locally-disabled", + "file-ignored", + "suppressed-message", + "useless-suppression", + "deprecated-pragma", + "use-implicit-booleaness-not-comparison-to-string", + "use-implicit-booleaness-not-comparison-to-zero", + "use-symbolic-message-instead", + "fixme", + "too-many-instance-attributes", + "import-error", + "too-many-locals", + "too-many-arguments", + "consider-using-f-string", + "consider-using-with", + "implicit-str-concat", + "line-too-long", + "redefined-outer-name", + "broad-exception-raised", + "duplicate-code", + "too-many-positional-arguments", +] From 545b47ded00569683827c5c6b0edd158332199b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 2 Dec 2024 22:37:15 +0100 Subject: [PATCH 47/78] style: disable pylint too-few-public-methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I think this lint is not useful, and makes writing small classes more difficult than it needs to be. Signed-off-by: Pablo Barbáchano --- tests/framework/http_api.py | 2 -- tests/framework/properties.py | 1 - tests/framework/state_machine.py | 2 -- tests/framework/utils.py | 1 - tests/integration_tests/functional/test_serial_io.py | 6 +++--- tests/pyproject.toml | 1 + 6 files changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/framework/http_api.py b/tests/framework/http_api.py index a1ee37174b0..ea8efd3df4f 100644 --- a/tests/framework/http_api.py +++ b/tests/framework/http_api.py @@ -3,8 +3,6 @@ """A simple HTTP client for the Firecracker API""" -# pylint:disable=too-few-public-methods - import urllib from http import HTTPStatus diff --git a/tests/framework/properties.py b/tests/framework/properties.py index 7dd1cb46588..7072a2ff3ca 100644 --- a/tests/framework/properties.py +++ b/tests/framework/properties.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # pylint:disable=broad-except -# pylint:disable=too-few-public-methods """ Metadata we want to attach to tests for further analysis and troubleshooting diff --git a/tests/framework/state_machine.py b/tests/framework/state_machine.py index 97975c75526..1d8dd664e6b 100644 --- a/tests/framework/state_machine.py +++ b/tests/framework/state_machine.py @@ -3,8 +3,6 @@ """Defines a stream based string matcher and a generic state object.""" -# Too few public methods (1/2) (too-few-public-methods) -# pylint: disable=R0903 class MatchStaticString: """Match a static string versus input.""" diff --git a/tests/framework/utils.py b/tests/framework/utils.py index a8715f00e94..e71302545c9 100644 --- a/tests/framework/utils.py +++ b/tests/framework/utils.py @@ -196,7 +196,6 @@ def __del__(self): self.proc.kill() -# pylint: disable=too-few-public-methods class CpuMap: """Cpu map from real cpu cores to containers visible cores. diff --git a/tests/integration_tests/functional/test_serial_io.py b/tests/integration_tests/functional/test_serial_io.py index db1521d4a44..aee9047f531 100644 --- a/tests/integration_tests/functional/test_serial_io.py +++ b/tests/integration_tests/functional/test_serial_io.py @@ -16,7 +16,7 @@ PLATFORM = platform.machine() -class WaitTerminal(TestState): # pylint: disable=too-few-public-methods +class WaitTerminal(TestState): """Initial state when we wait for the login prompt.""" def handle_input(self, serial, input_char) -> TestState: @@ -27,7 +27,7 @@ def handle_input(self, serial, input_char) -> TestState: return self -class WaitIDResult(TestState): # pylint: disable=too-few-public-methods +class WaitIDResult(TestState): """Wait for the console to show the result of the 'id' shell command.""" def handle_input(self, unused_serial, input_char) -> TestState: @@ -37,7 +37,7 @@ def handle_input(self, unused_serial, input_char) -> TestState: return self -class TestFinished(TestState): # pylint: disable=too-few-public-methods +class TestFinished(TestState): """Test complete and successful.""" def handle_input(self, unused_serial, _) -> TestState: diff --git a/tests/pyproject.toml b/tests/pyproject.toml index 19a77b5e190..70df5a75331 100644 --- a/tests/pyproject.toml +++ b/tests/pyproject.toml @@ -54,4 +54,5 @@ disable = [ "broad-exception-raised", "duplicate-code", "too-many-positional-arguments", + "too-few-public-methods", ] From fe8239232e6868df6366bcb10f9491eccaeac4c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 5 Nov 2024 13:25:40 +0100 Subject: [PATCH 48/78] tests: cleanup test_seccomp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - convert inline JSON to dicts - use pytest temporary files instead of tempfile - create a seccompiler fixture to make running it easy Signed-off-by: Pablo Barbáchano --- tests/integration_tests/security/conftest.py | 29 +++ .../security/test_custom_seccomp.py | 198 +++++------------- .../security/test_seccomp.py | 196 ++++++----------- 3 files changed, 136 insertions(+), 287 deletions(-) create mode 100644 tests/integration_tests/security/conftest.py diff --git a/tests/integration_tests/security/conftest.py b/tests/integration_tests/security/conftest.py new file mode 100644 index 00000000000..1cce3067b2f --- /dev/null +++ b/tests/integration_tests/security/conftest.py @@ -0,0 +1,29 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Fixtures for security tests""" + +import json +from pathlib import Path + +import pytest + +from host_tools.cargo_build import run_seccompiler_bin + + +@pytest.fixture() +def seccompiler(tmp_path): + "A seccompiler helper fixture" + + class Seccompiler: + "A seccompiler helper class" + + def compile(self, data: dict, basic=False) -> Path: + "Use seccompiler-bin to compile a filter from a dict" + inp = tmp_path / "input.json" + inp.write_text(json.dumps(data)) + bpf = tmp_path / "output.bpfmap" + run_seccompiler_bin(bpf_path=bpf, json_path=inp, basic=basic) + return bpf + + return Seccompiler() diff --git a/tests/integration_tests/security/test_custom_seccomp.py b/tests/integration_tests/security/test_custom_seccomp.py index 5fffb83f6cc..05f9b9aa96e 100644 --- a/tests/integration_tests/security/test_custom_seccomp.py +++ b/tests/integration_tests/security/test_custom_seccomp.py @@ -2,179 +2,76 @@ # SPDX-License-Identifier: Apache-2.0 """Tests that the --seccomp-filter parameter works as expected.""" -import os import platform -import tempfile import time +from pathlib import Path -import pytest import requests from framework import utils -from host_tools.cargo_build import run_seccompiler_bin -def _custom_filter_setup(test_microvm, json_filter): - json_temp = tempfile.NamedTemporaryFile(delete=False) - json_temp.write(json_filter) - json_temp.flush() +def install_filter(microvm, bpf_path): + """Install seccomp filter in microvm.""" + microvm.create_jailed_resource(bpf_path) + microvm.jailer.extra_args.update({"seccomp-filter": bpf_path.name}) - bpf_path = os.path.join(test_microvm.path, "bpf.out") - run_seccompiler_bin(bpf_path=bpf_path, json_path=json_temp.name) +def test_allow_all(uvm_plain, seccompiler): + """Test --seccomp-filter, allowing all syscalls.""" + seccomp_filter = { + thread: {"default_action": "allow", "filter_action": "trap", "filter": []} + for thread in ["vmm", "api", "vcpu"] + } - os.unlink(json_temp.name) - test_microvm.create_jailed_resource(bpf_path) - test_microvm.jailer.extra_args.update({"seccomp-filter": "bpf.out"}) - - -def _config_file_setup(test_microvm, vm_config_file): - test_microvm.create_jailed_resource(test_microvm.kernel_file) - test_microvm.create_jailed_resource(test_microvm.rootfs_file) - - vm_config_path = os.path.join(test_microvm.path, os.path.basename(vm_config_file)) - with open(vm_config_file, encoding="utf-8") as f1: - with open(vm_config_path, "w", encoding="utf-8") as f2: - for line in f1: - f2.write(line) - test_microvm.create_jailed_resource(vm_config_path) - test_microvm.jailer.extra_args = {"config-file": os.path.basename(vm_config_file)} - - test_microvm.jailer.extra_args.update({"no-api": None}) - - -def test_allow_all(uvm_plain): - """ - Test --seccomp-filter, allowing all syscalls. - """ + bpf_path = seccompiler.compile(seccomp_filter) test_microvm = uvm_plain - - _custom_filter_setup( - test_microvm, - """{ - "Vmm": { - "default_action": "allow", - "filter_action": "trap", - "filter": [] - }, - "Api": { - "default_action": "allow", - "filter_action": "trap", - "filter": [] - }, - "Vcpu": { - "default_action": "allow", - "filter_action": "trap", - "filter": [] - } - }""".encode( - "utf-8" - ), - ) - + install_filter(test_microvm, bpf_path) test_microvm.spawn() - test_microvm.basic_config() - test_microvm.start() - utils.assert_seccomp_level(test_microvm.firecracker_pid, "2") -def test_working_filter(uvm_plain): - """ - Test --seccomp-filter, rejecting some dangerous syscalls. - """ - test_microvm = uvm_plain +def test_working_filter(uvm_plain, seccompiler): + """Test --seccomp-filter, rejecting some dangerous syscalls.""" - _custom_filter_setup( - test_microvm, - """{ - "Vmm": { - "default_action": "allow", - "filter_action": "kill_process", - "filter": [ - { - "syscall": "clone" - }, - { - "syscall": "execve" - } - ] - }, - "Api": { - "default_action": "allow", - "filter_action": "kill_process", - "filter": [ - { - "syscall": "clone" - }, - { - "syscall": "execve" - } - ] - }, - "Vcpu": { + seccomp_filter = { + thread: { "default_action": "allow", "filter_action": "kill_process", - "filter": [ - { - "syscall": "clone" - }, - { - "syscall": "execve", - "comment": "sample comment" - } - ] + "filter": [{"syscall": "clone"}, {"syscall": "execve"}], } - }""".encode( - "utf-8" - ), - ) + for thread in ["vmm", "api", "vcpu"] + } + bpf_path = seccompiler.compile(seccomp_filter) + test_microvm = uvm_plain + install_filter(test_microvm, bpf_path) test_microvm.spawn() - test_microvm.basic_config() - test_microvm.start() # level should be 2, with no additional errors utils.assert_seccomp_level(test_microvm.firecracker_pid, "2") -def test_failing_filter(uvm_plain): - """ - Test --seccomp-filter, denying some needed syscalls. - """ - test_microvm = uvm_plain +def test_failing_filter(uvm_plain, seccompiler): + """Test --seccomp-filter, denying some needed syscalls.""" - _custom_filter_setup( - test_microvm, - """{ - "Vmm": { + seccomp_filter = { + "vmm": {"default_action": "allow", "filter_action": "trap", "filter": []}, + "api": {"default_action": "allow", "filter_action": "trap", "filter": []}, + "vcpu": { "default_action": "allow", "filter_action": "trap", - "filter": [] + "filter": [{"syscall": "ioctl"}], }, - "Api": { - "default_action": "allow", - "filter_action": "trap", - "filter": [] - }, - "Vcpu": { - "default_action": "allow", - "filter_action": "trap", - "filter": [ - { - "syscall": "ioctl" - } - ] - } - }""".encode( - "utf-8" - ), - ) + } + bpf_path = seccompiler.compile(seccomp_filter) + test_microvm = uvm_plain + install_filter(test_microvm, bpf_path) test_microvm.spawn() test_microvm.basic_config(vcpu_count=1) @@ -190,8 +87,7 @@ def test_failing_filter(uvm_plain): # Check the logger output ioctl_num = 16 if platform.machine() == "x86_64" else 29 test_microvm.check_log_message( - "Shutting down VM after intercepting a bad" - " syscall ({})".format(str(ioctl_num)) + f"Shutting down VM after intercepting a bad syscall ({ioctl_num})" ) # Check the metrics @@ -208,28 +104,28 @@ def test_failing_filter(uvm_plain): test_microvm.mark_killed() -@pytest.mark.parametrize("vm_config_file", ["framework/vm_config.json"]) -def test_invalid_bpf(uvm_plain, vm_config_file): - """ - Test that FC does not start, given an invalid binary filter. - """ +def test_invalid_bpf(uvm_plain): + """Test that FC does not start, given an invalid binary filter.""" test_microvm = uvm_plain # Configure VM from JSON. Otherwise, the test will error because # the process will be killed before configuring the API socket. - _config_file_setup(uvm_plain, vm_config_file) + test_microvm.create_jailed_resource(test_microvm.kernel_file) + test_microvm.create_jailed_resource(test_microvm.rootfs_file) - bpf_path = os.path.join(test_microvm.path, "bpf.out") - file = open(bpf_path, "w", encoding="utf-8") - file.write("Invalid BPF!") - file.close() + vm_config_file = Path("framework/vm_config.json") + test_microvm.create_jailed_resource(vm_config_file) + test_microvm.jailer.extra_args = {"config-file": vm_config_file.name} + test_microvm.jailer.extra_args.update({"no-api": None}) + bpf_path = Path(test_microvm.path) / "bpf.out" + bpf_path.write_bytes(b"Invalid BPF!") test_microvm.create_jailed_resource(bpf_path) - test_microvm.jailer.extra_args.update({"seccomp-filter": "bpf.out"}) + test_microvm.jailer.extra_args.update({"seccomp-filter": bpf_path.name}) test_microvm.spawn() - # give time for the process to get killed time.sleep(1) + assert "Seccomp error: Filter deserialization failed" in test_microvm.log_data test_microvm.mark_killed() diff --git a/tests/integration_tests/security/test_seccomp.py b/tests/integration_tests/security/test_seccomp.py index 0fa9aefafcb..8ae87271daf 100644 --- a/tests/integration_tests/security/test_seccomp.py +++ b/tests/integration_tests/security/test_seccomp.py @@ -2,91 +2,47 @@ # SPDX-License-Identifier: Apache-2.0 """Tests that the seccomp filters don't let denied syscalls through.""" -import json as json_lib +import json import os import platform -import tempfile +from pathlib import Path from framework import utils -from host_tools.cargo_build import run_seccompiler_bin + +ARCH = platform.machine() def _get_basic_syscall_list(): """Return the JSON list of syscalls that the demo jailer needs.""" - if platform.machine() == "x86_64": - sys_list = [ - "rt_sigprocmask", - "rt_sigaction", - "execve", - "mmap", - "mprotect", + sys_list = [ + "rt_sigprocmask", + "rt_sigaction", + "execve", + "mmap", + "mprotect", + "set_tid_address", + "read", + "close", + "brk", + "sched_getaffinity", + "sigaltstack", + "munmap", + "exit_group", + ] + if ARCH == "x86_64": + sys_list += [ "arch_prctl", - "set_tid_address", "readlink", "open", - "read", - "close", - "brk", - "sched_getaffinity", - "sigaltstack", - "munmap", - "exit_group", "poll", ] - else: - # platform.machine() == "aarch64" - sys_list = [ - "rt_sigprocmask", - "rt_sigaction", - "execve", - "mmap", - "mprotect", - "set_tid_address", - "read", - "close", - "brk", - "sched_getaffinity", - "sigaltstack", - "munmap", - "exit_group", - "ppoll", - ] - - json = "" - for syscall in sys_list[0:-1]: - json += """ - {{ - "syscall": \"{}\" - }}, - """.format( - syscall - ) - - json += """ - {{ - "syscall": \"{}\" - }} - """.format( - sys_list[-1] - ) - - return json - - -def _run_seccompiler_bin(json_data, basic=False): - json_temp = tempfile.NamedTemporaryFile(delete=False) - json_temp.write(json_data.encode("utf-8")) - json_temp.flush() - - bpf_temp = tempfile.NamedTemporaryFile(delete=False) + elif ARCH == "aarch64": + sys_list += ["ppoll"] - run_seccompiler_bin(bpf_path=bpf_temp.name, json_path=json_temp.name, basic=basic) + return sys_list - os.unlink(json_temp.name) - return bpf_temp.name - -def test_seccomp_ls(bin_seccomp_paths): +def test_seccomp_ls(bin_seccomp_paths, seccompiler): """ Assert that the seccomp filter denies an unallowed syscall. """ @@ -99,32 +55,26 @@ def test_seccomp_ls(bin_seccomp_paths): demo_jailer = bin_seccomp_paths["demo_jailer"] assert os.path.exists(demo_jailer) - json_filter = """{{ - "main": {{ + json_filter = { + "main": { "default_action": "trap", "filter_action": "allow", - "filter": [ - {} - ] - }} - }}""".format( - _get_basic_syscall_list() - ) + "filter": [{"syscall": x} for x in _get_basic_syscall_list()], + } + } # Run seccompiler-bin. - bpf_path = _run_seccompiler_bin(json_filter) + bpf_path = seccompiler.compile(json_filter) # Run the mini jailer. outcome = utils.run_cmd([demo_jailer, ls_command_path, bpf_path], shell=False) - os.unlink(bpf_path) - # The seccomp filters should send SIGSYS (31) to the binary. `ls` doesn't # handle it, so it will exit with error. assert outcome.returncode != 0 -def test_advanced_seccomp(bin_seccomp_paths): +def test_advanced_seccomp(bin_seccomp_paths, seccompiler): """ Test seccompiler-bin with `demo_jailer`. @@ -143,39 +93,37 @@ def test_advanced_seccomp(bin_seccomp_paths): assert os.path.exists(demo_harmless) assert os.path.exists(demo_malicious) - json_filter = """{{ - "main": {{ + json_filter = { + "main": { "default_action": "trap", "filter_action": "allow", "filter": [ - {}, - {{ + *[{"syscall": x} for x in _get_basic_syscall_list()], + { "syscall": "write", "args": [ - {{ + { "index": 0, "type": "dword", "op": "eq", "val": 1, - "comment": "stdout fd" - }}, - {{ + "comment": "stdout fd", + }, + { "index": 2, "type": "qword", "op": "eq", "val": 14, - "comment": "nr of bytes" - }} - ] - }} - ] - }} - }}""".format( - _get_basic_syscall_list() - ) + "comment": "nr of bytes", + }, + ], + }, + ], + } + } # Run seccompiler-bin. - bpf_path = _run_seccompiler_bin(json_filter) + bpf_path = seccompiler.compile(json_filter) # Run the mini jailer for harmless binary. outcome = utils.run_cmd([demo_jailer, demo_harmless, bpf_path], shell=False) @@ -189,10 +137,8 @@ def test_advanced_seccomp(bin_seccomp_paths): # The demo malicious binary should have received `SIGSYS`. assert outcome.returncode == -31 - os.unlink(bpf_path) - # Run seccompiler-bin with `--basic` flag. - bpf_path = _run_seccompiler_bin(json_filter, basic=True) + bpf_path = seccompiler.compile(json_filter, basic=True) # Run the mini jailer for malicious binary. outcome = utils.run_cmd([demo_jailer, demo_malicious, bpf_path], shell=False) @@ -201,28 +147,20 @@ def test_advanced_seccomp(bin_seccomp_paths): # disables all argument checks. assert outcome.returncode == 0 - os.unlink(bpf_path) - # Run the mini jailer with an empty allowlist. It should trap on any # syscall. - json_filter = """{ - "main": { - "default_action": "trap", - "filter_action": "allow", - "filter": [] - } - }""" + json_filter = { + "main": {"default_action": "trap", "filter_action": "allow", "filter": []} + } # Run seccompiler-bin. - bpf_path = _run_seccompiler_bin(json_filter) + bpf_path = seccompiler.compile(json_filter) outcome = utils.run_cmd([demo_jailer, demo_harmless, bpf_path], shell=False) # The demo binary should have received `SIGSYS`. assert outcome.returncode == -31 - os.unlink(bpf_path) - def test_no_seccomp(uvm_plain): """ @@ -231,11 +169,8 @@ def test_no_seccomp(uvm_plain): test_microvm = uvm_plain test_microvm.jailer.extra_args.update({"no-seccomp": None}) test_microvm.spawn() - test_microvm.basic_config() - test_microvm.start() - utils.assert_seccomp_level(test_microvm.firecracker_pid, "0") @@ -245,15 +180,12 @@ def test_default_seccomp_level(uvm_plain): """ test_microvm = uvm_plain test_microvm.spawn() - test_microvm.basic_config() - test_microvm.start() - utils.assert_seccomp_level(test_microvm.firecracker_pid, "2") -def test_seccomp_rust_panic(bin_seccomp_paths): +def test_seccomp_rust_panic(bin_seccomp_paths, seccompiler): """ Test seccompiler-bin with `demo_panic`. @@ -266,19 +198,15 @@ def test_seccomp_rust_panic(bin_seccomp_paths): demo_panic = bin_seccomp_paths["demo_panic"] assert os.path.exists(demo_panic) - fc_filters_path = "../resources/seccomp/{}-unknown-linux-musl.json".format( - platform.machine() - ) - with open(fc_filters_path, "r", encoding="utf-8") as fc_filters: - filter_threads = list(json_lib.loads(fc_filters.read())) + fc_filters = Path(f"../resources/seccomp/{ARCH}-unknown-linux-musl.json") + fc_filters_data = json.loads(fc_filters.read_text(encoding="ascii")) + filter_threads = list(fc_filters_data) - bpf_temp = tempfile.NamedTemporaryFile(delete=False) - run_seccompiler_bin(bpf_path=bpf_temp.name, json_path=fc_filters_path) - bpf_path = bpf_temp.name + bpf_path = seccompiler.compile(fc_filters_data) # Run the panic binary with all filters. for thread in filter_threads: - code, _, _ = utils.run_cmd([demo_panic, bpf_path, thread], shell=False) + code, _, _ = utils.run_cmd([demo_panic, str(bpf_path), thread], shell=False) # The demo panic binary should have terminated with SIGABRT # and not with a seccomp violation. # On a seccomp violation, the program exits with code -31 for @@ -286,8 +214,4 @@ def test_seccomp_rust_panic(bin_seccomp_paths): # is for SIGABRT. assert ( code == -6 - ), "Panic binary failed with exit code {} on {} " "filters.".format( - code, thread - ) - - os.unlink(bpf_path) + ), f"Panic binary failed with exit code {code} on {thread} filters." From 20275947ab2d241452d090b2bc6efb839685b8af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 5 Dec 2024 16:18:39 +0100 Subject: [PATCH 49/78] docs: reflect that seccompiler --basic filters are deprecated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit seccompiler --basic filters are deprecated Signed-off-by: Pablo Barbáchano --- DEPRECATED.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DEPRECATED.md b/DEPRECATED.md index ca9068d773d..e20e4af628a 100644 --- a/DEPRECATED.md +++ b/DEPRECATED.md @@ -19,3 +19,5 @@ a future major Firecracker release, in accordance with our - \[[#4428](https://github.com/firecracker-microvm/firecracker/pull/4428)\] Booting microVMs using MPTable and command line parameters for VirtIO devices. The functionality is substituted with ACPI. +- \[[#2628](https://github.com/firecracker-microvm/firecracker/pull/2628)\] The + `--basic` parameter of `seccompiler-bin`. From 979cf1b23eaa874f6befc60409139945d702ffbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 9 Dec 2024 23:50:50 +0100 Subject: [PATCH 50/78] tests: add test to validate seccomp filters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a test to validate that a seccomp filter works as defined in the JSON description. To do this we use a simple C program that just loads a given seccomp filter and calls a syscall also given in the arguments. Signed-off-by: Pablo Barbáchano --- tests/host_tools/test_syscalls.c | 77 ++++++++++ .../security/test_seccomp_validate.py | 138 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 tests/host_tools/test_syscalls.c create mode 100644 tests/integration_tests/security/test_seccomp_validate.py diff --git a/tests/host_tools/test_syscalls.c b/tests/host_tools/test_syscalls.c new file mode 100644 index 00000000000..6a58edf0983 --- /dev/null +++ b/tests/host_tools/test_syscalls.c @@ -0,0 +1,77 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// This is used by `test_seccomp_validate.py` + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +void install_bpf_filter(char *bpf_file) { + int fd = open(bpf_file, O_RDONLY); + if (fd == -1) { + perror("open"); + exit(EXIT_FAILURE); + } + struct stat sb; + if (fstat(fd, &sb) == -1) { + perror("stat"); + exit(EXIT_FAILURE); + } + size_t size = sb.st_size; + size_t insn_len = size / sizeof(struct sock_filter); + struct sock_filter *filterbuf = (struct sock_filter*)malloc(size); + if (read(fd, filterbuf, size) == -1) { + perror("read"); + exit(EXIT_FAILURE); + } + + /* Install seccomp filter */ + struct sock_fprog prog = { + .len = (unsigned short)(insn_len), + .filter = filterbuf, + }; + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl(NO_NEW_PRIVS)"); + exit(EXIT_FAILURE); + } + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { + perror("prctl(SECCOMP)"); + exit(EXIT_FAILURE); + } +} + + +int main(int argc, char **argv) { + /* parse arguments */ + if (argc < 3) { + fprintf(stderr, "Usage: %s BPF_FILE ARG0..\n", argv[0]); + exit(EXIT_FAILURE); + } + char *bpf_file = argv[1]; + long syscall_id = atoi(argv[2]); + long arg0, arg1, arg2, arg3; + arg0 = arg1 = arg2 = arg3 = 0; + if (argc > 3) arg0 = atoi(argv[3]); + if (argc > 4) arg1 = atoi(argv[4]); + if (argc > 5) arg2 = atoi(argv[5]); + if (argc > 6) arg3 = atoi(argv[6]); + + /* read seccomp filter from file */ + if (strcmp(bpf_file, "/dev/null") != 0) { + install_bpf_filter(bpf_file); + } + + long res = syscall(syscall_id, arg0, arg1, arg2, arg3); + printf("%ld\n", res); + return EXIT_SUCCESS; +} diff --git a/tests/integration_tests/security/test_seccomp_validate.py b/tests/integration_tests/security/test_seccomp_validate.py new file mode 100644 index 00000000000..5a0be067899 --- /dev/null +++ b/tests/integration_tests/security/test_seccomp_validate.py @@ -0,0 +1,138 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Test that validates that seccompiler filters work as expected""" + +import json +import platform +import resource +import struct +from pathlib import Path + +import pytest +import seccomp + +from framework import utils +from host_tools import cargo_build + +ARCH = platform.machine() + + +@pytest.fixture(scope="session") +def bin_test_syscall(test_fc_session_root_path): + """Build the test_syscall binary.""" + test_syscall_bin = Path(test_fc_session_root_path) / "test_syscall" + cargo_build.gcc_compile("host_tools/test_syscalls.c", test_syscall_bin) + assert test_syscall_bin.exists() + yield test_syscall_bin + + +class BpfMapReader: + """ + Simple reader for the files that seccompiler-bin produces + + The files are serialized with bincode[1] in format that is easy to parse. + + sock_filter = + BpfProgram = Vec + BpfMap = BTreeMap(str, BpfProgram) + str = Vec + + [1] https://github.com/bincode-org/bincode/blob/trunk/docs/spec.md + """ + + INSN_FMT = " Date: Fri, 29 Nov 2024 11:06:00 +0000 Subject: [PATCH 51/78] test: fix malformed f string in microvm_helpers.py My python version does not accept the precense of double quotes inside a double-quoted f-string. Use single quotes instead. Signed-off-by: Patrick Roy --- tests/framework/microvm_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/framework/microvm_helpers.py b/tests/framework/microvm_helpers.py index f29ae84a9a0..b34da3c447e 100644 --- a/tests/framework/microvm_helpers.py +++ b/tests/framework/microvm_helpers.py @@ -242,6 +242,6 @@ def trace_cmd_guest(self, fns, cmd, port=4321): print("guest> trace-cmd record") host_ip = self.vm.iface["eth0"]["iface"].host_ip _guest_ps = self.vm.ssh.run( - f"trace-cmd record -N {host_ip}:{port} -p function {" ".join(fns)} {cmd}" + f"trace-cmd record -N {host_ip}:{port} -p function {' '.join(fns)} {cmd}" ) return list(Path(".").glob("trace.*.dat")) From b3d202b1926fe31daf534c28e2699566c36eb5aa Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 13:13:33 +0000 Subject: [PATCH 52/78] test: close stdout/stderr after timeout in utils.run_cmd If a command times out in utils.run_cmd, we kill the subprocess and try to get whatever partial output it wrote so far to generate an error message. We do this using `communicate`, which waits for stdout/stderr to close. Some processes pass their stdout and stderr to their children. In this case, killing the parent won't close the stdout/stderr, and so the proc.communicate() call in run_cmd will wait indefinitely (or until whatever is holding on the the other end of the pipe exits). Avoid this by explicitly closing our end of the stdout/stderr pipes. Signed-off-by: Patrick Roy --- tests/framework/utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/framework/utils.py b/tests/framework/utils.py index e71302545c9..8bb1d8c744e 100644 --- a/tests/framework/utils.py +++ b/tests/framework/utils.py @@ -397,6 +397,12 @@ def run_cmd(cmd, check=False, shell=True, cwd=None, timeout=None) -> CommandRetu stdout, stderr = proc.communicate(timeout=timeout) except subprocess.TimeoutExpired: proc.kill() + + # Sometimes stdout/stderr are passed on to children, in which case killing + # the parent won't close them and communicate will still hang. + proc.stdout.close() + proc.stderr.close() + stdout, stderr = proc.communicate() # Log the message with one call so that multiple statuses From fd77b79a4cc3cf69d8626138d8d5cd539c9e6170 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 13:16:34 +0000 Subject: [PATCH 53/78] test: fix assertions in test_pause_resume We asserted twice that the guest is not responsive anymore after pausing, and zero times that it is responsive again after resuming. Fix this by doing each once. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_pause_resume.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/integration_tests/functional/test_pause_resume.py b/tests/integration_tests/functional/test_pause_resume.py index 3d0ac124c11..4b15c86ddfc 100644 --- a/tests/integration_tests/functional/test_pause_resume.py +++ b/tests/integration_tests/functional/test_pause_resume.py @@ -59,10 +59,6 @@ def test_pause_resume(uvm_nano): # guest or host side were handled. verify_net_emulation_paused(microvm.flush_metrics()) - # Verify guest is no longer active. - with pytest.raises(ChildProcessError): - microvm.ssh.check_output("true") - # Pausing the microVM when it is already `Paused` is allowed # (microVM remains in `Paused` state). microvm.api.vm.patch(state="Paused") @@ -71,6 +67,7 @@ def test_pause_resume(uvm_nano): microvm.api.vm.patch(state="Resumed") # Verify guest is active again. + microvm.ssh.check_output("true") # Resuming the microVM when it is already `Resumed` is allowed # (microVM remains in the running state). From b99abe1bd7a9e8b9b80df0b9ea8197849c6dabf0 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 14:03:13 +0000 Subject: [PATCH 54/78] test: remove timeout from test_high_ingress_traffic It's a fairly tight timeout, and I was hitting it quite frequently while running functional tests with high parallelism. I don't really see any reason why we should be concerned about this specific command simply hitting the pytest timeout when things go wrong, so let's just remove the timeout. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_net.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index 2072d015ca2..efccd946c61 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -41,9 +41,9 @@ def test_high_ingress_traffic(uvm_plain_any): time.sleep(1) # Start iperf3 client on the host. Send 1Gbps UDP traffic. - # If the net device breaks, iperf will freeze. We have to use a timeout. + # If the net device breaks, iperf will freeze, and we'll hit the pytest timeout utils.check_output( - "timeout 31 {} {} -c {} -u -V -b 1000000000 -t 30".format( + "{} {} -c {} -u -V -b 1000000000 -t 30".format( test_microvm.netns.cmd_prefix(), IPERF_BINARY_HOST, guest_ip, From 36448e94ebf43f04fc55dac5aa2fae6f9132bfea Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 14:04:58 +0000 Subject: [PATCH 55/78] test: set default timeout of 100s for ssh commands Opportunistically set a 100s timeout. We don't have anything that should run this long, and by manually setting a timeout we avoid hitting the pytest timeout of 300s in case something _does_ go wrong (and hitting the pytest timeout gives significantly less debug information, so a manual timeout is preferred). Signed-off-by: Patrick Roy --- tests/host_tools/network.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py index 7877b914d28..4a961e025df 100644 --- a/tests/host_tools/network.py +++ b/tests/host_tools/network.py @@ -109,9 +109,9 @@ def _init_connection(self): We'll keep trying to execute a remote command that can't fail (`/bin/true`), until we get a successful (0) exit code. """ - self.check_output("true", timeout=100, debug=True) + self.check_output("true", debug=True) - def run(self, cmd_string, timeout=None, *, check=False, debug=False): + def run(self, cmd_string, timeout=100, *, check=False, debug=False): """ Execute the command passed as a string in the ssh context. @@ -124,11 +124,11 @@ def run(self, cmd_string, timeout=None, *, check=False, debug=False): return self._exec(command, timeout, check=check) - def check_output(self, cmd_string, timeout=None, *, debug=False): + def check_output(self, cmd_string, timeout=100, *, debug=False): """Same as `run`, but raises an exception on non-zero return code of remote command""" return self.run(cmd_string, timeout, check=True, debug=debug) - def _exec(self, cmd, timeout=None, check=False): + def _exec(self, cmd, timeout=100, check=False): """Private function that handles the ssh client invocation.""" if self.netns is not None: cmd = ["ip", "netns", "exec", self.netns] + cmd From 030c2262c30a6e65a4fd9bc3fb42a6ae541853b7 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 14:44:31 +0000 Subject: [PATCH 56/78] test: simplify make_guest_dirty_memory Remove the logging from this function, because SSHConnection._exec already does this. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_balloon.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/integration_tests/functional/test_balloon.py b/tests/integration_tests/functional/test_balloon.py index 2c59fd2e814..41a790190de 100644 --- a/tests/integration_tests/functional/test_balloon.py +++ b/tests/integration_tests/functional/test_balloon.py @@ -62,18 +62,10 @@ def lower_ssh_oom_chance(ssh_connection): def make_guest_dirty_memory(ssh_connection, amount_mib=32): """Tell the guest, over ssh, to dirty `amount` pages of memory.""" - logger = logging.getLogger("make_guest_dirty_memory") - lower_ssh_oom_chance(ssh_connection) - cmd = f"/usr/local/bin/fillmem {amount_mib}" try: - exit_code, stdout, stderr = ssh_connection.run(cmd, timeout=1.0) - # add something to the logs for troubleshooting - if exit_code != 0: - logger.error("while running: %s", cmd) - logger.error("stdout: %s", stdout) - logger.error("stderr: %s", stderr) + _ = ssh_connection.run(f"/usr/local/bin/fillmem {amount_mib}", timeout=1.0) except TimeoutExpired: # It's ok if this expires. Sometimes the SSH connection # gets killed by the OOM killer *after* the fillmem program From 3b2c2d4d69f41c99aecb2de10d8c04d6efc26bc9 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 10:57:35 +0000 Subject: [PATCH 57/78] test: use single SSH connection for lifetime of microvm Instead of creating new SSH connections every time we want to run a command inside the microvm, open a single daemonized ssh connection in the constructor of `SSHConnection`, and reuse it until we kill the microvm. Realize this using openssh's ControlMaster/ControlPersist functionality, which allows us to persist the first connection opened to a microvm and multiplex all subsequent commands over this one connection. We need some slight changes in test_pause_restore.py and test_net.py. In the former, since we no longer reconnect to the VM on every ssh command, we will now observe a timeout instead of a connection failure. For the latter, it turns out that @lru_cache treats .ssh_iface() and .ssh_iface(0) as distinct invokations, despire the iface_idx argument of ssh_iface defaulting to 0 (meaning they are actually the same function call). This caused a re-intialization of the SSHConnection object, which then triggered the assertion in _init_connection about the socket file not existing. Signed-off-by: Patrick Roy --- tests/framework/microvm.py | 11 +- tests/host_tools/network.py | 123 ++++++++++++------ .../integration_tests/functional/test_net.py | 7 +- .../functional/test_pause_resume.py | 5 +- 4 files changed, 96 insertions(+), 50 deletions(-) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index eb755ffc5fa..11fecf720a7 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -247,6 +247,8 @@ def __init__( self.mem_size_bytes = None self.cpu_template_name = None + self._connections = [] + self._pre_cmd = [] if numa_node: node_str = str(numa_node) @@ -282,6 +284,10 @@ def kill(self): for monitor in self.monitors: monitor.stop() + # Kill all background SSH connections + for connection in self._connections: + connection.close() + # We start with vhost-user backends, # because if we stop Firecracker first, the backend will want # to exit as well and this will cause a race condition. @@ -1007,13 +1013,16 @@ def ssh_iface(self, iface_idx=0): """Return a cached SSH connection on a given interface id.""" guest_ip = list(self.iface.values())[iface_idx]["iface"].guest_ip self.ssh_key = Path(self.ssh_key) - return net_tools.SSHConnection( + connection = net_tools.SSHConnection( netns=self.netns.id, ssh_key=self.ssh_key, user="root", host=guest_ip, + control_path=Path(self.chroot()) / f"ssh-{iface_idx}.sock", on_error=self._dump_debug_information, ) + self._connections.append(connection) + return connection @property def ssh(self): diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py index 4a961e025df..ff6e58be2b9 100644 --- a/tests/host_tools/network.py +++ b/tests/host_tools/network.py @@ -3,30 +3,35 @@ """Utilities for test host microVM network setup.""" import ipaddress +import os import random +import re +import signal import string -import subprocess from dataclasses import dataclass, field from pathlib import Path -from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_fixed +from tenacity import retry, stop_after_attempt, wait_fixed from framework import utils +from framework.utils import Timeout class SSHConnection: """ SSHConnection encapsulates functionality for microVM SSH interaction. - This class should be instantiated as part of the ssh fixture with the + This class should be instantiated as part of the ssh fixture with the hostname obtained from the MAC address, the username for logging into the image and the path of the ssh key. - This translates into an SSH connection as follows: - ssh -i ssh_key_path username@hostname + Establishes a ControlMaster upon construction, which is then re-used + for all subsequent SSH interactions. """ - def __init__(self, netns, ssh_key: Path, host, user, *, on_error=None): + def __init__( + self, netns, ssh_key: Path, control_path: Path, host, user, *, on_error=None + ): """Instantiate a SSH client and connect to a microVM.""" self.netns = netns self.ssh_key = ssh_key @@ -37,22 +42,13 @@ def __init__(self, netns, ssh_key: Path, host, user, *, on_error=None): assert (ssh_key.stat().st_mode & 0o777) == 0o400 self.host = host self.user = user + self._control_path = control_path self._on_error = None self.options = [ "-o", - "LogLevel=ERROR", - "-o", - "ConnectTimeout=1", - "-o", - "StrictHostKeyChecking=no", - "-o", - "UserKnownHostsFile=/dev/null", - "-o", - "PreferredAuthentications=publickey", - "-i", - str(self.ssh_key), + f"ControlPath={self._control_path}", ] # _init_connection loops until it can connect to the guest @@ -96,20 +92,82 @@ def scp_get(self, remote_path, local_path, recursive=False): self._scp(self.remote_path(remote_path), local_path, opts) @retry( - retry=retry_if_exception_type(ChildProcessError), - wait=wait_fixed(0.5), + wait=wait_fixed(1), stop=stop_after_attempt(20), reraise=True, ) def _init_connection(self): - """Create an initial SSH client connection (retry until it works). + """Initialize the persistent background connection which will be used + to execute all commands sent via this `SSHConnection` object. Since we're connecting to a microVM we just started, we'll probably have to wait for it to boot up and start the SSH server. We'll keep trying to execute a remote command that can't fail (`/bin/true`), until we get a successful (0) exit code. """ - self.check_output("true", debug=True) + assert not self._control_path.exists() + + # Sadly, we cannot get debug output from this command (e.g. `-vvv`), + # because passing -vvv causes the daemonized ssh to hold on to stderr, + # and inside utils.run_cmd we're using subprocess.communicate, which + # only returns once stderr gets closed (which would thus result in an + # indefinite hang). + establish_cmd = [ + "ssh", + # Only need to pass the ssh key here, as all multiplexed + # connections won't have to re-authenticate + "-i", + str(self.ssh_key), + "-o", + "StrictHostKeyChecking=no", + "-o", + "ConnectTimeout=2", + # Set up a persistent background connection + "-o", + "ControlMaster=auto", + "-o", + "ControlPersist=yes", + *self.options, + self.user_host, + "/usr/bin/true", + ] + + # don't set a low timeout here, because otherwise we might get into a race condition + # where ssh already forked off the persisted connection daemon, but gets killed here + # before exiting itself. In that case, self._control_path will exist, and the retry + # will hit the assert at the start of this function. + self._exec(establish_cmd, check=True) + + def _check_liveness(self) -> int: + """Checks whether the ControlPersist connection is still alive""" + check_cmd = ["ssh", "-O", "check", *self.options, self.user_host] + + _, _, stderr = self._exec(check_cmd, check=True) + + pid_match = re.match(r"Master running \(pid=(\d+)\)", stderr) + + assert pid_match, f"SSH ControlMaster connection not alive anymore: {stderr}" + + return int(pid_match.group(1)) + + def close(self): + """Closes the ControlPersist connection""" + master_pid = self._check_liveness() + + stop_cmd = ["ssh", "-O", "stop", *self.options, self.user_host] + + _, _, stderr = self._exec(stop_cmd, check=True) + + assert "Stop listening request sent" in stderr + + try: + with Timeout(5): + utils.wait_process_termination(master_pid) + except TimeoutError: + # for some reason it won't exit, let's force it... + # if this also fails, when during teardown we'll get an error about + # "found a process with supposedly dead Firecracker's jailer ID" + os.kill(master_pid, signal.SIGKILL) def run(self, cmd_string, timeout=100, *, check=False, debug=False): """ @@ -117,6 +175,8 @@ def run(self, cmd_string, timeout=100, *, check=False, debug=False): If `debug` is set, pass `-vvv` to `ssh`. Note that this will clobber stderr. """ + self._check_liveness() + command = ["ssh", *self.options, self.user_host, cmd_string] if debug: @@ -141,27 +201,6 @@ def _exec(self, cmd, timeout=100, check=False): raise - # pylint:disable=invalid-name - def Popen( - self, - cmd: str, - stdin=subprocess.DEVNULL, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - **kwargs, - ) -> subprocess.Popen: - """Execute the command in the guest and return a Popen object. - - pop = uvm.ssh.Popen("while true; do echo $(date -Is) $RANDOM; sleep 1; done") - pop.stdout.read(16) - """ - cmd = ["ssh", *self.options, self.user_host, cmd] - if self.netns is not None: - cmd = ["ip", "netns", "exec", self.netns] + cmd - return subprocess.Popen( - cmd, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs - ) - def mac_from_ip(ip_address): """Create a MAC address based on the provided IP. diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index efccd946c61..7b784e453c5 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -112,11 +112,8 @@ def test_tap_offload(uvm_any): ) # Try to send a UDP message from host with UDP offload enabled - cmd = f"ip netns exec {vm.ssh_iface().netns} python3 ./host_tools/udp_offload.py {vm.ssh_iface().host} {port}" - ret = utils.run_cmd(cmd) - - # Check that the transmission was successful - assert ret.returncode == 0, f"{ret.stdout=} {ret.stderr=}" + cmd = f"ip netns exec {vm.ssh.netns} python3 ./host_tools/udp_offload.py {vm.ssh.host} {port}" + utils.check_output(cmd) # Check that the server received the message ret = vm.ssh.run(f"cat {out_filename}") diff --git a/tests/integration_tests/functional/test_pause_resume.py b/tests/integration_tests/functional/test_pause_resume.py index 4b15c86ddfc..34b9a9a7229 100644 --- a/tests/integration_tests/functional/test_pause_resume.py +++ b/tests/integration_tests/functional/test_pause_resume.py @@ -4,6 +4,7 @@ import platform import time +from subprocess import TimeoutExpired import pytest @@ -52,8 +53,8 @@ def test_pause_resume(uvm_nano): microvm.flush_metrics() # Verify guest is no longer active. - with pytest.raises(ChildProcessError): - microvm.ssh.check_output("true") + with pytest.raises(TimeoutExpired): + microvm.ssh.check_output("true", timeout=1) # Verify emulation was indeed paused and no events from either # guest or host side were handled. From 9455ed0420bcd4a7a9ea0f40662ee2d7c2195fb1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 15:51:02 +0000 Subject: [PATCH 58/78] poetry: remove fabric and netns dependencies With the ControlMaster/ControlPersist approach, these are no needed anymore. I'm not reverting the commit that added them because that also contained an update of poetry.lock. I'm also not rebuilding the devctr for this because the dependencies will simply be dropped the next time we're rebuilding it. Signed-off-by: Patrick Roy --- tools/devctr/poetry.lock | 360 +----------------------------------- tools/devctr/pyproject.toml | 2 - 2 files changed, 1 insertion(+), 361 deletions(-) diff --git a/tools/devctr/poetry.lock b/tools/devctr/poetry.lock index eb969e9eda2..b04d05efac9 100644 --- a/tools/devctr/poetry.lock +++ b/tools/devctr/poetry.lock @@ -210,44 +210,6 @@ files = [ [package.dependencies] aiohttp = "*" -[[package]] -name = "bcrypt" -version = "4.2.1" -description = "Modern password hashing for your software and your servers" -optional = false -python-versions = ">=3.7" -files = [ - {file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"}, - {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"}, - {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dbd0747208912b1e4ce730c6725cb56c07ac734b3629b60d4398f082ea718ad"}, - {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:aaa2e285be097050dba798d537b6efd9b698aa88eef52ec98d23dcd6d7cf6fea"}, - {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:76d3e352b32f4eeb34703370e370997065d28a561e4a18afe4fef07249cb4396"}, - {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:b7703ede632dc945ed1172d6f24e9f30f27b1b1a067f32f68bf169c5f08d0425"}, - {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:89df2aea2c43be1e1fa066df5f86c8ce822ab70a30e4c210968669565c0f4685"}, - {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:04e56e3fe8308a88b77e0afd20bec516f74aecf391cdd6e374f15cbed32783d6"}, - {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cfdf3d7530c790432046c40cda41dfee8c83e29482e6a604f8930b9930e94139"}, - {file = "bcrypt-4.2.1-cp37-abi3-win32.whl", hash = "sha256:adadd36274510a01f33e6dc08f5824b97c9580583bd4487c564fc4617b328005"}, - {file = "bcrypt-4.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:8c458cd103e6c5d1d85cf600e546a639f234964d0228909d8f8dbeebff82d526"}, - {file = "bcrypt-4.2.1-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:8ad2f4528cbf0febe80e5a3a57d7a74e6635e41af1ea5675282a33d769fba413"}, - {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909faa1027900f2252a9ca5dfebd25fc0ef1417943824783d1c8418dd7d6df4a"}, - {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cde78d385d5e93ece5479a0a87f73cd6fa26b171c786a884f955e165032b262c"}, - {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:533e7f3bcf2f07caee7ad98124fab7499cb3333ba2274f7a36cf1daee7409d99"}, - {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:687cf30e6681eeda39548a93ce9bfbb300e48b4d445a43db4298d2474d2a1e54"}, - {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:041fa0155c9004eb98a232d54da05c0b41d4b8e66b6fc3cb71b4b3f6144ba837"}, - {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f85b1ffa09240c89aa2e1ae9f3b1c687104f7b2b9d2098da4e923f1b7082d331"}, - {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c6f5fa3775966cca251848d4d5393ab016b3afed251163c1436fefdec3b02c84"}, - {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:807261df60a8b1ccd13e6599c779014a362ae4e795f5c59747f60208daddd96d"}, - {file = "bcrypt-4.2.1-cp39-abi3-win32.whl", hash = "sha256:b588af02b89d9fad33e5f98f7838bf590d6d692df7153647724a7f20c186f6bf"}, - {file = "bcrypt-4.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:e84e0e6f8e40a242b11bce56c313edc2be121cec3e0ec2d76fce01f6af33c07c"}, - {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76132c176a6d9953cdc83c296aeaed65e1a708485fd55abf163e0d9f8f16ce0e"}, - {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e158009a54c4c8bc91d5e0da80920d048f918c61a581f0a63e4e93bb556d362f"}, - {file = "bcrypt-4.2.1.tar.gz", hash = "sha256:6765386e3ab87f569b276988742039baab087b2cdb01e809d74e74503c2faafe"}, -] - -[package.extras] -tests = ["pytest (>=3.2.1,!=3.3.0)"] -typecheck = ["mypy"] - [[package]] name = "black" version = "24.10.0" @@ -305,85 +267,6 @@ files = [ {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - [[package]] name = "charset-normalizer" version = "3.4.0" @@ -523,57 +406,6 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -[[package]] -name = "cryptography" -version = "44.0.0" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.7" -files = [ - {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, - {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, - {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, - {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, - {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, - {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, - {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] -docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] -sdist = ["build (>=1.0.0)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] -test-randomorder = ["pytest-randomly"] - [[package]] name = "decorator" version = "5.1.1" @@ -585,23 +417,6 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] -[[package]] -name = "deprecated" -version = "1.2.15" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -files = [ - {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"}, - {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"}, -] - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "jinja2 (>=3.0.3,<3.1.0)", "setuptools", "sphinx (<2)", "tox"] - [[package]] name = "dill" version = "0.3.9" @@ -659,26 +474,6 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] -[[package]] -name = "fabric" -version = "3.2.2" -description = "High level SSH command execution" -optional = false -python-versions = "*" -files = [ - {file = "fabric-3.2.2-py3-none-any.whl", hash = "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f"}, - {file = "fabric-3.2.2.tar.gz", hash = "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3"}, -] - -[package.dependencies] -decorator = ">=5" -deprecated = ">=1.2" -invoke = ">=2.0" -paramiko = ">=2.4" - -[package.extras] -pytest = ["pytest (>=7)"] - [[package]] name = "filelock" version = "3.16.1" @@ -863,17 +658,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "invoke" -version = "2.2.0" -description = "Pythonic task execution" -optional = false -python-versions = ">=3.6" -files = [ - {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, - {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, -] - [[package]] name = "ipython" version = "8.30.0" @@ -1347,16 +1131,6 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] -[[package]] -name = "netns" -version = "1.0" -description = "Wrapper for the Linux setns() system call" -optional = false -python-versions = "*" -files = [ - {file = "netns-1.0.tar.gz", hash = "sha256:dc994c53e415baa739072784292630724d609566fb4a60ed8feef38dd9ecdca5"}, -] - [[package]] name = "numpy" version = "2.2.0" @@ -1465,27 +1239,6 @@ files = [ {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] -[[package]] -name = "paramiko" -version = "3.5.0" -description = "SSH2 protocol library" -optional = false -python-versions = ">=3.6" -files = [ - {file = "paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"}, - {file = "paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"}, -] - -[package.dependencies] -bcrypt = ">=3.2" -cryptography = ">=3.3" -pynacl = ">=1.5" - -[package.extras] -all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] -gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] -invoke = ["invoke (>=2.0)"] - [[package]] name = "parso" version = "0.8.4" @@ -1728,17 +1481,6 @@ files = [ [package.extras] tests = ["pytest"] -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - [[package]] name = "pygments" version = "2.18.0" @@ -1782,32 +1524,6 @@ tomlkit = ">=0.10.1" spelling = ["pyenchant (>=3.2,<4.0)"] testutils = ["gitpython (>3)"] -[[package]] -name = "pynacl" -version = "1.5.0" -description = "Python binding to the Networking and Cryptography (NaCl) library" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] - -[package.dependencies] -cffi = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] - [[package]] name = "pytest" version = "8.3.4" @@ -2565,80 +2281,6 @@ files = [ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] -[[package]] -name = "wrapt" -version = "1.17.0" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.8" -files = [ - {file = "wrapt-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8"}, - {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d"}, - {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df"}, - {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d"}, - {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea"}, - {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb"}, - {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301"}, - {file = "wrapt-1.17.0-cp310-cp310-win32.whl", hash = "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22"}, - {file = "wrapt-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575"}, - {file = "wrapt-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a"}, - {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed"}, - {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489"}, - {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9"}, - {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339"}, - {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d"}, - {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b"}, - {file = "wrapt-1.17.0-cp311-cp311-win32.whl", hash = "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346"}, - {file = "wrapt-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a"}, - {file = "wrapt-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569"}, - {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504"}, - {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451"}, - {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1"}, - {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106"}, - {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada"}, - {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4"}, - {file = "wrapt-1.17.0-cp312-cp312-win32.whl", hash = "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635"}, - {file = "wrapt-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7"}, - {file = "wrapt-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181"}, - {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393"}, - {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4"}, - {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b"}, - {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721"}, - {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90"}, - {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a"}, - {file = "wrapt-1.17.0-cp313-cp313-win32.whl", hash = "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045"}, - {file = "wrapt-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838"}, - {file = "wrapt-1.17.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b"}, - {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379"}, - {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d"}, - {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f"}, - {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c"}, - {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b"}, - {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab"}, - {file = "wrapt-1.17.0-cp313-cp313t-win32.whl", hash = "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf"}, - {file = "wrapt-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a"}, - {file = "wrapt-1.17.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13"}, - {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f"}, - {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c"}, - {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d"}, - {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce"}, - {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627"}, - {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f"}, - {file = "wrapt-1.17.0-cp38-cp38-win32.whl", hash = "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea"}, - {file = "wrapt-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed"}, - {file = "wrapt-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1"}, - {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c"}, - {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578"}, - {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33"}, - {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad"}, - {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9"}, - {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0"}, - {file = "wrapt-1.17.0-cp39-cp39-win32.whl", hash = "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88"}, - {file = "wrapt-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977"}, - {file = "wrapt-1.17.0-py3-none-any.whl", hash = "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371"}, - {file = "wrapt-1.17.0.tar.gz", hash = "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801"}, -] - [[package]] name = "yarl" version = "1.18.3" @@ -2738,4 +2380,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.10.0" -content-hash = "c3b6e2c1d9a0a7926b61ca38f9e91fd1c1c0519a1703d6eaa0fd07fcf5898cbd" +content-hash = "e38bfcb8811fb9b774956ed4b0e82603dbe5b66d8cb5bc4af6ed86417a9d5d1d" diff --git a/tools/devctr/pyproject.toml b/tools/devctr/pyproject.toml index 188a3b315bd..a4f7178aa5d 100644 --- a/tools/devctr/pyproject.toml +++ b/tools/devctr/pyproject.toml @@ -10,7 +10,6 @@ aws-embedded-metrics = "^3.1.0" black = "^24.3.0" # Gitlint locks this to 8.1.3. Lock from our side too to prevent different versions click = "8.1.3" -fabric = "^3.2.2" filelock = "^3.13.4" gitlint = "^0.19.1" ipython = "^8.15.0" @@ -19,7 +18,6 @@ mdformat = "^0.7.17" mdformat-gfm = "^0.3.5" mdformat-footnote = "^0.1.1" mdformat-frontmatter = "^2.0.8" -netns = "^1.0.0" openapi-spec-validator = "^0.7.1" psutil = "^6.0.0" pylint = "^3" From 8c7ee82f9d603faa6776671024ca7258c8e28d19 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 16:08:50 +0000 Subject: [PATCH 59/78] fix: properly clean up tmp dir after shared build Building the A/B binaries happens in a tmpdir, which we try to delete at the end. But we create files in the tmpdir from a privileged docker container, so to delete this tmpdir we also need elevated privileges Signed-off-by: Patrick Roy --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 3b4d89ec392..7d41229b2e7 100755 --- a/tools/devtool +++ b/tools/devtool @@ -525,7 +525,7 @@ cmd_build() { git branch -D $branch_name mkdir -p build/"$revision" cp $tmp_dir/build/cargo_target/$(uname -m)-unknown-linux-$libc/$profile/* build/"$revision" - rm -rf $tmp_dir + cmd_sh "rm -rf $tmp_dir" fi return $ret From 0b4266b0f3112e949bb4bf6eb5425c2d8ff097cb Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 13 Dec 2024 08:12:11 +0000 Subject: [PATCH 60/78] fix(test): remove timeouts from MSR integration tests These run in a nightly pipeline and apparently the read/write MSR scripts take longer than the 100s default timeout added in b99abe1. Fixes: 36448e94ebf4 ("test: set default timeout of 100s for ssh commands") Signed-off-by: Patrick Roy --- .../functional/test_cpu_features_x86_64.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/integration_tests/functional/test_cpu_features_x86_64.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py index 1af6a39f83a..dce36254cb6 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -314,7 +314,7 @@ def test_cpu_rdmsr( ) vm.start() vm.ssh.scp_put(DATA_FILES / "msr_reader.sh", "/tmp/msr_reader.sh") - _, stdout, stderr = vm.ssh.run("/tmp/msr_reader.sh") + _, stdout, stderr = vm.ssh.run("/tmp/msr_reader.sh", timeout=None) assert stderr == "" # Load results read from the microvm @@ -362,7 +362,9 @@ def dump_msr_state_to_file(dump_fname, ssh_conn, shared_names): ssh_conn.scp_put( shared_names["msr_reader_host_fname"], shared_names["msr_reader_guest_fname"] ) - _, stdout, stderr = ssh_conn.run(shared_names["msr_reader_guest_fname"]) + _, stdout, stderr = ssh_conn.run( + shared_names["msr_reader_guest_fname"], timeout=None + ) assert stderr == "" with open(dump_fname, "w", encoding="UTF-8") as file: @@ -416,7 +418,9 @@ def test_cpu_wrmsr_snapshot(microvm_factory, guest_kernel, rootfs, msr_cpu_templ wrmsr_input_guest_fname = "/tmp/wrmsr_input.txt" vm.ssh.scp_put(wrmsr_input_host_fname, wrmsr_input_guest_fname) - _, _, stderr = vm.ssh.run(f"{msr_writer_guest_fname} {wrmsr_input_guest_fname}") + _, _, stderr = vm.ssh.run( + f"{msr_writer_guest_fname} {wrmsr_input_guest_fname}", timeout=None + ) assert stderr == "" # Dump MSR state to a file that will be published to S3 for the 2nd part of the test From e56b6a2f109e036d31966cde0f0f963e4ac5172c Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 13 Dec 2024 08:25:16 +0000 Subject: [PATCH 61/78] gitlint: ignore "Fixes" lines Since these repeat commit titles, they can get longer than the configured body line length. So just ignore them. Signed-off-by: Patrick Roy --- .gitlint | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlint b/.gitlint index 8840b19bfe8..3b0cc0e07a0 100644 --- a/.gitlint +++ b/.gitlint @@ -9,8 +9,8 @@ line-length=72 [ignore-body-lines] # Ignore HTTP reference links -# Ignore lines that start with 'Co-Authored-By' or with 'Signed-off-by' -regex=(^\[.+\]: http.+)|(^Co-Authored-By)|(^Signed-off-by) +# Ignore lines that start with 'Co-Authored-By', with 'Signed-off-by' or with 'Fixes' +regex=(^\[.+\]: http.+)|(^Co-Authored-By)|(^Signed-off-by)|(^Fixes:) [ignore-by-author-name] # Ignore certain rules for commits of which the author name matches a regex From e7ccf54e7ca8997b8d4be9f9f2240aea10046ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 12 Dec 2024 15:20:43 +0100 Subject: [PATCH 62/78] tests: compile test_syscall with musl-gcc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In addition do a few more cleanups to the test: - Use `atol` to read longs - musl makes an ioctl that is not permitted in seccomp. We didn't use the return code anyway, so remove it. Signed-off-by: Pablo Barbáchano --- tests/host_tools/test_syscalls.c | 13 ++++++------- .../security/test_seccomp_validate.py | 16 ++++++++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/host_tools/test_syscalls.c b/tests/host_tools/test_syscalls.c index 6a58edf0983..685e45acde0 100644 --- a/tests/host_tools/test_syscalls.c +++ b/tests/host_tools/test_syscalls.c @@ -28,7 +28,6 @@ void install_bpf_filter(char *bpf_file) { exit(EXIT_FAILURE); } size_t size = sb.st_size; - size_t insn_len = size / sizeof(struct sock_filter); struct sock_filter *filterbuf = (struct sock_filter*)malloc(size); if (read(fd, filterbuf, size) == -1) { perror("read"); @@ -36,6 +35,7 @@ void install_bpf_filter(char *bpf_file) { } /* Install seccomp filter */ + size_t insn_len = size / sizeof(struct sock_filter); struct sock_fprog prog = { .len = (unsigned short)(insn_len), .filter = filterbuf, @@ -60,11 +60,11 @@ int main(int argc, char **argv) { char *bpf_file = argv[1]; long syscall_id = atoi(argv[2]); long arg0, arg1, arg2, arg3; - arg0 = arg1 = arg2 = arg3 = 0; - if (argc > 3) arg0 = atoi(argv[3]); - if (argc > 4) arg1 = atoi(argv[4]); - if (argc > 5) arg2 = atoi(argv[5]); - if (argc > 6) arg3 = atoi(argv[6]); + arg0 = arg1 = arg2 = arg3 = 0L; + if (argc > 3) arg0 = atol(argv[3]); + if (argc > 4) arg1 = atol(argv[4]); + if (argc > 5) arg2 = atol(argv[5]); + if (argc > 6) arg3 = atol(argv[6]); /* read seccomp filter from file */ if (strcmp(bpf_file, "/dev/null") != 0) { @@ -72,6 +72,5 @@ int main(int argc, char **argv) { } long res = syscall(syscall_id, arg0, arg1, arg2, arg3); - printf("%ld\n", res); return EXIT_SUCCESS; } diff --git a/tests/integration_tests/security/test_seccomp_validate.py b/tests/integration_tests/security/test_seccomp_validate.py index 5a0be067899..b91c7590a2b 100644 --- a/tests/integration_tests/security/test_seccomp_validate.py +++ b/tests/integration_tests/security/test_seccomp_validate.py @@ -13,18 +13,18 @@ import seccomp from framework import utils -from host_tools import cargo_build ARCH = platform.machine() -@pytest.fixture(scope="session") -def bin_test_syscall(test_fc_session_root_path): +@pytest.fixture +def bin_test_syscall(tmp_path): """Build the test_syscall binary.""" - test_syscall_bin = Path(test_fc_session_root_path) / "test_syscall" - cargo_build.gcc_compile("host_tools/test_syscalls.c", test_syscall_bin) + test_syscall_bin = tmp_path / "test_syscall" + compile_cmd = f"musl-gcc -static host_tools/test_syscalls.c -o {test_syscall_bin}" + utils.check_output(compile_cmd) assert test_syscall_bin.exists() - yield test_syscall_bin + yield test_syscall_bin.resolve() class BpfMapReader: @@ -77,11 +77,11 @@ def split(self): for _ in range(map_len): # read key key_str_len = self.read_format(" Date: Fri, 13 Dec 2024 11:15:53 +0000 Subject: [PATCH 63/78] fix(test): ensure socat gets killed in test_5_snapshots Use a try-finally block inside check_guest_connection to make sure that socat gets killed even if something inside check_guest_connection fails and raises an exception. Signed-off-by: Patrick Roy --- tests/framework/utils_vsock.py | 96 +++++++++++++++++----------------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/tests/framework/utils_vsock.py b/tests/framework/utils_vsock.py index 3f6885e3afd..fe192e92f06 100644 --- a/tests/framework/utils_vsock.py +++ b/tests/framework/utils_vsock.py @@ -142,53 +142,55 @@ def check_guest_connections(vm, server_port_path, blob_path, blob_hash): ["socat", f"UNIX-LISTEN:{server_port_path},fork,backlog=5", "exec:'/bin/cat'"] ) - # Link the listening Unix socket into the VM's jail, so that - # Firecracker can connect to it. - attempt = 0 - # But 1st, give socat a bit of time to create the socket - while not Path(server_port_path).exists() and attempt < 3: - time.sleep(0.2) - attempt += 1 - vm.create_jailed_resource(server_port_path) - - # Increase maximum process count for the ssh service. - # Avoids: "bash: fork: retry: Resource temporarily unavailable" - # Needed to execute the bash script that tests for concurrent - # vsock guest initiated connections. - pids_max_file = "/sys/fs/cgroup/system.slice/ssh.service/pids.max" - ecode, _, _ = vm.ssh.run(f"echo 1024 > {pids_max_file}") - assert ecode == 0, "Unable to set max process count for guest ssh service." - - # Build the guest worker sub-command. - # `vsock_helper` will read the blob file from STDIN and send the echo - # server response to STDOUT. This response is then hashed, and the - # hash is compared against `blob_hash` (computed on the host). This - # comparison sets the exit status of the worker command. - worker_cmd = "hash=$(" - worker_cmd += "cat {}".format(blob_path) - worker_cmd += " | /tmp/vsock_helper echo 2 {}".format(ECHO_SERVER_PORT) - worker_cmd += " | md5sum | cut -f1 -d\\ " - worker_cmd += ")" - worker_cmd += ' && [[ "$hash" = "{}" ]]'.format(blob_hash) - - # Run `TEST_CONNECTION_COUNT` concurrent workers, using the above - # worker sub-command. - # If any worker fails, this command will fail. If all worker sub-commands - # succeed, this will also succeed. - cmd = 'workers="";' - cmd += "for i in $(seq 1 {}); do".format(TEST_CONNECTION_COUNT) - cmd += " ({})& ".format(worker_cmd) - cmd += ' workers="$workers $!";' - cmd += "done;" - cmd += "for w in $workers; do wait $w || (wait; exit 1); done" - - ecode, _, stderr = vm.ssh.run(cmd) - echo_server.terminate() - rc = echo_server.wait() - # socat exits with 128 + 15 (SIGTERM) - assert rc == 143 - - assert ecode == 0, stderr + try: + # Link the listening Unix socket into the VM's jail, so that + # Firecracker can connect to it. + attempt = 0 + # But 1st, give socat a bit of time to create the socket + while not Path(server_port_path).exists() and attempt < 3: + time.sleep(0.2) + attempt += 1 + vm.create_jailed_resource(server_port_path) + + # Increase maximum process count for the ssh service. + # Avoids: "bash: fork: retry: Resource temporarily unavailable" + # Needed to execute the bash script that tests for concurrent + # vsock guest initiated connections. + pids_max_file = "/sys/fs/cgroup/system.slice/ssh.service/pids.max" + ecode, _, _ = vm.ssh.run(f"echo 1024 > {pids_max_file}") + assert ecode == 0, "Unable to set max process count for guest ssh service." + + # Build the guest worker sub-command. + # `vsock_helper` will read the blob file from STDIN and send the echo + # server response to STDOUT. This response is then hashed, and the + # hash is compared against `blob_hash` (computed on the host). This + # comparison sets the exit status of the worker command. + worker_cmd = "hash=$(" + worker_cmd += "cat {}".format(blob_path) + worker_cmd += " | /tmp/vsock_helper echo 2 {}".format(ECHO_SERVER_PORT) + worker_cmd += " | md5sum | cut -f1 -d\\ " + worker_cmd += ")" + worker_cmd += ' && [[ "$hash" = "{}" ]]'.format(blob_hash) + + # Run `TEST_CONNECTION_COUNT` concurrent workers, using the above + # worker sub-command. + # If any worker fails, this command will fail. If all worker sub-commands + # succeed, this will also succeed. + cmd = 'workers="";' + cmd += "for i in $(seq 1 {}); do".format(TEST_CONNECTION_COUNT) + cmd += " ({})& ".format(worker_cmd) + cmd += ' workers="$workers $!";' + cmd += "done;" + cmd += "for w in $workers; do wait $w || (wait; exit 1); done" + + ecode, _, stderr = vm.ssh.run(cmd) + + assert ecode == 0, stderr + finally: + echo_server.terminate() + rc = echo_server.wait() + # socat exits with 128 + 15 (SIGTERM) + assert rc == 143 def make_host_port_path(uds_path, port): From 130af91a280d6a26db16893e18106a215be8799e Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 13 Dec 2024 11:18:15 +0000 Subject: [PATCH 64/78] refactor(test): Use check_output in check_guest_connections Now that the assertion on the `run` return code is paired with the .run call itself, combine them into .check_output. Also use check_output further up. Signed-off-by: Patrick Roy --- tests/framework/utils_vsock.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/framework/utils_vsock.py b/tests/framework/utils_vsock.py index fe192e92f06..244850c3496 100644 --- a/tests/framework/utils_vsock.py +++ b/tests/framework/utils_vsock.py @@ -156,9 +156,9 @@ def check_guest_connections(vm, server_port_path, blob_path, blob_hash): # Avoids: "bash: fork: retry: Resource temporarily unavailable" # Needed to execute the bash script that tests for concurrent # vsock guest initiated connections. - pids_max_file = "/sys/fs/cgroup/system.slice/ssh.service/pids.max" - ecode, _, _ = vm.ssh.run(f"echo 1024 > {pids_max_file}") - assert ecode == 0, "Unable to set max process count for guest ssh service." + vm.ssh.check_output( + "echo 1024 > /sys/fs/cgroup/system.slice/ssh.service/pids.max" + ) # Build the guest worker sub-command. # `vsock_helper` will read the blob file from STDIN and send the echo @@ -183,9 +183,7 @@ def check_guest_connections(vm, server_port_path, blob_path, blob_hash): cmd += "done;" cmd += "for w in $workers; do wait $w || (wait; exit 1); done" - ecode, _, stderr = vm.ssh.run(cmd) - - assert ecode == 0, stderr + vm.ssh.check_output(cmd) finally: echo_server.terminate() rc = echo_server.wait() From 77d3704f847d3ef32a33a0c18b330fb5e2534cb1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 13 Dec 2024 11:23:15 +0000 Subject: [PATCH 65/78] refactor(test): improve retry look in check_guest_connections Use `tenancy.Retrying` instead of the home-grown retry loop. This has the advantage that we don't simply give up after 3 attempts, but instead raise a meaningful error message (whereas before I guess we would just fail further down the function when trying to do something that assumes the file exists). Signed-off-by: Patrick Roy --- tests/framework/utils_vsock.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/framework/utils_vsock.py b/tests/framework/utils_vsock.py index 244850c3496..9561c1c26f2 100644 --- a/tests/framework/utils_vsock.py +++ b/tests/framework/utils_vsock.py @@ -11,6 +11,8 @@ from subprocess import Popen from threading import Thread +from tenacity import Retrying, stop_after_attempt, wait_fixed + ECHO_SERVER_PORT = 5252 SERVER_ACCEPT_BACKLOG = 128 TEST_CONNECTION_COUNT = 50 @@ -143,13 +145,17 @@ def check_guest_connections(vm, server_port_path, blob_path, blob_hash): ) try: + # Give socat a bit of time to create the socket + for attempt in Retrying( + wait=wait_fixed(0.2), + stop=stop_after_attempt(3), + reraise=True, + ): + with attempt: + assert Path(server_port_path).exists() + # Link the listening Unix socket into the VM's jail, so that # Firecracker can connect to it. - attempt = 0 - # But 1st, give socat a bit of time to create the socket - while not Path(server_port_path).exists() and attempt < 3: - time.sleep(0.2) - attempt += 1 vm.create_jailed_resource(server_port_path) # Increase maximum process count for the ssh service. From a8a240b8712396afc2f5c220ed32a1ec29b78267 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 15:42:01 +0000 Subject: [PATCH 66/78] test: add support for running commands with nightly toolchain Add a `nightly` flag to the `cargo` function, which causes the requested command to be executing using the nightly toolchain. We have a nightly toolchain in our container due to kani. But since the toolchain version is prescribed by kani, we need to dynamically determine its name from `rustup toolchain list`, and cannot just use `+nightly`. Signed-off-by: Patrick Roy --- tests/host_tools/cargo_build.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/host_tools/cargo_build.py b/tests/host_tools/cargo_build.py index da72e5433b2..5a029f8c5f4 100644 --- a/tests/host_tools/cargo_build.py +++ b/tests/host_tools/cargo_build.py @@ -14,6 +14,11 @@ DEFAULT_TARGET_DIR = f"{DEFAULT_TARGET}/release/" +def nightly_toolchain() -> str: + """Receives the name of the installed nightly toolchain""" + return utils.check_output("rustup toolchain list | grep nightly").stdout.strip() + + def cargo( subcommand, cargo_args: str = "", @@ -21,11 +26,15 @@ def cargo( *, env: dict = None, cwd: str = None, + nightly: bool = False, ): """Executes the specified cargo subcommand""" + toolchain = f"+{nightly_toolchain()}" if nightly else "" env = env or {} env_string = " ".join(f'{key}="{str(value)}"' for key, value in env.items()) - cmd = f"{env_string} cargo {subcommand} {cargo_args} -- {subcommand_args}" + cmd = ( + f"{env_string} cargo {toolchain} {subcommand} {cargo_args} -- {subcommand_args}" + ) return utils.check_output(cmd, cwd=cwd) From a678ecc7c62e25dc96824365681f801fc8400da3 Mon Sep 17 00:00:00 2001 From: Jonathan Woollett-Light Date: Thu, 12 Oct 2023 10:00:09 +0100 Subject: [PATCH 67/78] ci: Test for unused cargo dependencies From: Jonathan Woollett-Light Adds test for unused cargo dependencies. Signed-off-by: Jonathan Woollett-Light Co-authored-by: Patrick Roy Signed-off-by: Patrick Roy --- tests/integration_tests/build/test_dependencies.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/integration_tests/build/test_dependencies.py diff --git a/tests/integration_tests/build/test_dependencies.py b/tests/integration_tests/build/test_dependencies.py new file mode 100644 index 00000000000..6ee3a675702 --- /dev/null +++ b/tests/integration_tests/build/test_dependencies.py @@ -0,0 +1,12 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Enforces controls over dependencies.""" + +from host_tools.cargo_build import cargo + + +def test_unused_dependencies(): + """ + Test that there are no unused dependencies. + """ + cargo("udeps", "--all", nightly=True) From 0bee970f8ee344604d5d110a91712d1f1f6559a2 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 16:50:43 +0000 Subject: [PATCH 68/78] chore: remove unused dependencies from Cargo.tomls The new test caught these. yay! Signed-off-by: Patrick Roy --- Cargo.lock | 27 +-------------------------- src/jailer/Cargo.toml | 1 - src/utils/Cargo.toml | 7 ------- src/vmm/Cargo.toml | 1 - 4 files changed, 1 insertion(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28561608a6a..8be5eab9cf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,12 +284,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "ciborium" version = "0.2.2" @@ -803,7 +797,6 @@ version = "1.11.0-dev" dependencies = [ "libc", "log-instrument", - "nix 0.29.0", "regex", "thiserror 2.0.6", "utils", @@ -965,18 +958,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nom" version = "7.1.3" @@ -1467,7 +1448,7 @@ dependencies = [ "bitflags 2.6.0", "cfg-if", "libc", - "nix 0.27.1", + "nix", "thiserror 1.0.69", "userfaultfd-sys", ] @@ -1493,15 +1474,10 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" name = "utils" version = "0.1.0" dependencies = [ - "derive_more", "displaydoc", "libc", "log-instrument", - "serde", - "serde_json", "thiserror 2.0.6", - "vm-memory", - "vmm-sys-util", ] [[package]] @@ -1600,7 +1576,6 @@ dependencies = [ "itertools 0.13.0", "kvm-bindings", "kvm-ioctls", - "lazy_static", "libc", "linux-loader", "log", diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index f486944ac3b..c84b09450b0 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -14,7 +14,6 @@ bench = false [dependencies] libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -nix = { version = "0.29.0", default-features = false, features = ["dir"] } regex = { version = "1.11.1", default-features = false, features = ["std"] } thiserror = "2.0.6" vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index 923155c265e..dd5652718da 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -9,17 +9,10 @@ license = "Apache-2.0" bench = false [dependencies] -derive_more = { version = "1.0.0", default-features = false, features = ["from"] } displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.215", features = ["derive"] } thiserror = "2.0.6" -vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -vmm-sys-util = "0.12.1" - -[dev-dependencies] -serde_json = "1.0.133" [features] tracing = ["log-instrument"] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index ec3137be748..0ab810b6573 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -24,7 +24,6 @@ gdbstub = { version = "0.7.3", optional = true } gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.19.1" -lazy_static = "1.5.0" libc = "0.2.168" linux-loader = "0.13.0" log = { version = "0.4.22", features = ["std", "serde"] } From 7121895761908ad8fb54d51260f8dc57ab564bdb Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 22 Nov 2024 07:57:24 +0000 Subject: [PATCH 69/78] Add a test that fails if there are obviously unneeded seccomp rules Since Firecracker uses the musl target, it is statically compiled against all of its dependencies. This means that all syscalls that Firecracker can possibly do, are represented by `syscall`/`svc #0x0` instructions inside its binary. By doing some primitive static analysis, it is possible to determine, for each of these instructions, what the actual syscall number is (the idea being: it will probably be a constant loaded into a specific register, determined by Linux's syscall convention, very near the instruction itself). On a best-effort basis, we can also try to determine the values of all registers that might holds syscall arguments (for things like ioctls, this works very well, because the ioctl number is almost always a constant loaded very closely to the syscall instruction). The static_analysis.py file implements the logic for this analysis. We essentially start at each syscall instruction, and then work through the preceding instructions in reverse order, trying to symbolically execute the program in reverse until we figure out the value of the register that holds the syscall number. Thankfully, because of the above mentioned locally, this means we only need to really understand a handful of instructions (based on the assumption that we can ignore instructions that do not explicitly refer to registers that we care about). For example, on x86_64, the syscall number is stored in the eax register, so if we encounter the following instruction sequence xor %ebx,%ebx mov %ebx,%eax syscall we first symbolically execute the "mov", and determine that to figure out the syscall number, we actually need to determine the value of the ebx register. So we go back one more instruction, and find out that %ebx is explicitly set to 0. Thus, forward propagating this 0 to the syscall instruction again, we find that we're doing a `read` syscall. Things get a bit more complicated on ARM, where we don't have to only care about register-to-register transfers, but also things like `add` instructions. For these, we must also keep a "log" of manipulations to apply during forward propagation. For example, on ARM the syscall number is passed in the w8 register, so in the following sequence mov w19, #0x6 add w8, w19, #0x1 svc #0x0 we determine that to compute the syscall number, we must first determine the value of the w19 register, but also we must remember that when we forward propagate the value 0x6 from the w19 register, we must add 1 to it when propagating into the w8 register. Sometimes, we additionally have to deal with wrapper functions around syscalls (e.g. `libc::syscall`). For these, we need to translate the list of syscall number and syscall arguments that the wrapper received according to to the architectures C calling convention (cdecl on x86_64, w0-w7 for arguments on ARM) into what the wrapper will eventually pass to the syscall instruction. On x86_64 this comes with the complication that cdecl only allows passing 6 arguments in registers, but syscall nr + all arguments are up to 7 values. Thus, when a syscall is invoked via libc::syscall, we can only determine up to 5 syscall arguments (the final one would be on the stack, and stack analysis would significantly complicate this script). Lastly, we sometimes also have wrappers for specific syscalls (e.g. ioctl). Here, we do something very similar to the above, however since now the syscall number is "implicit" (e.g. not an argument to the wrapper function, but rather hard-coded into the wrapper), we no not actually run into problems with argument counts on x86_64. We implement this logic because it allows us to determine more arguments (for example, if we did not explicitly look at callsites of the ioctl wrapper, we would not be able to determine which ioctl numbers are actually invoked, greatly reducing the usefulness, as our seccomp filters are large ioctls). After determining all the syscalls, we then compare it to our seccomp filters. We look at all our allowed rules, and compute the set of rules that does not match _any_ of the actual syscalls invoked by the binary. If any such are found, we fail inside a new integration test. There are fairly big limitations to this approach. Because we're doing a global analysis of the firecracker binary, we cannot differentiate between syscalls on different threads, and also not between syscalls done before and after actual application of seccomp filters. For this, we would need some sort of control flow graph analysis, which is made significantly harder due to the presence of dynamic dispatch. Nevertheless, this simple approach already showed 4 redundant syscall rules (and playing around with applying the script to reduced compilation units showed a lot more unneeded rules for the vcpu thread). For all of this to work, we need to compile Firecracker as a non-position independent executable (to get the compiler to general direct calls with absolute addresses, instead of instruction pointer relative ones). Since all dependencies also need to be compiled this way, we have to use cargo's unstable `-Zbuild-std` feature, which thus means we need a nightly toolchain. Signed-off-by: Patrick Roy --- tests/framework/static_analysis.py | 617 ++++++++++++++++++ .../build/test_seccomp_no_redundant_rules.py | 37 ++ 2 files changed, 654 insertions(+) create mode 100644 tests/framework/static_analysis.py create mode 100644 tests/integration_tests/build/test_seccomp_no_redundant_rules.py diff --git a/tests/framework/static_analysis.py b/tests/framework/static_analysis.py new file mode 100644 index 00000000000..fd249f59b85 --- /dev/null +++ b/tests/framework/static_analysis.py @@ -0,0 +1,617 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Module to perform a static analysis of a binary to determine all +actually invoked syscalls. Compares these against seccomp filters, and lists +redundant rules (e.g. those never triggered because the syscall they allow is not +actually used in the binary).""" + +import functools +import json +import logging +import platform +import re +import subprocess +from abc import ABC, abstractmethod +from collections import defaultdict +from dataclasses import dataclass +from pathlib import Path +from typing import Callable, ClassVar, Generic, Tuple, TypeVar, get_args + +import seccomp + +logger = logging.getLogger(__name__) + +# pylint: disable=c-extension-no-member,too-many-return-statements,too-few-public-methods + + +@dataclass +class Instruction(ABC): + """ABC representing a single assembly instruction""" + + mnemonic: str + args: list[str] + + comment_prefix: ClassVar[str] + + @property + @abstractmethod + def is_call(self): + """Checks whether the given instruction is a subroutine call""" + + @property + @abstractmethod + def is_syscall(self): + """Checks whether the given instruction is a syscall instruction""" + + @classmethod + def from_str(cls, insn_str): + """Parses the given string as a single assembly instruction, in the syntax that + objdump uses by default on this architecture""" + # remove comments + insn_str = re.sub(rf"\s+{cls.comment_prefix}.*", "", insn_str) + parts = insn_str.split(maxsplit=1) + args = [] + if len(parts) > 1: + # Strip each argument, in case objdump decides to put , + # spaces after commas (happens on ARM, doesn't happen on x86) + args = [x.strip() for x in parts[1].split(",")] + return cls(parts[0], args) + + @abstractmethod + def backpropagate_register( + self, reg: str + ) -> str | int | Tuple[str, Callable[[int], int]]: + """ + If this instruction loads an immediate into the given register, returns + that immediate as an integer. If the instruction is a register to register transfer, + returns the source register for this transfer. If this instruction doesn't change + the given register, returns the given register. Returns None if we don't know + how to backpropagate through this instruction. + + :param reg: the register to backpropagate through this instruction + :return: An integer if the register is loaded with an immediate by this instruction, or a register + which needs to be backpropagated further (together with an optional forward-propagation + function). + """ + + def __str__(self): + return f"{self.mnemonic} {','.join(self.args)}" + + +class InstructionX86_64(Instruction): # pylint: disable=invalid-name + """A x86_64 instruction""" + + comment_prefix = "#" + + @property + def is_call(self): + return self.mnemonic in ["call", "jmp"] + + @property + def is_syscall(self): + return self.mnemonic == "syscall" + + def backpropagate_register( + self, reg: str + ) -> str | int | Tuple[str, Callable[[int], int]]: + # Simplifying assumption: an instruction will not modify a register + # that it doesn't reference (generally wrong, but fine for our purposes) + affected_registers = [ + match for (match, _) in re.findall(r"(%[a-z0-9]{2,4})(\W|)", str(self)) + ] + if reg not in affected_registers: + return reg + + match self.mnemonic: + case "mov": + if len(self.args) != 2: + raise UnsupportedInstructionError(self, reg) + + src, dst = self.args + + if dst == reg: + # an immediate load + if src.startswith("$"): + return int(src[3:], 16) + # We moved something into our target register. If it's a new register, we understand + # what's going on. Anything else, and tough luck + if re.match(r"^%\w{2,4}$", src): + return src + raise UnsupportedInstructionError(self, reg) + return reg + case "xor": + src, dst = self.args + + if src == dst: + # we know that reg is part of the arguments, and we know that the arguments are identical + # Thus we have xor reg,reg, which is effectively zeroing reg + return 0 + case "push": + # a push doesn't do anything + return reg + + raise UnsupportedInstructionError(self, reg) + + +class InstructionAarch64(Instruction): + """An aarch64 assembly instruction""" + + comment_prefix = "//" + + @property + def is_call(self): + return self.mnemonic in ["b", "bl"] + + @property + def is_syscall(self): + return self.mnemonic == "svc" and self.args == ["#0x0"] + + def backpropagate_register( + self, reg: str + ) -> str | int | Tuple[str, Callable[[int], int]]: + affected_registers = [ + match + for (_, match, _) in re.findall(r"(\s|,)([wx]\d{1,2})(\W|)", str(self)) + ] + if reg not in affected_registers: + return reg + + match self.mnemonic: + case "mov": + if len(self.args) != 2: + raise UnsupportedInstructionError(self, reg) + + dst, src = self.args + + if dst == reg: + # an immediate load + if src.startswith("#"): + return int(src[3:], 16) + + if src in ["xzr", "wzr"]: + # See https://developer.arm.com/documentation/102374/0102/Registers-in-AArch64---other-registers + return 0 + + # We moved something into our target register. If it's a new register, we understand + # what's going on. Anything else, and tough luck + if re.match(r"^[xw]\d{1,2}$", src): + return src + + raise UnsupportedInstructionError(self, reg) + return reg + case "movk": + # https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/MOVK + assert len(self.args) in [2, 3], str(self) + + immediate = int(self.args[1][3:], 16) + shift = 0 + if len(self.args) == 3: + # shift has form "lsl #", so strip first 5 characters + shift = int(self.args[2][5:]) + + mask = 0b1111_1111_1111_1111 << shift + + return reg, lambda x: (x & ~mask) | (immediate << shift) + case "add" | "sub": + if len(self.args) != 3: + raise UnsupportedInstructionError(self, reg) + + dst, src, imm = self.args + + if dst != reg: + return reg + + try: + # We can only handle additions of constants, because + # the backpropagation algorithm cannot follow multiple registers. + imm = int(imm[3:], 16) + except ValueError as exc: + raise UnsupportedInstructionError(self, reg) from exc + + if self.mnemonic == "add": + return src, lambda x: x + imm + # must have self.mnemonic == "sub" here by the case label above. + return src, lambda x: x - imm + + raise UnsupportedInstructionError(self, reg) + + +TInstruction = TypeVar( # pylint: disable=invalid-name + "TInstruction", bound=Instruction +) + + +class Architecture(Generic[TInstruction]): + """ABC representing an instruction set architecture, specifically containing information + pertaining to syscall and subroutine call conventions""" + + # The symbolic name of the register used to pass the syscall number to the architectures + # syscall instruction + syscall_nr_register: ClassVar[str] + + # The list of registers (in order) used to pass arguments to the architectures syscall instruction + syscall_argument_registers: ClassVar[list[str]] + + # The list of registers (in order) used to pass arguments to normal function calls + fn_call_argument_registers: ClassVar[list[str]] + + # Convert to the correct variant of seccomp's Arch enum + seccomp_arch: ClassVar[seccomp.Arch] + + t_instruction: type + + def __init_subclass__(cls) -> None: + # Determine the generic parameter of a subclass, and store it in t_instruction. pylint doesnt understand it + # pylint: disable=no-member + cls.t_instruction = get_args(cls.__orig_bases__[0])[0] + + @staticmethod + @abstractmethod + def generalize_reg(reg: str) -> list[str]: + """For a given register, return a list of registers that partially alias it. + + E.g. on x86, when given %rdi as input, return [%rdi, %edi, %di]""" + + @classmethod + def determine_register_value(cls, instructions: list[TInstruction], register: str): + """Determines the value of the given register at the end of the given instruction sequence + via backpropagation""" + looking_for = cls.generalize_reg(register) + transforms = [] + + for insn in reversed(instructions): + for reg in looking_for: + next_reg = insn.backpropagate_register(reg) + + if isinstance(next_reg, tuple): + next_reg, transform = next_reg + + transforms.insert(0, transform) + + if isinstance(next_reg, int): + # Apply all transforms in reverse order of which we discovered them: We now forward propagate + # the actual value! + return functools.reduce( + lambda acc, fn: fn(acc), transforms, next_reg + ) + + if next_reg != reg: + looking_for = cls.generalize_reg(next_reg) + break + + raise BackpropagationReachedStartOfFn(looking_for) + + +class ArchitectureX86_64( # pylint: disable=invalid-name + Architecture[InstructionX86_64] +): + """The x86_64 ISA""" + + syscall_nr_register = "%eax" + syscall_argument_registers = ["%rdi", "%rsi", "%rdx", "%r10", "%r8", "%r9"] + fn_call_argument_registers = ["%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"] + seccomp_arch = seccomp.Arch.X86_64 + + @staticmethod + def generalize_reg(reg: str) -> list[str]: + suffixes = ["ax", "bx", "cx", "dx", "si", "di", "bp", "sp"] + prefixes = ["%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"] + + for suffix in suffixes: + if reg.endswith(suffix): + return [f"%r{suffix}", f"%e{suffix}", f"%{suffix}"] + + for prefix in prefixes: + if reg.startswith(prefix): + return [prefix, f"{prefix}d", f"{prefix}w"] + + return [reg] + + +class ArchitectureAarch64(Architecture[InstructionAarch64]): + """The aarch64 ISA""" + + ALL_REGS = [f"x{i}" for i in range(0, 32)] + + syscall_nr_register = "x8" + syscall_argument_registers = ALL_REGS[:8] + fn_call_argument_registers = ALL_REGS[:8] + seccomp_arch = seccomp.Arch.AARCH64 + + @staticmethod + def generalize_reg(reg: str) -> list[str]: + mtch = re.match(r"^[xw](\d{1,2})$", reg) + + if mtch: + nr = mtch.group(1) + + return [f"x{nr}", f"w{nr}"] + + return [reg] + + +SYSCALL_WRAPPERS = ["syscall", "__syscall_cp", "__syscall_cp_c"] +SPECIFIC_SYSCALL_WRAPPERS = { + "ioctl": {"syscall": "ioctl", "nargs": 3}, + "__mmap": {"syscall": "mmap", "nargs": 6}, + "socket": {"syscall": "socket", "nargs": 3}, + "__madvise": {"syscall": "madvise", "nargs": 3}, + # special snowflake ioctl: https://github.com/kraj/musl/blob/ffb23aef7b5339b8c3234f4c6a93c488dc873919/src/termios/tcsetattr.c#L5 + "tcsetattr": { + "syscall": "ioctl", + "nargs": 3, + "arg_transform": {1: lambda x: x + 0x5402}, + }, +} + + +class Function: + """Represents a single function in the binary (e.g. as determined from DWARF debug information)""" + + def __init__(self, name: str, arch: Architecture): + self.name = name + self.instructions = [] + self.arch = arch + + def resolve_registers_before_insn(self, i: int, registers: list[str]): + """Tries to determine the values of the given registers when the i-th instruction + executes.""" + resolved_registers = {} + + for reg in registers: + try: + resolved_registers[reg] = self.arch.determine_register_value( + self.instructions[:i], reg + ) + except ( + UnsupportedInstructionError, + BackpropagationReachedStartOfFn, + ) as exc: + resolved_registers[reg] = exc + + return resolved_registers + + +class UnsupportedInstructionError(Exception): + """Exception indicating that an unsupported instruction was encountered during backpropagation, and this + unsupported instruction refers to the register being backpropagated.""" + + def __init__(self, insn: Instruction, reg: str): + super().__init__( + f"Encountered unsupported instruction during backpropagation which affects a register of interest ({reg}): {insn}" + ) + + self.instruction = insn + + +class BackpropagationReachedStartOfFn(Exception): + """Exception indicating that the beginning of a function was reached during backpropagation, without any immediate + value being loaded into the register whose value we were trying to determine""" + + def __init__(self, current_register): + super().__init__( + f"Backpropagation reached beginning of function definition while backpropagating {current_register}. Maybe it is a parameter itself?" + ) + + +def parse_objdump_output(output: str, arch: Architecture) -> list[Function]: + """Parse the stdout from obj dump into a list of the contained functions""" + lines = output.splitlines() + + # Skip the first line of the output, it's just the file format + lines = lines[2:] + + functions = [] + current_function = None + + for line in lines: + line = line.strip() + + # Skip empty lines and those just announcing the start of a new section + if not line or line.startswith("Disassembly of section"): + # all functions are separated by empty lines. This is a sanity check to ensure the regex below + # catches all functions! + current_function = None + continue + + # Start of a new function? + mtch = re.match(r"^<(.+)>:$", line) + + if mtch: + # group 0 is always the full match (e.g. in our case the entire string because we have a regex with ^ and $) + # to get the groups defined inside the regex, start at 1. + current_function = Function(mtch.group(1), arch) + functions.append(current_function) + + continue + + # otherwise, must be instruction + if not current_function: + logger.error( + "Unexpectedly found data outside of function. Skipping line %s", line + ) + continue + + current_function.instructions.append(arch.t_instruction.from_str(line)) + + return functions + + +def find_syscalls_in_binary(binary_path: Path): # pylint: disable=too-many-branches + """Statically analyzes the given binary to find all syscalls. + + Uses objdump's '-d' option, parses the output, and then at the call site of each syscall instruction + (and also of simple wrappers around it that weren't inlined during compilation), tries to determine the values + of registers holding arguments to the syscall instruction.""" + if platform.processor() == "x86_64": + arch = ArchitectureX86_64() + else: + arch = ArchitectureAarch64() + + disassembly = subprocess.check_output( + f"objdump --demangle=rust -d {binary_path} --no-show-raw-insn --no-addresses".split() + ).decode("utf-8") + + functions = parse_objdump_output(disassembly, arch) + + found_syscalls = {} + + for fn in functions: + # We don't want to find syscall instruction inside functions that we treat as synthetic syscall instructions + # themselves, because we will not be able to figure out any argument values here (since they are instead + # determined by the arguments to the function itself). Not excluding these would mean the script recognizes + # them as very broad syscall invocations (e.g. only the syscall number is known, but nothing else, meaning + # all seccomp rules that refer to this syscall are more specific and thus cannot be ruled out). + if fn.name in SYSCALL_WRAPPERS or fn.name in SPECIFIC_SYSCALL_WRAPPERS: + continue + + for i, insn in enumerate(fn.instructions): + if insn.is_syscall: + resolved_registers = fn.resolve_registers_before_insn( + i, + [arch.syscall_nr_register] + arch.syscall_argument_registers, + ) + + syscall_nr = resolved_registers.pop(arch.syscall_nr_register) + syscall_args = [ + resolved_registers[reg] for reg in arch.syscall_argument_registers + ] + elif insn.is_call: + # in objdump output, these look like 'call ', so strip the angle brackets + called = insn.args[0][1:-1] + + if called in SYSCALL_WRAPPERS: + resolved_registers = fn.resolve_registers_before_insn( + i, arch.fn_call_argument_registers + ) + + # On x86_64, we are not able to recover the 6th argument passed, since it is passed on the stack + # This is because for the syscall wrapper, the syscall number itself is passed in one of the 6 + # registers available for function arguments in the cdecl convention (instead of being passed in + # eax, which is not usually used for function arguments). + syscall_nr = resolved_registers.pop( + arch.fn_call_argument_registers[0] + ) + syscall_args = [ + resolved_registers[reg] + for reg in arch.fn_call_argument_registers[1:] + ] + elif called in SPECIFIC_SYSCALL_WRAPPERS: + resolved_registers = fn.resolve_registers_before_insn( + i, arch.fn_call_argument_registers + ) + + syscall_nr = seccomp.resolve_syscall( + arch.seccomp_arch, SPECIFIC_SYSCALL_WRAPPERS[called]["syscall"] + ) + syscall_nargs = SPECIFIC_SYSCALL_WRAPPERS[called]["nargs"] + syscall_args = [ + resolved_registers[reg] + for reg in arch.fn_call_argument_registers[:syscall_nargs] + ] + + if all(isinstance(arg, Exception) for arg in syscall_args): + logger.warning( + "Could not resolve any argument for syscall wrapper %s in function %s", + called, + fn.name, + ) + + # If the wrapper performs some transformation of an argument, apply it. + # It'd be cool to determine these automatically via back propagation or something, + # but that's a fairly complex task, and we only have a single syscall wrapper that needs this + for arg, modifier in ( + SPECIFIC_SYSCALL_WRAPPERS[called] + .get("arg_transform", {}) + .items() + ): + syscall_args[arg] = modifier(syscall_args[arg]) + else: + continue + else: + continue + + # This gets triggered in the __lockfile function on x86_64 (syscall number is loader before a branching instruction, + # but if the branch is not taken, linear execution will eventually hit a ret. So during backpropagation we + # would need to skip the section of assembly between "jmp" and "ret", but our script doesn't do anything + # sophisticated like that and thus instead tries to analyse this branch where the syscall number register + # gets clobbered, and it eventually hits a "pop" which it doesnt understand). The syscall in question is + # "futex", and we call that one a million times elsewhere anyway. + # + # See: https://github.com/kraj/musl/blob/ffb23aef7b5339b8c3234f4c6a93c488dc873919/src/stdio/__lockfile.c#L4 + if isinstance(syscall_nr, Exception): + logger.warning( + "Failed to resolve syscall number for instruction %s in function %s: %s", + insn, + fn.name, + syscall_nr, + ) + continue + + syscall_name = seccomp.resolve_syscall( + arch.seccomp_arch, syscall_nr + ).decode("utf-8") + if syscall_name not in found_syscalls: + found_syscalls[syscall_name] = [] + + found_syscalls[syscall_name].append( + [None if isinstance(arg, Exception) else arg for arg in syscall_args] + ) + + return found_syscalls + + +def load_seccomp_rules(seccomp_path: Path): + """Loads seccomp rules from the given file, and presents them as a dictionary + mapping syscalls to a list of individual filters. Each individual filter + describes some restriction of the arguments that are allowed to be passed + to the syscall.""" + filters = json.loads(seccomp_path.read_text("utf-8")) + + all_filters = ( + filters["vcpu"]["filter"] + filters["vmm"]["filter"] + filters["api"]["filter"] + ) + allowlist = defaultdict(list) + + for seccomp_filter in all_filters: + syscall_name = seccomp_filter["syscall"] + + allowlist[syscall_name].append( + {arg["index"]: arg["val"] for arg in seccomp_filter.get("args", [])} + ) + + return allowlist + + +def determine_unneeded_seccomp_rules(seccomp_rules, found_syscalls): + """Based on the given list of syscall determined through static analysis, compute which of the + given seccomp rules are redundant. By 'redundant' we here mean that no syscall that would match + it is actually present in the given list of syscalls.""" + + # TODO: We could also determine "too broad" rules here: If all actual invocations of a syscall specific a parameter, + # but the rule does not restrict that parameter, we could recommend to strengthen the rule to specify the parameter! + + redundant_rules = [] + + for syscall, rules in seccomp_rules.items(): + for allowed_arguments in rules: + # A rule is not needed if for all actual invocation of the syscall the rule governs, + # the rule does not match. + # Here, we determine "does not match" as "the rule specifies some value for an argument of the syscall to be + # allowed, but the invocation of the syscall never passes this specified value of the argument". + # If there are no invocations of a syscall altogether, then the universal quantification will be vacuously + # true, and any rules involving that syscall are reported as non-needed. + rule_not_needed = all( + any( + actual_invocations[arg_index] is not None + and actual_invocations[arg_index] != allowed_arg + for arg_index, allowed_arg in allowed_arguments.items() + ) + for actual_invocations in found_syscalls.get(syscall, []) + ) + + if rule_not_needed: + redundant_rules.append((syscall, allowed_arguments)) + + return redundant_rules diff --git a/tests/integration_tests/build/test_seccomp_no_redundant_rules.py b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py new file mode 100644 index 00000000000..a61b86b5547 --- /dev/null +++ b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py @@ -0,0 +1,37 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""A test that fails if it can definitely prove a seccomp rule redundant +(although it passing does not guarantee the converse, that all rules are definitely needed).""" +import platform +from pathlib import Path + +from framework import utils +from framework.static_analysis import ( + determine_unneeded_seccomp_rules, + find_syscalls_in_binary, + load_seccomp_rules, +) + + +def test_redundant_seccomp_rules(): + """Test that fails if static analysis determines redundant seccomp rules""" + arch = platform.processor() + + nightly_toolchain = utils.check_output( + "rustup toolchain list | grep nightly" + ).stdout.strip() + target = f"{arch}-unknown-linux-musl" + + utils.check_output( + f'RUSTFLAGS="-C relocation-model=static -C link-args=-no-pie" cargo +{nightly_toolchain} -Zbuild-std=panic_abort,std build --release --target {target} -p firecracker' + ) + + found_syscalls = find_syscalls_in_binary( + Path(f"../build/cargo_target/{target}/release/firecracker") + ) + + seccomp_rules = load_seccomp_rules(Path(f"../resources/seccomp/{target}.json")) + + redundant_rules = determine_unneeded_seccomp_rules(seccomp_rules, found_syscalls) + + assert not redundant_rules, f"Found redundant seccomp rules! {redundant_rules}" From cb9521f8c1c5763dd4314055dd44a68cdfd87fd8 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 3 Dec 2024 15:28:31 +0000 Subject: [PATCH 70/78] disable static analysis seccomp test on aarch64 The nightly toolchain in our devctr is too old to successfully compile non-PIE, statically linked aarch64 executable. I have manually verified newer nightlies to work (2024-11-16 and newer), however our nightly toolchain is dictated by kani, so we need to wait for kani to release a new version that updates past this toolchain. Therefore, temporarily disable the test on aarch64. Signed-off-by: Patrick Roy --- .../build/test_seccomp_no_redundant_rules.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/integration_tests/build/test_seccomp_no_redundant_rules.py b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py index a61b86b5547..33c8764e512 100644 --- a/tests/integration_tests/build/test_seccomp_no_redundant_rules.py +++ b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py @@ -5,6 +5,8 @@ import platform from pathlib import Path +import pytest + from framework import utils from framework.static_analysis import ( determine_unneeded_seccomp_rules, @@ -13,6 +15,10 @@ ) +@pytest.mark.skipif( + platform.machine() != "x86_64", + reason="aarch64 nightly toolchain does not support flags needed to compile analyzable binary yet", +) def test_redundant_seccomp_rules(): """Test that fails if static analysis determines redundant seccomp rules""" arch = platform.processor() From 35502a5fd2706c379caa27496ec234adc179f7a1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 22 Nov 2024 07:40:25 +0000 Subject: [PATCH 71/78] Remove some redundant seccomp entries from allow lists These have been determined by static analysis of a Firecracker binary (see also follow up commits): The removed seccomp rules here trigger syscalls that are either not present at all in the entire Firecracker binary, or are not reachable from the entry point of a specific Firecracker thread (this analysis has only been done for the vcpu thread for now, due to being fairly tricky). Some explanations for why some of these entries are no longer needed can be found below - The `uname` syscall was used back when we supported 4.14, to query the host kernel version and disable specific Firecracker features that were not supported pre-5.10 (io_uring and hugepages for memfd). With 4.14 support dropped, there are no such checks anymore. - Various KVM_SET_* ioctls do not need to be allowed on the vcpu thread, because they are all called _before_ the vcpu seccomp filters are installed (as they are only used during snapshot restore / when preparing KVM state for boot). - on aarch64, we can additionally remove KVM_{SET,GET}VCPU_EVENTS, as we never call this ioctl on arm (only on x86) Signed-off-by: Patrick Roy --- .../seccomp/aarch64-unknown-linux-musl.json | 52 ------ .../seccomp/x86_64-unknown-linux-musl.json | 154 +----------------- 2 files changed, 3 insertions(+), 203 deletions(-) diff --git a/resources/seccomp/aarch64-unknown-linux-musl.json b/resources/seccomp/aarch64-unknown-linux-musl.json index 48d94a0f050..10abb9dc9ed 100644 --- a/resources/seccomp/aarch64-unknown-linux-musl.json +++ b/resources/seccomp/aarch64-unknown-linux-musl.json @@ -42,10 +42,6 @@ { "syscall": "close" }, - { - "syscall": "uname", - "comment": "Used for getting the kernel version, for validating io_uring support" - }, { "syscall": "eventfd2", "comment": "Used for creating io_uring completion event, on drive patch" @@ -970,42 +966,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074048665, - "comment": "KVM_SET_MP_STATE" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 2151722655, - "comment": "KVM_GET_VCPU_EVENTS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1077980832, - "comment": "KVM_SET_VCPU_EVENTS" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1018,18 +978,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074835116, - "comment": "KVM_SET_ONE_REG" - } - ] - }, { "syscall": "ioctl", "args": [ diff --git a/resources/seccomp/x86_64-unknown-linux-musl.json b/resources/seccomp/x86_64-unknown-linux-musl.json index 861b69c6b44..5a70f4c01d1 100644 --- a/resources/seccomp/x86_64-unknown-linux-musl.json +++ b/resources/seccomp/x86_64-unknown-linux-musl.json @@ -42,10 +42,6 @@ { "syscall": "close" }, - { - "syscall": "uname", - "comment": "Used for getting the kernel version, for validating io_uring support" - }, { "syscall": "eventfd2", "comment": "Used for creating io_uring completion event, on drive patch" @@ -111,8 +107,8 @@ "comment": "sigaltstack is used by Rust stdlib to remove alternative signal stack during thread teardown." }, { - "syscall": "getrandom", - "comment": "getrandom is used by aws-lc library which we consume in virtio-rng" + "syscall": "getrandom", + "comment": "getrandom is used by aws-lc library which we consume in virtio-rng" }, { "syscall": "accept4", @@ -214,7 +210,7 @@ }, { "syscall": "madvise", - "comment": "Used by the VirtIO balloon device and by musl for some customer workloads. It is also used by aws-lc during random number generation. They setup a memory page that mark with MADV_WIPEONFORK to be able to detect forks. They also call it with -1 to see if madvise is supported in certain platforms." + "comment": "Used by the VirtIO balloon device and by musl for some customer workloads. It is also used by aws-lc during random number generation. They setup a memory page that mark with MADV_WIPEONFORK to be able to detect forks. They also call it with -1 to see if madvise is supported in certain platforms." }, { "syscall": "mmap", @@ -978,18 +974,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074048665, - "comment": "KVM_SET_MP_STATE" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1002,18 +986,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1077980832, - "comment": "KVM_SET_VCPU_EVENTS" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1038,78 +1010,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074310800, - "comment": "KVM_SET_CPUID2" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1140895375, - "comment": "KVM_SET_LAPIC" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074310793, - "comment": "KVM_SET_MSRS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1083223682, - "comment": "KVM_SET_REGS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1094233732, - "comment": "KVM_SET_SREGS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 2154868383, - "comment": "KVM_GET_PIT2" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1158,18 +1058,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1082175138, - "comment": "KVM_SET_DEBUGREGS" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1182,18 +1070,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1342221989, - "comment": "KVM_SET_XSAVE" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1206,30 +1082,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1099476647, - "comment": "KVM_SET_XCRS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 44706, - "comment": "KVM_SET_TSC_KHZ" - } - ] - }, { "syscall": "ioctl", "args": [ From 1709e4fa60a52d543623350f54c0f82f65f7c99a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:35:17 +0000 Subject: [PATCH 72/78] build(deps): Bump the firecracker group with 7 updates Bumps the firecracker group with 7 updates: | Package | From | To | | --- | --- | --- | | [thiserror](https://github.com/dtolnay/thiserror) | `2.0.6` | `2.0.7` | | [serde](https://github.com/serde-rs/serde) | `1.0.215` | `1.0.216` | | [serde_derive](https://github.com/serde-rs/serde) | `1.0.215` | `1.0.216` | | [semver](https://github.com/dtolnay/semver) | `1.0.23` | `1.0.24` | | [proptest](https://github.com/proptest-rs/proptest) | `1.5.0` | `1.6.0` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.3` | `1.2.4` | | [home](https://github.com/rust-lang/cargo) | `0.5.9` | `0.5.11` | Updates `thiserror` from 2.0.6 to 2.0.7 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/2.0.6...2.0.7) Updates `serde` from 1.0.215 to 1.0.216 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.215...v1.0.216) Updates `serde_derive` from 1.0.215 to 1.0.216 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.215...v1.0.216) Updates `semver` from 1.0.23 to 1.0.24 - [Release notes](https://github.com/dtolnay/semver/releases) - [Commits](https://github.com/dtolnay/semver/compare/1.0.23...1.0.24) Updates `proptest` from 1.5.0 to 1.6.0 - [Release notes](https://github.com/proptest-rs/proptest/releases) - [Changelog](https://github.com/proptest-rs/proptest/blob/main/CHANGELOG.md) - [Commits](https://github.com/proptest-rs/proptest/commits) Updates `cc` from 1.2.3 to 1.2.4 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.3...cc-v1.2.4) Updates `home` from 0.5.9 to 0.5.11 - [Changelog](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cargo/commits) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_derive dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: semver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: proptest dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: home dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 61 +++++++++++++----------------- src/acpi-tables/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 4 +- src/firecracker/Cargo.toml | 8 ++-- src/jailer/Cargo.toml | 2 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 4 +- src/snapshot-editor/Cargo.toml | 4 +- src/utils/Cargo.toml | 2 +- src/vmm/Cargo.toml | 8 ++-- 10 files changed, 45 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8be5eab9cf6..d499d3f16f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ name = "acpi_tables" version = "0.1.0" dependencies = [ "displaydoc", - "thiserror 2.0.6", + "thiserror 2.0.7", "vm-memory", "zerocopy 0.8.13", ] @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" dependencies = [ "jobserver", "libc", @@ -419,7 +419,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.6", + "thiserror 2.0.7", "vmm", "vmm-sys-util", ] @@ -613,7 +613,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.6", + "thiserror 2.0.7", "timerfd", "userfaultfd", "utils", @@ -718,11 +718,11 @@ checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -798,7 +798,7 @@ dependencies = [ "libc", "log-instrument", "regex", - "thiserror 2.0.6", + "thiserror 2.0.7", "utils", "vmm-sys-util", ] @@ -863,12 +863,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "libm" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - [[package]] name = "linux-loader" version = "0.13.0" @@ -975,7 +969,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -1050,9 +1043,9 @@ dependencies = [ [[package]] name = "proptest" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ "bitflags 2.6.0", "lazy_static", @@ -1119,7 +1112,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.6", + "thiserror 2.0.7", "utils", "vmm-sys-util", ] @@ -1197,34 +1190,34 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.6", + "thiserror 2.0.7", "utils", "vmm-sys-util", ] [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -1277,7 +1270,7 @@ dependencies = [ "libc", "log-instrument", "semver", - "thiserror 2.0.6", + "thiserror 2.0.7", "utils", "vmm", "vmm-sys-util", @@ -1317,11 +1310,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" dependencies = [ - "thiserror-impl 2.0.6", + "thiserror-impl 2.0.7", ] [[package]] @@ -1337,9 +1330,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" dependencies = [ "proc-macro2", "quote", @@ -1477,7 +1470,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.6", + "thiserror 2.0.7", ] [[package]] @@ -1588,7 +1581,7 @@ dependencies = [ "serde", "serde_json", "slab", - "thiserror 2.0.6", + "thiserror 2.0.7", "timerfd", "userfaultfd", "utils", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 87b2e7ed626..0a7f92dee5f 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" [dependencies] displaydoc = "0.2.5" -thiserror = "2.0.6" +thiserror = "2.0.7" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } zerocopy = { version = "0.8.13", features = ["derive"] } diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 0e665f8f521..5fd314bf48c 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -14,9 +14,9 @@ clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.215", features = ["derive"] } +serde = { version = "1.0.216", features = ["derive"] } serde_json = "1.0.133" -thiserror = "2.0.6" +thiserror = "2.0.7" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index ec20799e798..cbd9ffe5e2d 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -23,10 +23,10 @@ log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.215", features = ["derive"] } +serde = { version = "1.0.216", features = ["derive"] } serde_derive = "1.0.136" serde_json = "1.0.133" -thiserror = "2.0.6" +thiserror = "2.0.7" timerfd = "1.6.0" utils = { path = "../utils" } vmm = { path = "../vmm" } @@ -38,13 +38,13 @@ libc = "0.2.168" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples -serde = { version = "1.0.215", features = ["derive"] } +serde = { version = "1.0.216", features = ["derive"] } userfaultfd = "0.8.1" [build-dependencies] bincode = "1.2.1" seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.215" } +serde = { version = "1.0.216" } serde_json = "1.0.133" [features] diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index c84b09450b0..955fe1af5b2 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -15,7 +15,7 @@ bench = false libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } regex = { version = "1.11.1", default-features = false, features = ["std"] } -thiserror = "2.0.6" +thiserror = "2.0.7" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index 8409430340e..c435d2ae249 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -13,7 +13,7 @@ bench = false displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.6" +thiserror = "2.0.7" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 93be7082920..4c23f0ae595 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -20,9 +20,9 @@ bincode = "1.2.1" displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.215", features = ["derive"] } +serde = { version = "1.0.216", features = ["derive"] } serde_json = "1.0.133" -thiserror = "2.0.6" +thiserror = "2.0.7" utils = { path = "../utils" } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 0e42cd11859..a199a8ab99f 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -16,8 +16,8 @@ displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -semver = "1.0.23" -thiserror = "2.0.6" +semver = "1.0.24" +thiserror = "2.0.7" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index dd5652718da..c4509ec1e57 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -12,7 +12,7 @@ bench = false displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.6" +thiserror = "2.0.7" [features] tracing = ["log-instrument"] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 0ab810b6573..043fc11528c 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -32,11 +32,11 @@ memfd = "0.6.3" micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } -semver = { version = "1.0.23", features = ["serde"] } -serde = { version = "1.0.215", features = ["derive", "rc"] } +semver = { version = "1.0.24", features = ["serde"] } +serde = { version = "1.0.216", features = ["derive", "rc"] } serde_json = "1.0.133" slab = "0.4.7" -thiserror = "2.0.6" +thiserror = "2.0.7" timerfd = "1.5.0" userfaultfd = "0.8.1" utils = { path = "../utils" } @@ -54,7 +54,7 @@ vm-fdt = "0.3.0" criterion = { version = "0.5.0", default-features = false } device_tree = "1.1.0" itertools = "0.13.0" -proptest = { version = "1.5.0", default-features = false, features = ["std"] } +proptest = { version = "1.6.0", default-features = false, features = ["std"] } [features] default = [] From 5c3ff0881f0cdf7ad82326408c9f10cee6b3c1c8 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 16 Dec 2024 13:10:42 +0000 Subject: [PATCH 73/78] test: use fio instead of dd for performance tests In test_drive_rate_limiter, use `fio` for measuring latencies of writing a fixed number of bytes to a block device, instead of `dd` (which the test itself notes is unreliable). Should fix intermitted failures we're been seeing in this test, hopefully. Signed-off-by: Patrick Roy --- .../performance/test_drive_rate_limiter.py | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/tests/integration_tests/performance/test_drive_rate_limiter.py b/tests/integration_tests/performance/test_drive_rate_limiter.py index adeb0c25123..dbb1bfb310c 100644 --- a/tests/integration_tests/performance/test_drive_rate_limiter.py +++ b/tests/integration_tests/performance/test_drive_rate_limiter.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 """Tests for checking the rate limiter on /drives resources.""" - +import json import os import host_tools.drive as drive_tools @@ -12,28 +12,22 @@ def check_iops_limit(ssh_connection, block_size, count, min_time, max_time): """Verify if the rate limiter throttles block iops using dd.""" - obs = block_size + byte_count = block_size * count - dd = "dd if=/dev/zero of=/dev/vdb ibs={} obs={} count={} oflag=direct".format( - block_size, obs, count - ) - print("Running cmd {}".format(dd)) - # Check write iops (writing with oflag=direct is more reliable). - _, _, stderr = ssh_connection.check_output(dd) - # "dd" writes to stderr by design. We drop first lines - lines = stderr.split("\n") - dd_result = lines[2].strip() + fio = f"fio --name=fixed-job --direct=1 --rw=write --blocksize={block_size} --size={byte_count} --filename=/dev/vdb --zero_buffers --output-format=json" + + _, stdout, _ = ssh_connection.check_output(fio) - # Interesting output looks like this: - # 4194304 bytes (4.2 MB, 4.0 MiB) copied, 0.0528524 s, 79.4 MB/s - tokens = dd_result.split() + data = json.loads(stdout) + runtime_ms = data["jobs"][0]["write"]["runtime"] + io_bytes = data["jobs"][0]["write"]["io_bytes"] # Check total read bytes. - assert int(tokens[0]) == byte_count + assert io_bytes == byte_count # Check duration. - assert float(tokens[7]) > min_time - assert float(tokens[7]) < max_time + assert runtime_ms > min_time * 1000 + assert runtime_ms < max_time * 1000 def test_patch_drive_limiter(uvm_plain): From 5b8e44ab2e0f4f2c67002a97470887d7afd1cb79 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 16 Dec 2024 14:15:04 +0000 Subject: [PATCH 74/78] fix(test): do not use absolute path to true when opening ssh connection In #4955 the executable to check the ssh connection liveliness was changed from `true` to `/usr/bin/true`, but that is not its path in all rootfs, causing failures in the `test-populat-containers` suite. Also, since the error is retried but the daemon is not cleaned up, subsequent retries would fail for the assertion. This change fixes both issues by using the binary name `true` and stopping the daemon on error before the next retry. Fixes: 3b2c2d4d6 ("test: use single SSH connection for lifetime of microvm") Signed-off-by: Riccardo Mancini --- tests/host_tools/network.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py index ff6e58be2b9..af0b3766ee0 100644 --- a/tests/host_tools/network.py +++ b/tests/host_tools/network.py @@ -129,14 +129,21 @@ def _init_connection(self): "ControlPersist=yes", *self.options, self.user_host, - "/usr/bin/true", + "true", ] - # don't set a low timeout here, because otherwise we might get into a race condition - # where ssh already forked off the persisted connection daemon, but gets killed here - # before exiting itself. In that case, self._control_path will exist, and the retry - # will hit the assert at the start of this function. - self._exec(establish_cmd, check=True) + try: + # don't set a low timeout here, because otherwise we might get into a race condition + # where ssh already forked off the persisted connection daemon, but gets killed here + # before exiting itself. In that case, self._control_path will exist, and the retry + # will hit the assert at the start of this function. + self._exec(establish_cmd, check=True) + except Exception: + # if the control socket is present, then the daemon is running, and we should stop it + # before retrying again + if self._control_path.exists(): + self.close() + raise def _check_liveness(self) -> int: """Checks whether the ControlPersist connection is still alive""" From 89ca78177ba4ee5faeb225d2ff16641e82da2b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 12 Dec 2024 17:39:05 +0100 Subject: [PATCH 75/78] tests: prevent double publishing of metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seem that pytest_runtest_logreport is triggered for the worker where the test happens and the main process. So do not emit metrics unless we are in the main process. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index ac73b4bd8ab..865fa0b44b2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -105,6 +105,11 @@ def record_props(request, record_property): def pytest_runtest_logreport(report): """Send general test metrics to CloudWatch""" + # only publish metrics from the main process + worker_id = os.environ.get("PYTEST_XDIST_WORKER") + if worker_id is not None: + return + # The pytest's test protocol has three phases for each test item: setup, # call and teardown. At the end of each phase, pytest_runtest_logreport() # is called. @@ -135,6 +140,7 @@ def pytest_runtest_logreport(report): # and global {}, ) + METRICS.set_property("pytest_xdist_worker", worker_id) METRICS.set_property("result", report.outcome) METRICS.set_property("location", report.location) for prop_name, prop_val in report.user_properties: From 56306be408cee9b73bbb48411b3e3fbd9caff7e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 17 Dec 2024 13:17:22 +0100 Subject: [PATCH 76/78] tests: ignore vsock tx_flush_fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 9364472d528d380985ac0077385fc2f70e9c65bd we started to ignore tx_read_fails/tx_write_fails, but should also have included tx_flush_fails. Add it here. Fixes: 9364472d528d380985ac0077385fc2f70e9c65bd Signed-off-by: Pablo Barbáchano --- tests/host_tools/fcmetrics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/host_tools/fcmetrics.py b/tests/host_tools/fcmetrics.py index e33e89089dc..47661d5b27d 100644 --- a/tests/host_tools/fcmetrics.py +++ b/tests/host_tools/fcmetrics.py @@ -472,6 +472,7 @@ def flatten_dict(node, prefix: str): # See also https://github.com/stefano-garzarella/iperf-vsock/issues/4 "fc_metrics.vsock.rx_read_fails", "fc_metrics.vsock.tx_write_fails", + "fc_metrics.vsock.tx_flush_fails", ] failure_metrics = { From c6add4fccf27cd0522a7e49a2c5dc67ab7067980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 17 Dec 2024 14:52:45 +0100 Subject: [PATCH 77/78] ci: allow passing a dict/list as a step parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some cases we may want to pass a complex value to a step. For example: .buildkite/pipeline_pr.py \ --step-param 'retry/automatic=[{"exit_status": "*", "limit": 2}]' Signed-off-by: Pablo Barbáchano --- .buildkite/common.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.buildkite/common.py b/.buildkite/common.py index a8913d5d6ef..342bd671ddc 100644 --- a/.buildkite/common.py +++ b/.buildkite/common.py @@ -6,6 +6,7 @@ """ import argparse +import ast import json import os import random @@ -138,7 +139,7 @@ def __call__(self, parser, namespace, value, option_string=None): res = getattr(namespace, self.dest, {}) key_str, val = value.split("=", maxsplit=1) keys = key_str.split("/") - update = {keys[-1]: val} + update = {keys[-1]: ast.literal_eval(val)} for key in list(reversed(keys))[1:]: update = {key: update} res = overlay_dict(res, update) From 70ac1544d3bb460c47d93132f59a9e35cd5ad3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 17 Dec 2024 16:09:56 +0100 Subject: [PATCH 78/78] ci: report all microcode packages during a test run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit microcode_ctl only covers Intel firmware files. Capture AMD and any other possible ones. Signed-off-by: Pablo Barbáchano --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 7d41229b2e7..a55fda81269 100755 --- a/tools/devtool +++ b/tools/devtool @@ -742,7 +742,7 @@ cmd_test() { # If we got to here, we've got all we need to continue. say "Kernel version: $(uname -r)" say "$(sed '/^processor.*: 0$/,/^processor.*: 1$/!d; /^processor.*: 1$/d' /proc/cpuinfo)" - say "RPM microcode_ctl version: $(rpm -q microcode_ctl)" + say "RPM firmware versions: $(rpm -q microcode_ctl amd-ucode-firmware linux-firmware)" env |grep -P "^(AWS_EMF_|BUILDKITE|CODECOV_)" > env.list if [[ $performance_tweaks -eq 1 ]]; then