diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock new file mode 100644 index 0000000..5c9028a --- /dev/null +++ b/.claude/scheduled_tasks.lock @@ -0,0 +1 @@ +{"sessionId":"b333c4dc-d866-4418-9a6e-f4cc30f904c1","pid":840357,"acquiredAt":1776367523862} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c8a6286..1e2ee99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ be split into per-release sections once tagging begins. policy-enforcing `.gitignore`, pinned Python 3.11 (`.python-version`), and `pyproject.toml` with full project metadata, classifiers, and URL pointers. The runtime TensorFlow dependency is pinned to - `tensorflow>=2.16,<3.0` — see *Changed* below for the rationale. + `tensorflow>=2.16,<2.19` — see *Changed* below for the rationale. `psutil>=5.9` is a runtime dependency used by the estimator's always-on `PerformanceMetrics` collection to sample peak RSS. - `[project.optional-dependencies].analysis` extra for fastdtw, scipy, @@ -381,17 +381,24 @@ be split into per-release sections once tagging begins. `datetime.utcnow()`, addresses the "no-videos"-vs-exception-path inconsistency (both now quarantine), and persists a structured `error` string on every failure for grep-friendly diagnostics. -- **TensorFlow pin tightened to `tensorflow>=2.16,<3.0`.** The 2.16 +- **TensorFlow pin set to `tensorflow>=2.16,<2.19`.** The 2.16 floor is the first release with native `darwin/arm64` wheels under the `tensorflow` package name on PyPI, so a single dependency line works across Linux x86_64, Linux arm64, and Apple Silicon macOS without platform markers or a separate `tensorflow-macos` package. - Empirical verification: the pinned MeTRAbs SavedModel - (`metrabs_eff2l_y4_384px_800k_28ds`, serialized with TF 2.10) - loads and runs `detect_poses` end-to-end on TF 2.21 + Keras 3 with - no errors, and exposes only stock TensorFlow ops (zero MeTRAbs - custom kernels). Full test matrix and op inventory in - `RESEARCH.md`. + The `<2.19` ceiling is a `tensorflow-metal` compatibility constraint: + the latest Metal plugin (1.2.0, January 2025) advertises "TF 2.18+" + but in practice fails on 2.19 and 2.20 with symbol-not-found errors + and graph-execution `InvalidArgumentError`s + ([tensorflow/tensorflow#84167](https://github.com/tensorflow/tensorflow/issues/84167)). + Cap is global rather than darwin-only so dependency resolution stays + identical across platforms. The MeTRAbs SavedModel itself + (`metrabs_eff2l_y4_384px_800k_28ds`, serialized with TF 2.10) was + separately verified to load and run `detect_poses` end-to-end on + TF 2.21 + Keras 3 with no errors and zero custom ops, so the cap is + purely an external-package constraint and can lift once Apple ships + a Metal plugin that tracks mainline TensorFlow again. Full probe + data and op inventory in `RESEARCH.md`. - Operating-system classifiers in `pyproject.toml` extended from Linux-only to `POSIX` + `POSIX :: Linux` + `MacOS`, reflecting the Apple Silicon support that the TF 2.16 floor makes real. diff --git a/RESEARCH.md b/RESEARCH.md index d263f91..c040c4c 100644 --- a/RESEARCH.md +++ b/RESEARCH.md @@ -356,7 +356,7 @@ that crosses the Keras-3 cutover at TF 2.16. ### Decision -Pin `tensorflow>=2.16,<3.0`. Reasoning: +Pin `tensorflow>=2.16,<2.19`. Reasoning: 1. **2.16 is the Apple Silicon floor that matters.** TF 2.16 is the first release with native `darwin/arm64` wheels published on PyPI @@ -387,6 +387,26 @@ Pin `tensorflow>=2.16,<3.0`. Reasoning: `docs/getting-started.md`, and users are expected to spot-check `poses3d` output against the CPU path before trusting it for any clinical measurement. +4. **`tensorflow-metal` forces a TF upper bound.** `tensorflow-metal` + 1.2.0 (released January 2025, the latest version as of 2026-04) is + advertised as supporting "TF 2.18+" but in practice fails on + 2.19 and 2.20 with symbol-not-found errors and graph-execution + `InvalidArgumentError`s. See + [tensorflow/tensorflow#84167](https://github.com/tensorflow/tensorflow/issues/84167) + and the Apple Developer forum threads at + [developer.apple.com/forums/thread/772147](https://developer.apple.com/forums/thread/772147) + and [developer.apple.com/forums/thread/803658](https://developer.apple.com/forums/thread/803658). + 2.18.x is the last version confirmed to work cleanly on Apple + Silicon GPU. Even though the Metal path is opt-in, dependency + resolution is shared — if uv resolves `tensorflow` to 2.21 on a + Linux developer's machine and 2.18 on the Mac, lockfile churn + and "works on my box" become permanent. Cap is therefore applied + globally rather than via a darwin/arm64 marker split. Cost on + Linux is zero: nothing in the pipeline depends on TF 2.19+ + features, and the SavedModel ran fine on TF 2.21 in the probe + above, so the cap is purely an external-package constraint. Lift + it once Apple ships a Metal plugin that tracks mainline + TensorFlow again. ### What is **not** yet verified @@ -422,9 +442,11 @@ Pin `tensorflow>=2.16,<3.0`. Reasoning: detector head), how do we want the loader to fail? Currently the `_REQUIRED_MODEL_ATTRS` interface check would still pass; the failure would surface at first `detect_poses` call, which is late. -3. Does it make sense to upper-bound the pin more tightly than `<3.0` +3. ~~Does it make sense to upper-bound the pin more tightly than `<3.0` (e.g. `<2.22` to bound to tested versions), or is the SemVer guard - sufficient given the all-stock-ops result? + sufficient given the all-stock-ops result?~~ **Resolved 2026-04-16.** + Tightened to `<2.19` for `tensorflow-metal` compatibility. See + reasoning point 4 in the Decision section above. ### Next steps diff --git a/benchmarks/README.md b/benchmarks/README.md index 87138d7..c2896a3 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -49,32 +49,42 @@ a tracked extension inside `benchmarks/videos/` because only ## Rsyncing to the research Mac -The directory layout is designed so one `rsync` path covers both -code and videos: +The repo ships a wrapper script, [`scripts/sync_benchmarks.sh`](../scripts/sync_benchmarks.sh), +that pushes the whole `benchmarks/` directory to the research Mac +with a predictable command: ```console -$ rsync -av --delete \ - --exclude='.venv/' \ - --exclude='site/' \ - --exclude='.git/' \ - ~/Repos/research/brown/shu/neuropose/ \ - mac.local:~/Repos/research/brown/shu/neuropose/ +$ scripts/sync_benchmarks.sh # copy files, no deletions +$ scripts/sync_benchmarks.sh --dry-run # preview what would transfer +$ scripts/sync_benchmarks.sh --delete # make remote exactly mirror local +``` + +Defaults are baked in for the Shu Lab research Mac +(`Levi@100.64.15.110:/Users/levi/Repos/neuropose/benchmarks/`). Point +the script at a different destination via environment variables: + +```console +$ REMOTE_HOST=me@other-host REMOTE_PATH=/tmp/benchmarks/ \ + scripts/sync_benchmarks.sh ``` After the sync, the videos in `benchmarks/videos/` on the Mac are -identical to the ones on Linux, so a benchmark run on the Mac can -reference the same filename the Linux report does — makes cross- -machine comparisons trivial. +identical to the ones on the source machine, so a benchmark run on +the Mac can reference the same filename the local report does — +makes cross-machine comparisons trivial. -Tips: +Notes: -- Add `--exclude='benchmarks/videos/*.json'` if you want to keep - per-machine benchmark results isolated. -- `--delete` makes the target exactly mirror the source. Without - it, old files on the target persist — safer but surprising. -- For one-off pushes, `scp benchmarks/videos/clip.mp4 - mac.local:~/Repos/research/brown/shu/neuropose/benchmarks/videos/` - works without touching the rest of the repo. +- **`--delete` is opt-in.** The default is purely additive so the + remote can hold per-machine benchmark result JSONs that the source + machine does not have. Pass `--delete` only when you want the + remote to become an exact mirror. +- **`--partial` is always on.** An interrupted transfer of a + multi-gigabyte video can resume on the next invocation without + starting from zero. +- **One-off pushes** of a single file still work fine with plain + `scp` (or rsync directly) — the wrapper script is for the + "everything in `benchmarks/`" case. ## Bulk intake via `neuropose ingest` diff --git a/docs/getting-started.md b/docs/getting-started.md index e7ed146..65f0d88 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -16,10 +16,14 @@ before. - Internet access on first run (for the ~2 GB MeTRAbs model download) !!! note "Apple Silicon" - NeuroPose pins `tensorflow>=2.16`, which is the first TensorFlow - release with native `darwin/arm64` wheels on PyPI. Mac users get a - working CPU install from the same command Linux users run — no - `tensorflow-macos`, no platform markers, no extra configuration. + NeuroPose pins `tensorflow>=2.16,<2.19`. The 2.16 floor is the first + TensorFlow release with native `darwin/arm64` wheels on PyPI; the + `<2.19` ceiling tracks the highest TF version that Apple's + `tensorflow-metal` plugin works cleanly with (see the *Metal GPU + acceleration* note below and `RESEARCH.md` for the full reasoning). + Mac users get a working CPU install from the same command Linux + users run — no `tensorflow-macos`, no platform markers, no extra + configuration. Metal GPU acceleration is available as an **opt-in extra** for users who need it: diff --git a/pyproject.toml b/pyproject.toml index 8134f23..8ce14c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,8 +45,18 @@ classifiers = [ # split to ``tensorflow-macos`` on Apple Silicon. The MeTRAbs SavedModel was # serialized with TF 2.10 and uses only stock ops (no custom kernels), so # any TF >= 2.10 loads it; 2.16 is chosen for cross-platform install -# uniformity, not for any MeTRAbs-side requirement. End-to-end verification -# against TF 2.21 is logged in RESEARCH.md. +# uniformity, not for any MeTRAbs-side requirement. +# +# The ``<2.19`` ceiling is a tensorflow-metal compatibility constraint, not +# a MeTRAbs one. Apple's ``tensorflow-metal`` 1.2.0 (the latest release, +# Jan 2025) advertises "TF 2.18+" support, but community reports on the +# Apple Developer forums and tensorflow/tensorflow#84167 show it actually +# breaks on 2.19+ with symbol-not-found errors and ``InvalidArgumentError`` +# at graph execution time. 2.18.x is the last version confirmed to work +# cleanly on Apple Silicon GPU. Cap applied globally rather than with a +# darwin/arm64 marker split to keep dependency resolution identical across +# platforms; revisit once Apple ships a Metal plugin that tracks mainline +# TensorFlow again. dependencies = [ "typer>=0.12", "pydantic>=2.6", @@ -61,7 +71,7 @@ dependencies = [ # small C extension; brought in at runtime because metrics are always # collected, not an optional feature. "psutil>=5.9", - "tensorflow>=2.16,<3.0", + "tensorflow>=2.16,<2.19", "tensorflow-hub>=0.16", ] diff --git a/scripts/sync_benchmarks.sh b/scripts/sync_benchmarks.sh new file mode 100755 index 0000000..41235d0 --- /dev/null +++ b/scripts/sync_benchmarks.sh @@ -0,0 +1,119 @@ +#!/usr/bin/env bash +# Sync the benchmarks/ directory from this repo checkout to a remote +# machine — typically the research Mac where inference actually runs. +# +# Defaults match the Shu Lab research Mac (a Tailscale address): +# +# Levi@100.64.15.110:/Users/levi/Repos/neuropose/benchmarks/ +# +# Override either side via environment variables: +# +# REMOTE_HOST=user@host # SSH target +# REMOTE_PATH=/absolute/path/ # Remote destination (trailing slash +# # recommended — see rsync(1)) +# +# Flags: +# +# -n, --dry-run Show what would be transferred, change nothing. +# --delete Make the remote exactly mirror the local source, +# deleting any files on the remote that are not in +# the local tree. OFF by default because the remote +# may hold per-machine benchmark result JSONs you +# do not want to lose. Pass --delete explicitly +# when you *want* a clean mirror. +# -h, --help Print this header. +# +# What gets transferred: +# +# The entire benchmarks/ directory, including videos/*.mp4 and any +# *.json result files. The directory's .gitignore status is +# irrelevant to rsync — rsync copies what is in the working tree, +# not what is tracked by git — so the videos you drop into +# benchmarks/videos/ travel to the remote exactly as they sit on +# disk. +# +# Safety: +# +# - The script resolves its source directory relative to the repo +# root via `git rev-parse --show-toplevel`, so it works from any +# subdirectory of the checkout and never accidentally syncs some +# other `benchmarks/` that happens to live in $PWD. +# - --partial keeps half-transferred files on the remote so an +# interrupted run can resume on the next invocation. +# - Without --delete, the script is purely additive: it will create +# and update files on the remote but never remove them. +# +# Examples: +# +# scripts/sync_benchmarks.sh +# scripts/sync_benchmarks.sh --dry-run +# scripts/sync_benchmarks.sh --delete +# REMOTE_HOST=me@other-host scripts/sync_benchmarks.sh + +set -euo pipefail + +REMOTE_HOST="${REMOTE_HOST:-Levi@100.64.15.110}" +REMOTE_PATH="${REMOTE_PATH:-/Users/levi/Repos/neuropose/benchmarks/}" + +dry_run=0 +do_delete=0 + +while [ $# -gt 0 ]; do + case "$1" in + -n|--dry-run) + dry_run=1 + ;; + --delete) + do_delete=1 + ;; + -h|--help) + # Echo the leading comment block as the help text so the + # in-script documentation is the single source of truth. + sed -n '2,60p' "$0" | sed 's/^# \{0,1\}//' + exit 0 + ;; + *) + echo "error: unknown argument: $1" >&2 + echo "run with --help for usage" >&2 + exit 2 + ;; + esac + shift +done + +# Resolve the repo root so this script works from any cwd inside the +# checkout. $(dirname "$0") is the scripts/ directory; the parent is +# the repo root. +script_dir="$(cd "$(dirname "$0")" && pwd)" +repo_root="$(git -C "$script_dir" rev-parse --show-toplevel)" +source_dir="$repo_root/benchmarks/" + +if [ ! -d "$source_dir" ]; then + echo "error: source directory does not exist: $source_dir" >&2 + exit 1 +fi + +# rsync flags: +# -a archive mode (recurse + preserve metadata) +# -h human-readable sizes +# --partial resume interrupted transfers on the next run +# --info=progress2 single running progress line (rsync >= 3.1.0 +# on the local side; the remote's rsync version +# is irrelevant because progress is client-side) +rsync_flags=(-ah --partial --info=progress2) + +if [ $dry_run -eq 1 ]; then + rsync_flags+=(--dry-run) + echo "[dry-run] no files will actually be transferred" +fi + +if [ $do_delete -eq 1 ]; then + rsync_flags+=(--delete) + echo "[delete] remote will be pruned to exactly mirror local" +fi + +echo "source: $source_dir" +echo "target: $REMOTE_HOST:$REMOTE_PATH" +echo + +exec rsync "${rsync_flags[@]}" "$source_dir" "$REMOTE_HOST:$REMOTE_PATH" diff --git a/tests/unit/test_benchmark.py b/tests/unit/test_benchmark.py index aeb4fe8..1c140a6 100644 --- a/tests/unit/test_benchmark.py +++ b/tests/unit/test_benchmark.py @@ -246,7 +246,7 @@ class TestFormatBenchmarkReport: peak_rss_mb=512.0, active_device="/CPU:0", tensorflow_metal_active=False, - tensorflow_version="2.21.0", + tensorflow_version="2.18.0", ) def test_report_mentions_key_fields( @@ -276,7 +276,7 @@ class TestFormatBenchmarkReport: peak_rss_mb=100.0, active_device="/GPU:0", tensorflow_metal_active=True, - tensorflow_version="2.21.0", + tensorflow_version="2.18.0", ) agg = BenchmarkAggregate( repeats_measured=1, @@ -290,7 +290,7 @@ class TestFormatBenchmarkReport: peak_rss_mb_max=100.0, active_device="/GPU:0", tensorflow_metal_active=True, - tensorflow_version="2.21.0", + tensorflow_version="2.18.0", ) result = BenchmarkResult( video_name="test.mp4", diff --git a/tests/unit/test_io.py b/tests/unit/test_io.py index cd34632..339f23a 100644 --- a/tests/unit/test_io.py +++ b/tests/unit/test_io.py @@ -223,7 +223,7 @@ def _make_metrics( peak_rss_mb=peak_rss_mb, active_device=active_device, tensorflow_metal_active=metal_active, - tensorflow_version="2.21.0", + tensorflow_version="2.18.0", ) @@ -240,7 +240,7 @@ def _make_aggregate() -> BenchmarkAggregate: peak_rss_mb_max=512.0, active_device="/CPU:0", tensorflow_metal_active=False, - tensorflow_version="2.21.0", + tensorflow_version="2.18.0", ) @@ -256,7 +256,7 @@ class TestPerformanceMetricsModel: total_seconds=-1.0, peak_rss_mb=0.0, active_device="/CPU:0", - tensorflow_version="2.21.0", + tensorflow_version="2.18.0", ) def test_rejects_negative_peak_rss(self) -> None: @@ -265,7 +265,7 @@ class TestPerformanceMetricsModel: total_seconds=1.0, peak_rss_mb=-5.0, active_device="/CPU:0", - tensorflow_version="2.21.0", + tensorflow_version="2.18.0", ) def test_model_load_seconds_optional(self) -> None: diff --git a/uv.lock b/uv.lock index 5850499..f7df5d0 100644 --- a/uv.lock +++ b/uv.lock @@ -719,7 +719,7 @@ requires-dist = [ { name = "scikit-learn", marker = "extra == 'analysis'", specifier = ">=1.4" }, { name = "scipy", marker = "extra == 'analysis'", specifier = ">=1.12" }, { name = "sktime", marker = "extra == 'analysis'", specifier = ">=0.28" }, - { name = "tensorflow", specifier = ">=2.16,<3.0" }, + { name = "tensorflow", specifier = ">=2.16,<2.19" }, { name = "tensorflow-hub", specifier = ">=0.16" }, { name = "tensorflow-metal", marker = "platform_machine == 'arm64' and sys_platform == 'darwin' and extra == 'metal'", specifier = ">=1.2,<2" }, { name = "typer", specifier = ">=0.12" }, @@ -750,28 +750,20 @@ wheels = [ [[package]] name = "numpy" -version = "2.3.5" +version = "2.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/76/65/21b3bc86aac7b8f2862db1e808f1ea22b028e30a225a34a5ede9bf8678f2/numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0", size = 20584950, upload-time = "2025-11-16T22:52:42.067Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/75/10dd1f8116a8b796cb2c737b674e02d02e80454bda953fa7e65d8c12b016/numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78", size = 18902015, upload-time = "2024-08-26T20:19:40.945Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/77/84dd1d2e34d7e2792a236ba180b5e8fcc1e3e414e761ce0253f63d7f572e/numpy-2.3.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de5672f4a7b200c15a4127042170a694d4df43c992948f5e1af57f0174beed10", size = 17034641, upload-time = "2025-11-16T22:49:19.336Z" }, - { url = "https://files.pythonhosted.org/packages/2a/ea/25e26fa5837106cde46ae7d0b667e20f69cbbc0efd64cba8221411ab26ae/numpy-2.3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:acfd89508504a19ed06ef963ad544ec6664518c863436306153e13e94605c218", size = 12528324, upload-time = "2025-11-16T22:49:22.582Z" }, - { url = "https://files.pythonhosted.org/packages/4d/1a/e85f0eea4cf03d6a0228f5c0256b53f2df4bc794706e7df019fc622e47f1/numpy-2.3.5-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:ffe22d2b05504f786c867c8395de703937f934272eb67586817b46188b4ded6d", size = 5356872, upload-time = "2025-11-16T22:49:25.408Z" }, - { url = "https://files.pythonhosted.org/packages/5c/bb/35ef04afd567f4c989c2060cde39211e4ac5357155c1833bcd1166055c61/numpy-2.3.5-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:872a5cf366aec6bb1147336480fef14c9164b154aeb6542327de4970282cd2f5", size = 6893148, upload-time = "2025-11-16T22:49:27.549Z" }, - { url = "https://files.pythonhosted.org/packages/f2/2b/05bbeb06e2dff5eab512dfc678b1cc5ee94d8ac5956a0885c64b6b26252b/numpy-2.3.5-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3095bdb8dd297e5920b010e96134ed91d852d81d490e787beca7e35ae1d89cf7", size = 14557282, upload-time = "2025-11-16T22:49:30.964Z" }, - { url = "https://files.pythonhosted.org/packages/65/fb/2b23769462b34398d9326081fad5655198fcf18966fcb1f1e49db44fbf31/numpy-2.3.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cba086a43d54ca804ce711b2a940b16e452807acebe7852ff327f1ecd49b0d4", size = 16897903, upload-time = "2025-11-16T22:49:34.191Z" }, - { url = "https://files.pythonhosted.org/packages/ac/14/085f4cf05fc3f1e8aa95e85404e984ffca9b2275a5dc2b1aae18a67538b8/numpy-2.3.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6cf9b429b21df6b99f4dee7a1218b8b7ffbbe7df8764dc0bd60ce8a0708fed1e", size = 16341672, upload-time = "2025-11-16T22:49:37.2Z" }, - { url = "https://files.pythonhosted.org/packages/6f/3b/1f73994904142b2aa290449b3bb99772477b5fd94d787093e4f24f5af763/numpy-2.3.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:396084a36abdb603546b119d96528c2f6263921c50df3c8fd7cb28873a237748", size = 18838896, upload-time = "2025-11-16T22:49:39.727Z" }, - { url = "https://files.pythonhosted.org/packages/cd/b9/cf6649b2124f288309ffc353070792caf42ad69047dcc60da85ee85fea58/numpy-2.3.5-cp311-cp311-win32.whl", hash = "sha256:b0c7088a73aef3d687c4deef8452a3ac7c1be4e29ed8bf3b366c8111128ac60c", size = 6563608, upload-time = "2025-11-16T22:49:42.079Z" }, - { url = "https://files.pythonhosted.org/packages/aa/44/9fe81ae1dcc29c531843852e2874080dc441338574ccc4306b39e2ff6e59/numpy-2.3.5-cp311-cp311-win_amd64.whl", hash = "sha256:a414504bef8945eae5f2d7cb7be2d4af77c5d1cb5e20b296c2c25b61dff2900c", size = 13078442, upload-time = "2025-11-16T22:49:43.99Z" }, - { url = "https://files.pythonhosted.org/packages/6d/a7/f99a41553d2da82a20a2f22e93c94f928e4490bb447c9ff3c4ff230581d3/numpy-2.3.5-cp311-cp311-win_arm64.whl", hash = "sha256:0cd00b7b36e35398fa2d16af7b907b65304ef8bb4817a550e06e5012929830fa", size = 10458555, upload-time = "2025-11-16T22:49:47.092Z" }, - { url = "https://files.pythonhosted.org/packages/c6/65/f9dea8e109371ade9c782b4e4756a82edf9d3366bca495d84d79859a0b79/numpy-2.3.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f0963b55cdd70fad460fa4c1341f12f976bb26cb66021a5580329bd498988310", size = 16910689, upload-time = "2025-11-16T22:52:23.247Z" }, - { url = "https://files.pythonhosted.org/packages/00/4f/edb00032a8fb92ec0a679d3830368355da91a69cab6f3e9c21b64d0bb986/numpy-2.3.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f4255143f5160d0de972d28c8f9665d882b5f61309d8362fdd3e103cf7bf010c", size = 12457053, upload-time = "2025-11-16T22:52:26.367Z" }, - { url = "https://files.pythonhosted.org/packages/16/a4/e8a53b5abd500a63836a29ebe145fc1ab1f2eefe1cfe59276020373ae0aa/numpy-2.3.5-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:a4b9159734b326535f4dd01d947f919c6eefd2d9827466a696c44ced82dfbc18", size = 5285635, upload-time = "2025-11-16T22:52:29.266Z" }, - { url = "https://files.pythonhosted.org/packages/a3/2f/37eeb9014d9c8b3e9c55bc599c68263ca44fdbc12a93e45a21d1d56df737/numpy-2.3.5-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2feae0d2c91d46e59fcd62784a3a83b3fb677fead592ce51b5a6fbb4f95965ff", size = 6801770, upload-time = "2025-11-16T22:52:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/7d/e4/68d2f474df2cb671b2b6c2986a02e520671295647dad82484cde80ca427b/numpy-2.3.5-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffac52f28a7849ad7576293c0cb7b9f08304e8f7d738a8cb8a90ec4c55a998eb", size = 14391768, upload-time = "2025-11-16T22:52:33.593Z" }, - { url = "https://files.pythonhosted.org/packages/b8/50/94ccd8a2b141cb50651fddd4f6a48874acb3c91c8f0842b08a6afc4b0b21/numpy-2.3.5-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63c0e9e7eea69588479ebf4a8a270d5ac22763cc5854e9a7eae952a3908103f7", size = 16729263, upload-time = "2025-11-16T22:52:36.369Z" }, - { url = "https://files.pythonhosted.org/packages/2d/ee/346fa473e666fe14c52fcdd19ec2424157290a032d4c41f98127bfb31ac7/numpy-2.3.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f16417ec91f12f814b10bafe79ef77e70113a2f5f7018640e7425ff979253425", size = 12967213, upload-time = "2025-11-16T22:52:39.38Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cf/034500fb83041aa0286e0fb16e7c76e5c8b67c0711bb6e9e9737a717d5fe/numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448", size = 21169137, upload-time = "2024-08-26T20:07:45.345Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d9/32de45561811a4b87fbdee23b5797394e3d1504b4a7cf40c10199848893e/numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195", size = 13703552, upload-time = "2024-08-26T20:08:06.666Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ca/2f384720020c7b244d22508cb7ab23d95f179fcfff33c31a6eeba8d6c512/numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57", size = 5298957, upload-time = "2024-08-26T20:08:15.83Z" }, + { url = "https://files.pythonhosted.org/packages/0e/78/a3e4f9fb6aa4e6fdca0c5428e8ba039408514388cf62d89651aade838269/numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a", size = 6905573, upload-time = "2024-08-26T20:08:27.185Z" }, + { url = "https://files.pythonhosted.org/packages/a0/72/cfc3a1beb2caf4efc9d0b38a15fe34025230da27e1c08cc2eb9bfb1c7231/numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669", size = 13914330, upload-time = "2024-08-26T20:08:48.058Z" }, + { url = "https://files.pythonhosted.org/packages/ba/a8/c17acf65a931ce551fee11b72e8de63bf7e8a6f0e21add4c937c83563538/numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951", size = 19534895, upload-time = "2024-08-26T20:09:16.536Z" }, + { url = "https://files.pythonhosted.org/packages/ba/86/8767f3d54f6ae0165749f84648da9dcc8cd78ab65d415494962c86fac80f/numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9", size = 19937253, upload-time = "2024-08-26T20:09:46.263Z" }, + { url = "https://files.pythonhosted.org/packages/df/87/f76450e6e1c14e5bb1eae6836478b1028e096fd02e85c1c37674606ab752/numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15", size = 14414074, upload-time = "2024-08-26T20:10:08.483Z" }, + { url = "https://files.pythonhosted.org/packages/5c/ca/0f0f328e1e59f73754f06e1adfb909de43726d4f24c6a3f8805f34f2b0fa/numpy-2.0.2-cp311-cp311-win32.whl", hash = "sha256:a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4", size = 6470640, upload-time = "2024-08-26T20:10:19.732Z" }, + { url = "https://files.pythonhosted.org/packages/eb/57/3a3f14d3a759dcf9bf6e9eda905794726b758819df4663f217d658a58695/numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc", size = 15910230, upload-time = "2024-08-26T20:10:43.413Z" }, ] [[package]] @@ -938,17 +930,16 @@ wheels = [ [[package]] name = "protobuf" -version = "7.34.1" +version = "5.29.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6b/6b/a0e95cad1ad7cc3f2c6821fcab91671bd5b78bd42afb357bb4765f29bc41/protobuf-7.34.1.tar.gz", hash = "sha256:9ce42245e704cc5027be797c1db1eb93184d44d1cdd71811fb2d9b25ad541280", size = 454708, upload-time = "2026-03-20T17:34:47.036Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/57/394a763c103e0edf87f0938dafcd918d53b4c011dfc5c8ae80f3b0452dbb/protobuf-5.29.6.tar.gz", hash = "sha256:da9ee6a5424b6b30fd5e45c5ea663aef540ca95f9ad99d1e887e819cdf9b8723", size = 425623, upload-time = "2026-02-04T22:54:40.584Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7", size = 429247, upload-time = "2026-03-20T17:34:37.024Z" }, - { url = "https://files.pythonhosted.org/packages/eb/9d/aa69df2724ff63efa6f72307b483ce0827f4347cc6d6df24b59e26659fef/protobuf-7.34.1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:5185e0e948d07abe94bb76ec9b8416b604cfe5da6f871d67aad30cbf24c3110b", size = 325753, upload-time = "2026-03-20T17:34:38.751Z" }, - { url = "https://files.pythonhosted.org/packages/92/e8/d174c91fd48e50101943f042b09af9029064810b734e4160bbe282fa1caa/protobuf-7.34.1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:403b093a6e28a960372b44e5eb081775c9b056e816a8029c61231743d63f881a", size = 340198, upload-time = "2026-03-20T17:34:39.871Z" }, - { url = "https://files.pythonhosted.org/packages/53/1b/3b431694a4dc6d37b9f653f0c64b0a0d9ec074ee810710c0c3da21d67ba7/protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4", size = 324267, upload-time = "2026-03-20T17:34:41.1Z" }, - { url = "https://files.pythonhosted.org/packages/85/29/64de04a0ac142fb685fd09999bc3d337943fb386f3a0ec57f92fd8203f97/protobuf-7.34.1-cp310-abi3-win32.whl", hash = "sha256:34b84ce27680df7cca9f231043ada0daa55d0c44a2ddfaa58ec1d0d89d8bf60a", size = 426628, upload-time = "2026-03-20T17:34:42.536Z" }, - { url = "https://files.pythonhosted.org/packages/4d/87/cb5e585192a22b8bd457df5a2c16a75ea0db9674c3a0a39fc9347d84e075/protobuf-7.34.1-cp310-abi3-win_amd64.whl", hash = "sha256:e97b55646e6ce5cbb0954a8c28cd39a5869b59090dfaa7df4598a7fba869468c", size = 437901, upload-time = "2026-03-20T17:34:44.112Z" }, - { url = "https://files.pythonhosted.org/packages/88/95/608f665226bca68b736b79e457fded9a2a38c4f4379a4a7614303d9db3bc/protobuf-7.34.1-py3-none-any.whl", hash = "sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11", size = 170715, upload-time = "2026-03-20T17:34:45.384Z" }, + { url = "https://files.pythonhosted.org/packages/d4/88/9ee58ff7863c479d6f8346686d4636dd4c415b0cbeed7a6a7d0617639c2a/protobuf-5.29.6-cp310-abi3-win32.whl", hash = "sha256:62e8a3114992c7c647bce37dcc93647575fc52d50e48de30c6fcb28a6a291eb1", size = 423357, upload-time = "2026-02-04T22:54:25.805Z" }, + { url = "https://files.pythonhosted.org/packages/1c/66/2dc736a4d576847134fb6d80bd995c569b13cdc7b815d669050bf0ce2d2c/protobuf-5.29.6-cp310-abi3-win_amd64.whl", hash = "sha256:7e6ad413275be172f67fdee0f43484b6de5a904cc1c3ea9804cb6fe2ff366eda", size = 435175, upload-time = "2026-02-04T22:54:28.592Z" }, + { url = "https://files.pythonhosted.org/packages/06/db/49b05966fd208ae3f44dcd33837b6243b4915c57561d730a43f881f24dea/protobuf-5.29.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:b5a169e664b4057183a34bdc424540e86eea47560f3c123a0d64de4e137f9269", size = 418619, upload-time = "2026-02-04T22:54:30.266Z" }, + { url = "https://files.pythonhosted.org/packages/b7/d7/48cbf6b0c3c39761e47a99cb483405f0fde2be22cf00d71ef316ce52b458/protobuf-5.29.6-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:a8866b2cff111f0f863c1b3b9e7572dc7eaea23a7fae27f6fc613304046483e6", size = 320284, upload-time = "2026-02-04T22:54:31.782Z" }, + { url = "https://files.pythonhosted.org/packages/e3/dd/cadd6ec43069247d91f6345fa7a0d2858bef6af366dbd7ba8f05d2c77d3b/protobuf-5.29.6-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:e3387f44798ac1106af0233c04fb8abf543772ff241169946f698b3a9a3d3ab9", size = 320478, upload-time = "2026-02-04T22:54:32.909Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cb/e3065b447186cb70aa65acc70c86baf482d82bf75625bf5a2c4f6919c6a3/protobuf-5.29.6-py3-none-any.whl", hash = "sha256:6b9edb641441b2da9fa8f428760fc136a49cf97a52076010cf22a2ff73438a86", size = 173126, upload-time = "2026-02-04T22:54:39.462Z" }, ] [[package]] @@ -1327,9 +1318,39 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/0d/3b2e5b51593009f72fb7fb6956e6c652da1450c8c5484c40a276113c2114/sktime-0.40.1-py3-none-any.whl", hash = "sha256:130bb0c39ca4377e491c4dfa64c8ac67c3de2660dd406dd7690db6a8ac349c4e", size = 36265753, upload-time = "2025-11-25T00:03:34.522Z" }, ] +[[package]] +name = "tensorboard" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "absl-py" }, + { name = "grpcio" }, + { name = "markdown" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "protobuf" }, + { name = "setuptools" }, + { name = "six" }, + { name = "tensorboard-data-server" }, + { name = "werkzeug" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/de/021c1d407befb505791764ad2cbd56ceaaa53a746baed01d2e2143f05f18/tensorboard-2.18.0-py3-none-any.whl", hash = "sha256:107ca4821745f73e2aefa02c50ff70a9b694f39f790b11e6f682f7d326745eab", size = 5503036, upload-time = "2024-09-25T21:21:50.169Z" }, +] + +[[package]] +name = "tensorboard-data-server" +version = "0.7.2" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl", hash = "sha256:7e0610d205889588983836ec05dc098e80f97b7e7bbff7e994ebb78f578d0ddb", size = 2356, upload-time = "2023-10-23T21:23:32.16Z" }, + { url = "https://files.pythonhosted.org/packages/b7/85/dabeaf902892922777492e1d253bb7e1264cadce3cea932f7ff599e53fea/tensorboard_data_server-0.7.2-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:9fe5d24221b29625dbc7328b0436ca7fc1c23de4acf4d272f1180856e32f9f60", size = 4823598, upload-time = "2023-10-23T21:23:33.714Z" }, + { url = "https://files.pythonhosted.org/packages/73/c6/825dab04195756cf8ff2e12698f22513b3db2f64925bdd41671bfb33aaa5/tensorboard_data_server-0.7.2-py3-none-manylinux_2_31_x86_64.whl", hash = "sha256:ef687163c24185ae9754ed5650eb5bc4d84ff257aabdc33f0cc6f74d8ba54530", size = 6590363, upload-time = "2023-10-23T21:23:35.583Z" }, +] + [[package]] name = "tensorflow" -version = "2.21.0" +version = "2.18.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "absl-py" }, @@ -1349,15 +1370,17 @@ dependencies = [ { name = "requests" }, { name = "setuptools" }, { name = "six" }, + { name = "tensorboard" }, + { name = "tensorflow-io-gcs-filesystem" }, { name = "termcolor" }, { name = "typing-extensions" }, { name = "wrapt" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/76/b649b02a243c09f0348199dbd81408c1558cfbec2b6d77d820c428a95254/tensorflow-2.21.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:51f46f4806139d01fc7920cc72a4c75876f80649bf40ff083ab6212ceb43ca88", size = 223405849, upload-time = "2026-03-06T17:23:12.976Z" }, - { url = "https://files.pythonhosted.org/packages/9c/7c/57b7ee953b40d5d837136d20af6851b20ea6ca63753fc05699e8bcfab6d5/tensorflow-2.21.0-cp311-cp311-manylinux_2_27_aarch64.whl", hash = "sha256:4b24aca16d527a3cf1c37f720c04c484c3d20f4d0fdfa98632ac8b9f3be6eb5c", size = 281828020, upload-time = "2026-03-06T17:23:21.243Z" }, - { url = "https://files.pythonhosted.org/packages/26/a1/23b9b39c046c723db63a1c2c93397703efa3400a36f98d9c717b473aafb8/tensorflow-2.21.0-cp311-cp311-manylinux_2_27_x86_64.whl", hash = "sha256:9056fbc9ba04235810b71ae6cbd958a196e8804fb53bbcffbf3e23b56155f124", size = 572440367, upload-time = "2026-03-06T17:23:35.279Z" }, - { url = "https://files.pythonhosted.org/packages/8f/a2/6d7e6a738e302530586d484895de2cf3fc158ad9c73b4504a670b2956dd9/tensorflow-2.21.0-cp311-cp311-win_amd64.whl", hash = "sha256:0064a19bdc054a4b7c5e7e21cdf50ce38a114c2bada578b4f5267a37410f6784", size = 350834005, upload-time = "2026-03-06T17:23:53.021Z" }, + { url = "https://files.pythonhosted.org/packages/a1/88/57e2acd11a2587cc5c0a6612a389a57f3bda3cd60d132934cb7a9bb00a81/tensorflow-2.18.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:661029cd769b311db910b79a3a6ef50a5a61ecc947172228c777a49989722508", size = 239549037, upload-time = "2025-03-12T00:12:38.202Z" }, + { url = "https://files.pythonhosted.org/packages/c8/b3/902588dcffbc0603893f1df482840ff9c596430155d62e159bc8fc155230/tensorflow-2.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a6485edd2148f70d011dbd1d8dc2c775e91774a5a159466e83d0d1f21580944", size = 231937898, upload-time = "2025-03-12T00:12:47.544Z" }, + { url = "https://files.pythonhosted.org/packages/45/c6/05d862ebeaaf63343dffc4f97dab62ac493e8c2bbc6b1a256199bcc78ed4/tensorflow-2.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9f87e5d2a680a4595f5dc30daf6bbaec9d4129b46d7ef1b2af63c46ac7d2828", size = 615510377, upload-time = "2025-03-12T00:13:03.792Z" }, + { url = "https://files.pythonhosted.org/packages/28/2a/5f5ade4be81e521a16e143234747570ffd0d1a90e001ecc2688aa54bb419/tensorflow-2.18.1-cp311-cp311-win_amd64.whl", hash = "sha256:99223d0dde08aec4ceebb3bf0f80da7802e18462dab0d5048225925c064d2af7", size = 369183850, upload-time = "2025-03-12T00:13:24.786Z" }, ] [[package]] @@ -1373,6 +1396,17 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e5/50/00dba77925bf2a0a1e45d7bcf8a69a1d2534fb4bb277d9010bd148d2235e/tensorflow_hub-0.16.1-py2.py3-none-any.whl", hash = "sha256:e10c184b3d08daeafada11ffea2dd46781725b6bef01fad1f74d6634ad05311f", size = 30771, upload-time = "2024-01-30T14:49:07.005Z" }, ] +[[package]] +name = "tensorflow-io-gcs-filesystem" +version = "0.37.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/9b/b2fb82d0da673b17a334f785fc19c23483165019ddc33b275ef25ca31173/tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:32c50ab4e29a23c1f91cd0f9ab8c381a0ab10f45ef5c5252e94965916041737c", size = 2470224, upload-time = "2024-07-01T23:44:23.039Z" }, + { url = "https://files.pythonhosted.org/packages/5b/cc/16634e76f3647fbec18187258da3ba11184a6232dcf9073dc44579076d36/tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b02f9c5f94fd62773954a04f69b68c4d576d076fd0db4ca25d5479f0fbfcdbad", size = 3479613, upload-time = "2024-07-01T23:44:24.399Z" }, + { url = "https://files.pythonhosted.org/packages/de/bf/ba597d3884c77d05a78050f3c178933d69e3f80200a261df6eaa920656cd/tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e1f2796b57e799a8ca1b75bf47c2aaa437c968408cc1a402a9862929e104cda", size = 4842079, upload-time = "2024-07-01T23:44:26.825Z" }, + { url = "https://files.pythonhosted.org/packages/66/7f/e36ae148c2f03d61ca1bff24bc13a0fef6d6825c966abef73fc6f880a23b/tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee7c8ee5fe2fd8cb6392669ef16e71841133041fee8a330eff519ad9b36e4556", size = 5085736, upload-time = "2024-07-01T23:44:28.618Z" }, +] + [[package]] name = "tensorflow-metal" version = "1.2.0" @@ -1396,14 +1430,14 @@ wheels = [ [[package]] name = "tf-keras" -version = "2.21.0" +version = "2.18.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tensorflow" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/76/80/b005b59f9ccdbabc1b6cd07ca1126cbd4d902288438f0c00072f91a43c6f/tf_keras-2.21.0.tar.gz", hash = "sha256:f9af0f2546cd5532de0fae7a481f34a1ca2253737d4cd1000f6b713dc733f770", size = 1255377, upload-time = "2026-03-18T22:12:02.103Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/a4/7d0acc28cde2b29b8114552ce3258dafdc6b2186d24bf8e912de713dd74f/tf_keras-2.18.0.tar.gz", hash = "sha256:ebf744519b322afead33086a2aba872245473294affd40973694f3eb7c7ad77d", size = 1260765, upload-time = "2024-10-24T22:58:06.652Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/d2/5220e3b93444f1c57c092ab5eb2c30cdc762a6e412234750f2d6a85b3769/tf_keras-2.21.0-py3-none-any.whl", hash = "sha256:f858bf3d97f892304e7fbcf5eb0942ed91674e27204f940a85de8c93cf07fe62", size = 1694939, upload-time = "2026-03-18T22:12:00.662Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ed/e08afca471299b04a34cd548e64e89d0153eda0e6cf9b715356777e24774/tf_keras-2.18.0-py3-none-any.whl", hash = "sha256:c431d04027eef790fcd3261cf7fdf93eb74f3cb32e05078b57b7f5a54bd53262", size = 1725427, upload-time = "2024-10-24T22:58:03.918Z" }, ] [[package]] @@ -1523,6 +1557,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, ] +[[package]] +name = "werkzeug" +version = "3.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/b2/381be8cfdee792dd117872481b6e378f85c957dd7c5bca38897b08f765fd/werkzeug-3.1.8.tar.gz", hash = "sha256:9bad61a4268dac112f1c5cd4630a56ede601b6ed420300677a869083d70a4c44", size = 875852, upload-time = "2026-04-02T18:49:14.268Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/8c/2e650f2afeb7ee576912636c23ddb621c91ac6a98e66dc8d29c3c69446e1/werkzeug-3.1.8-py3-none-any.whl", hash = "sha256:63a77fb8892bf28ebc3178683445222aa500e48ebad5ec77b0ad80f8726b1f50", size = 226459, upload-time = "2026-04-02T18:49:12.72Z" }, +] + [[package]] name = "wheel" version = "0.46.3"