diff --git a/.copier-answers.resonant.yml b/.copier-answers.resonant.yml
index e12dbcc2a..b3597c89f 100644
--- a/.copier-answers.resonant.yml
+++ b/.copier-answers.resonant.yml
@@ -1,5 +1,5 @@
-_commit: v0.47.1
-_src_path: gh:kitware-resonant/cookiecutter-resonant
+_commit: v0.48.1
+_src_path: https://github.com/kitware-resonant/cookiecutter-resonant
core_app_name: api
include_example_code: false
project_name: DANDI Archive
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 4a6c81b02..ed34a6d8f 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -24,7 +24,7 @@
"ghcr.io/devcontainers-extra/features/heroku-cli:1.0.5": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/node:1": {
- "version": "20"
+ "version": "24"
}
},
"customizations": {
diff --git a/.github/renovate.json5 b/.github/renovate.json5
new file mode 100644
index 000000000..90da719b5
--- /dev/null
+++ b/.github/renovate.json5
@@ -0,0 +1,6 @@
+{
+ $schema: 'https://docs.renovatebot.com/renovate-schema.json',
+ extends: [
+ 'github>kitware-resonant/.github:renovate-project.json5',
+ ],
+}
diff --git a/.github/workflows/auto-add-issues.yml b/.github/workflows/auto-add-issues.yml
index a3545a48e..aac9d6fd3 100644
--- a/.github/workflows/auto-add-issues.yml
+++ b/.github/workflows/auto-add-issues.yml
@@ -9,7 +9,7 @@ on:
jobs:
add-to-project:
name: Add issue to project
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- uses: actions/add-to-project@v1.0.2
with:
diff --git a/.github/workflows/backend-ci.yml b/.github/workflows/backend-ci.yml
index b26619ce8..f837a170e 100644
--- a/.github/workflows/backend-ci.yml
+++ b/.github/workflows/backend-ci.yml
@@ -12,7 +12,7 @@ permissions:
contents: read
jobs:
test:
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
services:
postgres:
image: postgres:latest
diff --git a/.github/workflows/backend-production-deploy.yml b/.github/workflows/backend-production-deploy.yml
index effe0d562..0052692cd 100644
--- a/.github/workflows/backend-production-deploy.yml
+++ b/.github/workflows/backend-production-deploy.yml
@@ -25,7 +25,7 @@ concurrency:
jobs:
# reset-release-branch:
# name: Update release branch
- # runs-on: ubuntu-22.04
+ # runs-on: ubuntu-24.04
# steps:
# - uses: actions/checkout@v6
# with:
@@ -40,8 +40,8 @@ jobs:
production-deploy:
name: Deploy to Heroku
- runs-on: ubuntu-22.04
- #needs: reset-release-branch
+ runs-on: ubuntu-24.04
+ # needs: reset-release-branch
steps:
- uses: actions/checkout@v6
with:
@@ -55,7 +55,7 @@ jobs:
run: curl https://cli-assets.heroku.com/install.sh | sh
- name: Install builds plugin
- run: heroku plugins:install heroku-builds
+ run: heroku plugins:install @heroku-cli/heroku-builds
- name: Build app into tarball
run: |
diff --git a/.github/workflows/backend-staging-deploy.yml b/.github/workflows/backend-staging-deploy.yml
index 741c27a0a..afbb3179d 100644
--- a/.github/workflows/backend-staging-deploy.yml
+++ b/.github/workflows/backend-staging-deploy.yml
@@ -21,7 +21,7 @@ concurrency:
jobs:
deploy:
name: Deploy to Heroku
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
@@ -34,7 +34,7 @@ jobs:
run: curl https://cli-assets.heroku.com/install.sh | sh
- name: Install builds plugin
- run: heroku plugins:install heroku-builds
+ run: heroku plugins:install @heroku-cli/heroku-builds
- name: Build app into tarball
run: |
diff --git a/.github/workflows/cli-integration.yml b/.github/workflows/cli-integration.yml
index 40bf1d635..b5e76ba08 100644
--- a/.github/workflows/cli-integration.yml
+++ b/.github/workflows/cli-integration.yml
@@ -15,7 +15,7 @@ permissions:
jobs:
build-image:
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- name: Check out this repository
uses: actions/checkout@v6
@@ -40,7 +40,7 @@ jobs:
path: dandiarchive-api.tgz
test:
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
needs: build-image
strategy:
fail-fast: false
diff --git a/.github/workflows/frontend-ci.yml b/.github/workflows/frontend-ci.yml
index 38ca6cb61..03db070ea 100644
--- a/.github/workflows/frontend-ci.yml
+++ b/.github/workflows/frontend-ci.yml
@@ -11,7 +11,7 @@ jobs:
defaults:
run:
working-directory: web
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
@@ -19,7 +19,7 @@ jobs:
- uses: actions/setup-node@v6
with:
- node-version: 20.x
+ node-version: 24.x
- name: Install Vue app
run: npm ci
@@ -35,7 +35,7 @@ jobs:
test-e2e:
name: E2E tests
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
services:
postgres:
image: postgres:latest
@@ -93,7 +93,7 @@ jobs:
- uses: actions/setup-node@v6
with:
- node-version: 20
+ node-version: 24
- name: Install uv
uses: astral-sh/setup-uv@v7
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ba612620b..fc3c7eb7d 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -12,7 +12,7 @@ on:
jobs:
release:
if: "!contains(github.event.head_commit.message, 'ci skip') && !contains(github.event.head_commit.message, 'skip ci')"
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 86d4dcd9d..7ad3c8774 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,51 @@
+# v0.21.11 (Tue Mar 24 2026)
+
+#### 🐛 Bug Fix
+
+- Update dashboard permissions [#2752](https://github.com/dandi/dandi-archive/pull/2752) ([@jjnesbitt](https://github.com/jjnesbitt))
+- Fix heroku build [#2741](https://github.com/dandi/dandi-archive/pull/2741) ([@jjnesbitt](https://github.com/jjnesbitt))
+- Update dependency ubuntu to v24 [#2738](https://github.com/dandi/dandi-archive/pull/2738) ([@renovate[bot]](https://github.com/renovate[bot]))
+
+#### Authors: 2
+
+- [@renovate[bot]](https://github.com/renovate[bot])
+- Jacob Nesbitt ([@jjnesbitt](https://github.com/jjnesbitt))
+
+---
+
+# v0.21.10 (Wed Mar 18 2026)
+
+#### 🐛 Bug Fix
+
+- Add Blog link to AppBar navigation [#2739](https://github.com/dandi/dandi-archive/pull/2739) ([@yarikoptic](https://github.com/yarikoptic))
+- Update dependency @sentry/vue to v10 [#2736](https://github.com/dandi/dandi-archive/pull/2736) ([@renovate[bot]](https://github.com/renovate[bot]))
+- Update dependency node to v24 [#2737](https://github.com/dandi/dandi-archive/pull/2737) ([@renovate[bot]](https://github.com/renovate[bot]))
+- Upgrade to Resonant v0.48.1 [#2734](https://github.com/dandi/dandi-archive/pull/2734) ([@brianhelba](https://github.com/brianhelba))
+- Add required pytest marks for test_info tests [#2727](https://github.com/dandi/dandi-archive/pull/2727) ([@jjnesbitt](https://github.com/jjnesbitt))
+
+#### Authors: 4
+
+- [@renovate[bot]](https://github.com/renovate[bot])
+- Brian Helba ([@brianhelba](https://github.com/brianhelba))
+- Jacob Nesbitt ([@jjnesbitt](https://github.com/jjnesbitt))
+- Yaroslav Halchenko ([@yarikoptic](https://github.com/yarikoptic))
+
+---
+
+# v0.21.9 (Wed Mar 11 2026)
+
+#### 🐛 Bug Fix
+
+- Display the correct CLI and required python version in the GUI [#2714](https://github.com/dandi/dandi-archive/pull/2714) ([@jjnesbitt](https://github.com/jjnesbitt))
+- Remove CLI as core dependency [#2715](https://github.com/dandi/dandi-archive/pull/2715) ([@jjnesbitt](https://github.com/jjnesbitt))
+- Set asset to pending when its zarr is ingested [#2720](https://github.com/dandi/dandi-archive/pull/2720) ([@jjnesbitt](https://github.com/jjnesbitt))
+
+#### Authors: 1
+
+- Jacob Nesbitt ([@jjnesbitt](https://github.com/jjnesbitt))
+
+---
+
# v0.21.8 (Fri Mar 06 2026)
#### 🐛 Bug Fix
diff --git a/dandiapi/api/management/commands/extract_metadata.py b/dandiapi/api/management/commands/extract_metadata.py
index 5fdf25fb4..a1a479566 100644
--- a/dandiapi/api/management/commands/extract_metadata.py
+++ b/dandiapi/api/management/commands/extract_metadata.py
@@ -1,12 +1,11 @@
from __future__ import annotations
+import importlib.util
import logging
from pathlib import Path
+import sys
from typing import TYPE_CHECKING
-from dandi.dandiapi import RemoteReadableAsset
-from dandi.metadata.nwb import nwb2asset
-from dandi.misctypes import Digest, DigestType
from dandischema.models import get_schema_version
from django.contrib.auth.models import User
from django.db import transaction
@@ -22,6 +21,15 @@
logger = logging.getLogger(__name__)
+# The CLI only exists as an optional requirement, so ensure it's been specified correctly.
+if importlib.util.find_spec('dandi') is None:
+ click.echo('Module "dandi" not found. Please run:\n\tuv sync --extra cli')
+ sys.exit(1)
+else:
+ from dandi.dandiapi import RemoteReadableAsset
+ from dandi.metadata.nwb import nwb2asset
+ from dandi.misctypes import Digest, DigestType
+
@click.group()
def group():
diff --git a/dandiapi/api/tests/test_dashboard.py b/dandiapi/api/tests/test_dashboard.py
new file mode 100644
index 000000000..2b232968d
--- /dev/null
+++ b/dandiapi/api/tests/test_dashboard.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+import pytest
+
+from dandiapi.api.tests.factories import UserFactory
+
+
+@pytest.mark.parametrize(
+ ('is_staff', 'is_superuser'),
+ [
+ (False, False),
+ (False, True),
+ (True, False),
+ (True, True),
+ ],
+)
+@pytest.mark.django_db
+def test_dashboard_access(api_client, is_staff, is_superuser):
+ user = UserFactory.create(is_staff=is_staff, is_superuser=is_superuser)
+ api_client.force_login(user)
+ resp = api_client.get('/dashboard/')
+
+ should_pass = is_staff or is_superuser
+ assert resp.status_code == (200 if should_pass else 403)
+
+
+@pytest.mark.django_db
+def test_dashboard_access_unauthenticated(api_client):
+ resp = api_client.get('/dashboard/')
+ assert resp.status_code == 302
+
+
+@pytest.mark.parametrize(
+ ('is_staff', 'is_superuser'),
+ [
+ (False, False),
+ (False, True),
+ (True, False),
+ (True, True),
+ ],
+)
+@pytest.mark.django_db
+def test_user_approval_access(api_client, is_staff, is_superuser):
+ user = UserFactory.create(is_staff=is_staff, is_superuser=is_superuser)
+ api_client.force_login(user)
+
+ other_user = UserFactory.create()
+ resp = api_client.get(f'/dashboard/user/{other_user.username}/')
+
+ should_pass = is_staff or is_superuser
+ assert resp.status_code == (200 if should_pass else 403)
+
+
+@pytest.mark.django_db
+def test_user_approval_access_unauthenticated(api_client):
+ other_user = UserFactory.create()
+ resp = api_client.get(f'/dashboard/user/{other_user.username}/')
+ assert resp.status_code == 302
+
+
+@pytest.mark.parametrize(
+ ('is_staff', 'is_superuser'),
+ [
+ (False, False),
+ (False, True),
+ (True, False),
+ (True, True),
+ ],
+)
+@pytest.mark.django_db
+def test_mailchimp_view_access(api_client, is_staff, is_superuser):
+ user = UserFactory.create(is_staff=is_staff, is_superuser=is_superuser)
+ api_client.force_login(user)
+
+ resp = api_client.get('/dashboard/mailchimp/')
+
+ should_pass = is_staff or is_superuser
+ assert resp.status_code == (200 if should_pass else 403)
+
+
+@pytest.mark.django_db
+def test_mailchimp_view_access_unauthenticated(api_client):
+ resp = api_client.get('/dashboard/mailchimp/')
+ assert resp.status_code == 403
diff --git a/dandiapi/api/tests/test_info.py b/dandiapi/api/tests/test_info.py
index da82b8b2b..649d3f5b0 100644
--- a/dandiapi/api/tests/test_info.py
+++ b/dandiapi/api/tests/test_info.py
@@ -1,7 +1,11 @@
from __future__ import annotations
+import importlib.metadata
+
from dandischema.conf import get_instance_config
+from packaging.specifiers import SpecifierSet
import pytest
+import requests
@pytest.mark.django_db
@@ -16,3 +20,37 @@ def test_rest_info_instance_config_include_none(api_client):
resp.json()['instance_config'].keys()
== get_instance_config().model_dump(mode='json', exclude_none=False).keys()
)
+
+
+@pytest.mark.django_db
+def test_cli_minimal_version_matches_dandischema(api_client):
+ """Test that local dandischema and minimal cli dandischema are compatible."""
+ # Get CLI version info from pypi
+ minimal_version = api_client.get('/api/info/').json()['cli-minimal-version']
+ data = requests.get(f'https://pypi.org/pypi/dandi/{minimal_version}/json').json()
+
+ # Extract the dandischema requirement
+ dandischema_requires = [x for x in data['info']['requires_dist'] if x.startswith('dandischema')]
+ assert len(dandischema_requires) == 1
+ dandischema_version: str = dandischema_requires[0]
+ version_range = SpecifierSet(
+ dandischema_version.split(';', maxsplit=1)[0].removeprefix('dandischema').strip()
+ )
+
+ # Ensure that local dandischema is compatible with the CLI version
+ local_version = importlib.metadata.version('dandischema')
+ assert version_range.contains(local_version)
+
+
+@pytest.mark.django_db
+def test_cli_requires_python_compatible_with_minimal_version(api_client):
+ """Test that the CLI's required python version is compatible with the minimal version."""
+ info = api_client.get('/api/info/').json()
+ minimal_version: str = info['cli-minimal-version']
+ data = requests.get(f'https://pypi.org/pypi/dandi/{minimal_version}/json').json()
+
+ cli_requires_python: str = info['cli-requires-python']
+ dandischema_requires_python: str = data['info']['requires_python']
+
+ # Test for exact match
+ assert cli_requires_python == dandischema_requires_python
diff --git a/dandiapi/api/views/dashboard.py b/dandiapi/api/views/dashboard.py
index 4f567cbce..89af3307f 100644
--- a/dandiapi/api/views/dashboard.py
+++ b/dandiapi/api/views/dashboard.py
@@ -1,6 +1,7 @@
from __future__ import annotations
import csv
+import typing
from typing import TYPE_CHECKING
from django.conf import settings
@@ -25,7 +26,8 @@
class DashboardMixin(LoginRequiredMixin, UserPassesTestMixin):
def test_func(self):
- return self.request.user.is_superuser
+ user = typing.cast('User', self.request.user)
+ return user.is_staff or user.is_superuser
class DashboardView(DashboardMixin, TemplateView):
@@ -87,6 +89,10 @@ def _users(self):
def mailchimp_csv_view(request: HttpRequest) -> StreamingHttpResponse:
"""Generate a Mailchimp-compatible CSV file of all active users."""
+ # If they are authenticated but are not a superuser or staff, deny access
+ if not (request.user.is_superuser or request.user.is_staff):
+ raise PermissionDenied
+
# Exclude the django-guardian anonymous user account.
users = User.objects.filter(metadata__status=UserMetadata.Status.APPROVED).exclude(
username='AnonymousUser'
@@ -125,8 +131,8 @@ def user_approval_view(request: HttpRequest, username: str):
if not request.user.is_authenticated:
return HttpResponseRedirect(redirect_to=f'{settings.LOGIN_URL}?next={request.path}')
- # If they are authenticated but are not a superuser, deny access
- if not request.user.is_superuser:
+ # If they are authenticated but are not a superuser or staff, deny access
+ if not (request.user.is_superuser or request.user.is_staff):
raise PermissionDenied
user: User = get_object_or_404(User.objects.select_related('metadata'), username=username)
diff --git a/dandiapi/api/views/info.py b/dandiapi/api/views/info.py
index 69b1752a2..a44416fba 100644
--- a/dandiapi/api/views/info.py
+++ b/dandiapi/api/views/info.py
@@ -48,6 +48,7 @@ def __init__(self, *args, **kwargs):
self.fields.update(
{
'cli-minimal-version': serializers.CharField(),
+ 'cli-requires-python': serializers.CharField(),
'cli-bad-versions': serializers.ListField(child=serializers.CharField()),
}
)
@@ -84,7 +85,8 @@ def info_view(request):
'schema_url': get_schema_url(),
'allowed_schema_versions': ALLOWED_INPUT_SCHEMAS,
'version': importlib.metadata.version('dandiapi'),
- 'cli-minimal-version': '0.60.0',
+ 'cli-minimal-version': '0.74.0',
+ 'cli-requires-python': '>=3.10',
'cli-bad-versions': [],
'services': {
'api': {'url': api_url},
diff --git a/dandiapi/zarr/tasks/__init__.py b/dandiapi/zarr/tasks/__init__.py
index 7389297c8..852402095 100644
--- a/dandiapi/zarr/tasks/__init__.py
+++ b/dandiapi/zarr/tasks/__init__.py
@@ -8,6 +8,7 @@
from zarr_checksum.generators import S3ClientOptions, yield_files_s3
from dandiapi.api.asset_paths import add_zarr_paths, delete_zarr_paths
+from dandiapi.api.models.asset import Asset
from dandiapi.api.models.version import Version
from dandiapi.zarr.models import ZarrArchive, ZarrArchiveStatus
@@ -73,6 +74,11 @@ def ingest_zarr_archive(zarr_id: str, *, force: bool = False):
status=Version.Status.PENDING, modified=timezone.now()
)
+ # Set the asset status back to pending, and update modified
+ zarr_assets = Asset.objects.filter(zarr=zarr, published=False)
+ if zarr_assets.exists():
+ zarr_assets.update(status=Asset.Status.PENDING, modified=timezone.now())
+
def ingest_dandiset_zarrs(dandiset_id: int, **kwargs):
for zarr in ZarrArchive.objects.filter(dandiset__id=dandiset_id):
diff --git a/e2e/package-lock.json b/e2e/package-lock.json
index a14a937fd..5e76f5658 100644
--- a/e2e/package-lock.json
+++ b/e2e/package-lock.json
@@ -8,7 +8,7 @@
"devDependencies": {
"@faker-js/faker": "^9.6.0",
"@playwright/test": "^1.41.2",
- "@types/node": "^20.11.19",
+ "@types/node": "^24.0.0",
"axios": "^1.6.7",
"lodash": "^4.17.21",
"moment": "^2.29.4"
@@ -48,13 +48,13 @@
}
},
"node_modules/@types/node": {
- "version": "20.17.30",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.30.tgz",
- "integrity": "sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==",
+ "version": "24.12.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
+ "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "undici-types": "~6.19.2"
+ "undici-types": "~7.16.0"
}
},
"node_modules/asynckit": {
@@ -423,9 +423,9 @@
"license": "MIT"
},
"node_modules/undici-types": {
- "version": "6.19.8",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
- "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
"dev": true,
"license": "MIT"
}
diff --git a/e2e/package.json b/e2e/package.json
index 67d726aa4..cc4cd0344 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -9,7 +9,7 @@
"devDependencies": {
"@faker-js/faker": "^9.6.0",
"@playwright/test": "^1.41.2",
- "@types/node": "^20.11.19",
+ "@types/node": "^24.0.0",
"axios": "^1.6.7",
"lodash": "^4.17.21",
"moment": "^2.29.4"
diff --git a/pyproject.toml b/pyproject.toml
index 040dffa34..9091bb2fb 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,5 +1,5 @@
[build-system]
-requires = ["hatchling", "hatch-vcs"]
+requires = ["hatchling==1.29.0", "hatch-vcs==0.5.0"]
build-backend = "hatchling.build"
[project]
@@ -10,57 +10,57 @@ license-files = ["LICENSE", "NOTICE"]
classifiers = ["Private :: Do Not Upload"]
dependencies = [
# Runtime dependencies, always needed
- "boto3",
- "celery",
- "dandi", # minimal version is also provided in API /info
+ "boto3==1.40.51",
+ "celery==5.5.3",
# Pin dandischema to exact version to make explicit which schema version is being used
"dandischema==0.12.1", # schema version 0.7.0
- "django[argon2]",
- "django-allauth",
- "django-auth-style",
- "django-click",
- "django-cors-headers",
- "django-environ",
- "django-extensions",
- "django-filter",
- "django-guardian",
- "django-oauth-toolkit",
- "django-resonant-settings[allauth,celery]",
- "django-resonant-utils[allauth,s3_storage]",
- "django-stubs-ext",
+ "django[argon2]==5.2.7",
+ "django-allauth==65.12.0",
+ "django-auth-style==0.12.0",
+ "django-click==2.4.1",
+ "django-cors-headers==4.9.0",
+ "django-environ==0.12.1",
+ "django-extensions==4.1",
+ "django-filter==25.2",
+ "django-guardian==3.2.0",
+ "django-oauth-toolkit==3.1.0",
+ "django-resonant-settings[allauth,celery]==0.48.1",
+ "django-resonant-utils[allauth,s3_storage]==0.16.0",
+ "django-stubs-ext==5.2.7",
# TODO: pin djangorestframework until we figure out what the cause of
# https://github.com/dandi/dandi-archive/issues/1896 is.
- "djangorestframework<3.15.0",
- "drf-extensions",
- "drf-yasg",
- "fsspec[http]",
- "jsonschema",
- "more_itertools",
- "psycopg[binary]",
- "pyyaml",
- "requests",
- "rich",
- "whitenoise[brotli]",
- "zarr-checksum",
+ "djangorestframework==3.14.0",
+ "drf-extensions==0.8.0",
+ "drf-yasg==1.21.11",
+ "fsspec[http]==2025.9.0",
+ "jsonschema==4.25.1",
+ "more_itertools==10.8.0",
+ "psycopg[binary]==3.2.10",
+ "pyyaml==6.0.3",
+ "requests==2.32.5",
+ "rich==14.2.0",
+ "whitenoise[brotli]==6.11.0",
+ "zarr-checksum==0.4.7",
# Production-only
- "django-s3-file-field[s3]",
- "django-storages[s3]",
- "sentry-sdk[celery,django,pure_eval]",
- "gunicorn",
+ "django-s3-file-field[s3]==1.1.0",
+ "django-storages[s3]==1.14.6",
+ "sentry-sdk[celery,django,pure_eval]==2.41.0",
+ "gunicorn==23.0.0",
# Development-only, but required
- "tqdm",
+ "tqdm==4.67.1",
]
dynamic = ["version"]
[project.optional-dependencies]
development = [
# Runtime dependencies, only needed with "development" settings
- "django-browser-reload",
- "django-debug-toolbar",
- "ipython",
- "watchdog",
- "werkzeug",
+ "django-browser-reload==1.21.0",
+ "django-debug-toolbar==6.0.0",
+ "ipython==9.6.0",
+ "watchdog==6.0.0",
+ "werkzeug==3.1.3",
]
+cli = ["dandi==0.74.3"]
[dependency-groups]
dev = [
@@ -68,36 +68,36 @@ dev = [
# The "dev" dependency group is installed by default,
# so use this to install "development" extras by default too
"dandiapi[development]",
- "pre-commit",
- "tox",
- "tox-uv",
+ "pre-commit==4.3.0",
+ "tox==4.31.0",
+ "tox-uv==1.29.0",
]
lint = [
- "ruff",
+ "ruff==0.14.0",
]
type = [
- "mypy",
- "boto3-stubs[s3]",
- "celery-types",
- "django-stubs[compatible-mypy]",
- "djangorestframework-stubs[compatible-mypy]",
+ "mypy==1.18.2",
+ "boto3-stubs[s3]==1.40.51",
+ "celery-types==0.23.0",
+ "django-stubs[compatible-mypy]==5.2.7",
+ "djangorestframework-stubs[compatible-mypy]==3.16.4",
]
test = [
- "djangorestframework-yaml",
- "Faker",
- "factory-boy",
- "freezegun",
- "pytest",
- "pytest-cov",
- "pytest-django",
- "pytest-factoryboy",
+ "djangorestframework-yaml==2.0.0",
+ "Faker==37.11.0",
+ "factory-boy==3.3.3",
+ "freezegun==1.5.5",
+ "pytest==8.4.2",
+ "pytest-cov==7.0.0",
+ "pytest-django==4.11.1",
+ "pytest-factoryboy==2.8.1",
# Enable with "pytest --memray ..."
- "pytest-memray",
- "pytest-mock",
+ "pytest-memray==1.8.0",
+ "pytest-mock==3.15.1",
# Enable with "pytest --random-order ..."
- "pytest-random-order",
+ "pytest-random-order==1.2.0",
# Enable with "pytest --count=... ..."
- "pytest-repeat",
+ "pytest-repeat==0.9.4",
]
[tool.hatch.build]
diff --git a/uv.lock b/uv.lock
index f714f652d..1e63fbc38 100644
--- a/uv.lock
+++ b/uv.lock
@@ -7,6 +7,15 @@ resolution-markers = [
"python_full_version < '3.14'",
]
+[[package]]
+name = "acres"
+version = "0.5.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ec/ba/94b63a9af588fbf7bde25ce44d55456199654a92fb7b2337767198a824b0/acres-0.5.0.tar.gz", hash = "sha256:128b6447bf5df3b6210264feccbfa018b4ac5bd337358319aec6563f99db8f3a", size = 57750, upload-time = "2025-06-04T12:40:30.329Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/39/e8/806475fe4cdfd8635535d3fa11bd61d19b7cc94b61b9147ebdd2ab4cbbee/acres-0.5.0-py3-none-any.whl", hash = "sha256:fcc32b974b510897de0f041609b4234f9ff03e2e960aea088f63973fb106c772", size = 12703, upload-time = "2025-06-04T12:40:28.745Z" },
+]
+
[[package]]
name = "aiohappyeyeballs"
version = "2.6.1"
@@ -117,15 +126,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
]
-[[package]]
-name = "appdirs"
-version = "1.4.4"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/d7/d8/05696357e0311f5b5c316d7b95f46c669dd9c15aaeecbb48c7d0aeb88c40/appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", size = 13470, upload-time = "2020-05-11T07:59:51.037Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128", size = 9566, upload-time = "2020-05-11T07:59:49.499Z" },
-]
-
[[package]]
name = "argon2-cffi"
version = "25.1.0"
@@ -182,6 +182,12 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/f8/ed/e97229a566617f2ae958a6b13e7cc0f585470eac730a73e9e82c32a3cdd2/arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80", size = 66419, upload-time = "2023-09-30T22:11:16.072Z" },
]
+[[package]]
+name = "asciitree"
+version = "0.3.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/2d/6a/885bc91484e1aa8f618f6f0228d76d0e67000b0fdd6090673b777e311913/asciitree-0.3.3.tar.gz", hash = "sha256:4aa4b9b649f85e3fcb343363d97564aa1fb62e249677f2e18a96765145cc0f6e", size = 3951, upload-time = "2016-09-05T19:10:42.681Z" }
+
[[package]]
name = "asgiref"
version = "3.10.0"
@@ -209,6 +215,33 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" },
]
+[[package]]
+name = "bids-validator-deno"
+version = "2.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7e/36/2ab666d2277469c47ba6e8171cd2bbf3791201e8793e717a79e4544d545f/bids_validator_deno-2.4.0.tar.gz", hash = "sha256:78cd6bc4d43aa6b17555185181c74b22e2ccaea8c3494175b6524807b467aa94", size = 83454, upload-time = "2026-02-05T16:18:34.446Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8c/4b/66f13d9875214815540c80e86048c34d9c2e14a8b1b9f35c0e0eaf37757a/bids_validator_deno-2.4.0-py2.py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9018593f9f768c0912001fb724374eff1034128374512e0da08ff727920c604", size = 43212524, upload-time = "2026-02-05T16:18:19.278Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/ee/88190e9bc2c747217601ad625462eebc22642cacd0b0864b966655efd71a/bids_validator_deno-2.4.0-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:a35622e2b0f5772fe08ba309e3eac9a3ad47cc4aecc37c4a6e93aea2b72f2849", size = 41071591, upload-time = "2026-02-05T16:18:22.494Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/c6/4ad8cdc2128d323c23933aa9d453b17bbd8a8632fad3c0fd2a5358749091/bids_validator_deno-2.4.0-py2.py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4fdf1267c1da17402d143d6b4f963cf54117dec1525e9f68437f6ace3518219", size = 43476625, upload-time = "2026-02-05T16:18:25.303Z" },
+ { url = "https://files.pythonhosted.org/packages/6c/c0/a73e362dfe68d6b7fb2507d4d513685a07f745bfc86624d2788f27f001cd/bids_validator_deno-2.4.0-py2.py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6a7000b926323d25c6122ea4f92579eb7cd13790d5a2d90eb22fa069837a530", size = 44741656, upload-time = "2026-02-05T16:18:28.389Z" },
+ { url = "https://files.pythonhosted.org/packages/38/2a/f5a15654795fe1010a7a51a14231c815840aa930b1a1f85dfd395dd83172/bids_validator_deno-2.4.0-py2.py3-none-win_amd64.whl", hash = "sha256:181cc80b792523970a134962e1f65ec0539b455fa5aaeef1d1e3a1b20a29c5eb", size = 44004476, upload-time = "2026-02-05T16:18:31.058Z" },
+]
+
+[[package]]
+name = "bidsschematools"
+version = "1.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "acres" },
+ { name = "click" },
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/82/9c/e65cf502947a27748ad572528f5fab6836bd8e8276029e912c226100f83f/bidsschematools-1.2.0.tar.gz", hash = "sha256:0f5af8d669793483c42298d670fdd73ac39eeb28793fb48dee4adc0cfae58f58", size = 1767945, upload-time = "2026-02-04T21:01:01.971Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b8/86/577bac5e163e1a85ec3430e9cea64f7efe52d044c40ff795d994c4a6b363/bidsschematools-1.2.0-py3-none-any.whl", hash = "sha256:34ab6b2a404cd73a0a0b664c506a4b43e94dda12fe2380cc808e976913ac5dcc", size = 194012, upload-time = "2026-02-04T21:00:59.775Z" },
+]
+
[[package]]
name = "billiard"
version = "4.2.2"
@@ -647,21 +680,27 @@ wheels = [
[[package]]
name = "dandi"
-version = "0.17.0"
+version = "0.74.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "appdirs" },
+ { name = "bids-validator-deno" },
+ { name = "bidsschematools" },
{ name = "click" },
{ name = "click-didyoumean" },
- { name = "email-validator" },
+ { name = "dandischema" },
{ name = "etelemetry" },
{ name = "fasteners" },
{ name = "fscacher" },
+ { name = "hdmf" },
{ name = "humanize" },
+ { name = "interleave" },
{ name = "joblib" },
- { name = "jsonschema" },
{ name = "keyring" },
{ name = "keyrings-alt" },
+ { name = "numcodecs" },
+ { name = "nwbinspector" },
+ { name = "packaging" },
+ { name = "platformdirs" },
{ name = "pycryptodomex" },
{ name = "pydantic" },
{ name = "pynwb" },
@@ -671,11 +710,15 @@ dependencies = [
{ name = "ruamel-yaml" },
{ name = "semantic-version" },
{ name = "tenacity" },
- { name = "tqdm" },
+ { name = "tensorstore" },
+ { name = "urllib3" },
+ { name = "yarl" },
+ { name = "zarr" },
+ { name = "zarr-checksum" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/81/e0/185a68af1a5e20564e654984b24c7f4e7d42e41d2e038f13d558ad5b1523/dandi-0.17.0.tar.gz", hash = "sha256:5198c9087b1fab0767be8314e382637bfd75ee61092419ce00dd3a341816b99d", size = 143395, upload-time = "2021-05-12T20:54:10.065Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/b2/63/058c64e3e9402d5da145be8dcaacf1803df735d72a5e1db63d63dc0249af/dandi-0.74.3.tar.gz", hash = "sha256:675a8ff978f044ed5532cb55b18ab40e5f0c291ea73d57d5d31930315cba4ebf", size = 369716, upload-time = "2026-02-14T03:30:56.29Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/a8/f1/e4ed51dc07f5ccfd44d8a1e2d940b375dc8c3abbb119fd78fdd051d00036/dandi-0.17.0-py3-none-any.whl", hash = "sha256:0dc9d9cabcf083e2169a4fc70c0d1f8ea60762a4dac66f8e27ed6e778f628c67", size = 152512, upload-time = "2021-05-12T20:54:08.554Z" },
+ { url = "https://files.pythonhosted.org/packages/ef/e9/b2803835dad7f13c5ab01896c95d868bf8eafc014b633af64bb3e3cd845c/dandi-0.74.3-py3-none-any.whl", hash = "sha256:2b1d5e1038d8e775a3ce6c5864c4519cfb2ee96727bc73f4902851548cba0540", size = 370877, upload-time = "2026-02-14T03:30:54.274Z" },
]
[[package]]
@@ -684,7 +727,6 @@ source = { editable = "." }
dependencies = [
{ name = "boto3" },
{ name = "celery" },
- { name = "dandi" },
{ name = "dandischema" },
{ name = "django", extra = ["argon2"] },
{ name = "django-allauth" },
@@ -719,6 +761,9 @@ dependencies = [
]
[package.optional-dependencies]
+cli = [
+ { name = "dandi" },
+]
development = [
{ name = "django-browser-reload" },
{ name = "django-debug-toolbar" },
@@ -761,76 +806,76 @@ type = [
[package.metadata]
requires-dist = [
- { name = "boto3" },
- { name = "celery" },
- { name = "dandi" },
+ { name = "boto3", specifier = "==1.40.51" },
+ { name = "celery", specifier = "==5.5.3" },
+ { name = "dandi", marker = "extra == 'cli'", specifier = "==0.74.3" },
{ name = "dandischema", specifier = "==0.12.1" },
- { name = "django", extras = ["argon2"] },
- { name = "django-allauth" },
- { name = "django-auth-style" },
- { name = "django-browser-reload", marker = "extra == 'development'" },
- { name = "django-click" },
- { name = "django-cors-headers" },
- { name = "django-debug-toolbar", marker = "extra == 'development'" },
- { name = "django-environ" },
- { name = "django-extensions" },
- { name = "django-filter" },
- { name = "django-guardian" },
- { name = "django-oauth-toolkit" },
- { name = "django-resonant-settings", extras = ["allauth", "celery"] },
- { name = "django-resonant-utils", extras = ["allauth", "s3-storage"] },
- { name = "django-s3-file-field", extras = ["s3"] },
- { name = "django-storages", extras = ["s3"] },
- { name = "django-stubs-ext" },
- { name = "djangorestframework", specifier = "<3.15.0" },
- { name = "drf-extensions" },
- { name = "drf-yasg" },
- { name = "fsspec", extras = ["http"] },
- { name = "gunicorn" },
- { name = "ipython", marker = "extra == 'development'" },
- { name = "jsonschema" },
- { name = "more-itertools" },
- { name = "psycopg", extras = ["binary"] },
- { name = "pyyaml" },
- { name = "requests" },
- { name = "rich" },
- { name = "sentry-sdk", extras = ["celery", "django", "pure-eval"] },
- { name = "tqdm" },
- { name = "watchdog", marker = "extra == 'development'" },
- { name = "werkzeug", marker = "extra == 'development'" },
- { name = "whitenoise", extras = ["brotli"] },
- { name = "zarr-checksum" },
-]
-provides-extras = ["development"]
+ { name = "django", extras = ["argon2"], specifier = "==5.2.7" },
+ { name = "django-allauth", specifier = "==65.12.0" },
+ { name = "django-auth-style", specifier = "==0.12.0" },
+ { name = "django-browser-reload", marker = "extra == 'development'", specifier = "==1.21.0" },
+ { name = "django-click", specifier = "==2.4.1" },
+ { name = "django-cors-headers", specifier = "==4.9.0" },
+ { name = "django-debug-toolbar", marker = "extra == 'development'", specifier = "==6.0.0" },
+ { name = "django-environ", specifier = "==0.12.1" },
+ { name = "django-extensions", specifier = "==4.1" },
+ { name = "django-filter", specifier = "==25.2" },
+ { name = "django-guardian", specifier = "==3.2.0" },
+ { name = "django-oauth-toolkit", specifier = "==3.1.0" },
+ { name = "django-resonant-settings", extras = ["allauth", "celery"], specifier = "==0.48.1" },
+ { name = "django-resonant-utils", extras = ["allauth", "s3-storage"], specifier = "==0.16.0" },
+ { name = "django-s3-file-field", extras = ["s3"], specifier = "==1.1.0" },
+ { name = "django-storages", extras = ["s3"], specifier = "==1.14.6" },
+ { name = "django-stubs-ext", specifier = "==5.2.7" },
+ { name = "djangorestframework", specifier = "==3.14.0" },
+ { name = "drf-extensions", specifier = "==0.8.0" },
+ { name = "drf-yasg", specifier = "==1.21.11" },
+ { name = "fsspec", extras = ["http"], specifier = "==2025.9.0" },
+ { name = "gunicorn", specifier = "==23.0.0" },
+ { name = "ipython", marker = "extra == 'development'", specifier = "==9.6.0" },
+ { name = "jsonschema", specifier = "==4.25.1" },
+ { name = "more-itertools", specifier = "==10.8.0" },
+ { name = "psycopg", extras = ["binary"], specifier = "==3.2.10" },
+ { name = "pyyaml", specifier = "==6.0.3" },
+ { name = "requests", specifier = "==2.32.5" },
+ { name = "rich", specifier = "==14.2.0" },
+ { name = "sentry-sdk", extras = ["celery", "django", "pure-eval"], specifier = "==2.41.0" },
+ { name = "tqdm", specifier = "==4.67.1" },
+ { name = "watchdog", marker = "extra == 'development'", specifier = "==6.0.0" },
+ { name = "werkzeug", marker = "extra == 'development'", specifier = "==3.1.3" },
+ { name = "whitenoise", extras = ["brotli"], specifier = "==6.11.0" },
+ { name = "zarr-checksum", specifier = "==0.4.7" },
+]
+provides-extras = ["cli", "development"]
[package.metadata.requires-dev]
dev = [
{ name = "dandiapi", extras = ["development"] },
- { name = "pre-commit" },
- { name = "tox" },
- { name = "tox-uv" },
+ { name = "pre-commit", specifier = "==4.3.0" },
+ { name = "tox", specifier = "==4.31.0" },
+ { name = "tox-uv", specifier = "==1.29.0" },
]
-lint = [{ name = "ruff" }]
+lint = [{ name = "ruff", specifier = "==0.14.0" }]
test = [
- { name = "djangorestframework-yaml" },
- { name = "factory-boy" },
- { name = "faker" },
- { name = "freezegun" },
- { name = "pytest" },
- { name = "pytest-cov" },
- { name = "pytest-django" },
- { name = "pytest-factoryboy" },
- { name = "pytest-memray" },
- { name = "pytest-mock" },
- { name = "pytest-random-order" },
- { name = "pytest-repeat" },
+ { name = "djangorestframework-yaml", specifier = "==2.0.0" },
+ { name = "factory-boy", specifier = "==3.3.3" },
+ { name = "faker", specifier = "==37.11.0" },
+ { name = "freezegun", specifier = "==1.5.5" },
+ { name = "pytest", specifier = "==8.4.2" },
+ { name = "pytest-cov", specifier = "==7.0.0" },
+ { name = "pytest-django", specifier = "==4.11.1" },
+ { name = "pytest-factoryboy", specifier = "==2.8.1" },
+ { name = "pytest-memray", specifier = "==1.8.0" },
+ { name = "pytest-mock", specifier = "==3.15.1" },
+ { name = "pytest-random-order", specifier = "==1.2.0" },
+ { name = "pytest-repeat", specifier = "==0.9.4" },
]
type = [
- { name = "boto3-stubs", extras = ["s3"] },
- { name = "celery-types" },
- { name = "django-stubs", extras = ["compatible-mypy"] },
- { name = "djangorestframework-stubs", extras = ["compatible-mypy"] },
- { name = "mypy" },
+ { name = "boto3-stubs", extras = ["s3"], specifier = "==1.40.51" },
+ { name = "celery-types", specifier = "==0.23.0" },
+ { name = "django-stubs", extras = ["compatible-mypy"], specifier = "==5.2.7" },
+ { name = "djangorestframework-stubs", extras = ["compatible-mypy"], specifier = "==3.16.4" },
+ { name = "mypy", specifier = "==1.18.2" },
]
[[package]]
@@ -859,6 +904,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" },
]
+[[package]]
+name = "deprecated"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "wrapt" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/49/85/12f0a49a7c4ffb70572b6c2ef13c90c88fd190debda93b23f026b25f9634/deprecated-1.3.1.tar.gz", hash = "sha256:b1b50e0ff0c1fddaa5708a2c6b0a6588bb09b892825ab2b214ac9ea9d92a5223", size = 2932523, upload-time = "2025-10-30T08:19:02.757Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/84/d0/205d54408c08b13550c733c4b85429e7ead111c7f0014309637425520a9a/deprecated-1.3.1-py2.py3-none-any.whl", hash = "sha256:597bfef186b6f60181535a29fbe44865ce137a5079f295b479886c82729d5f3f", size = 11298, upload-time = "2025-10-30T08:19:00.758Z" },
+]
+
[[package]]
name = "distlib"
version = "0.4.0"
@@ -962,11 +1019,11 @@ wheels = [
[[package]]
name = "django-environ"
-version = "0.12.0"
+version = "0.12.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/d6/04/65d2521842c42f4716225f20d8443a50804920606aec018188bbee30a6b0/django_environ-0.12.0.tar.gz", hash = "sha256:227dc891453dd5bde769c3449cf4a74b6f2ee8f7ab2361c93a07068f4179041a", size = 56804, upload-time = "2025-01-13T17:03:37.74Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/d4/3c/b2de27581c28929e3b33c5797e3d075c93541b4a8499ddc84dfd659d550f/django_environ-0.12.1.tar.gz", hash = "sha256:22859c6e905ab7637fa3348d1787543bb4492f38d761104a3ce0519b7b752845", size = 58257, upload-time = "2026-02-14T01:19:50.733Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/83/b3/0a3bec4ecbfee960f39b1842c2f91e4754251e0a6ed443db9fe3f666ba8f/django_environ-0.12.0-py2.py3-none-any.whl", hash = "sha256:92fb346a158abda07ffe6eb23135ce92843af06ecf8753f43adf9d2366dcc0ca", size = 19957, upload-time = "2025-01-13T17:03:32.918Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/1c/a6c55b856cb2c5824ee2fe5e27d6f54909ac7c228672b359ecbca99a6b41/django_environ-0.12.1-py2.py3-none-any.whl", hash = "sha256:064ba2d5082f833e6d7fe4def4928bde1eedc0248a417575da7db147aeec1c20", size = 20035, upload-time = "2026-02-14T01:19:48.683Z" },
]
[[package]]
@@ -1022,15 +1079,15 @@ wheels = [
[[package]]
name = "django-resonant-settings"
-version = "0.47.1"
+version = "0.48.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
{ name = "django-environ" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/07/e2/0961283ccaf797307f3671a7ff3965b5a54d816ff86c9091713cdcfde562/django_resonant_settings-0.47.1.tar.gz", hash = "sha256:3d58bed8d0595806a42007ef63f58348523d95699e5811068ca3337483ef5843", size = 19179, upload-time = "2026-02-26T15:46:42.839Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/93/36/70d9e2441a204e138c50c97b7791efa8e8bc15e17dfea2c2413733d2e576/django_resonant_settings-0.48.1.tar.gz", hash = "sha256:c101ccc60e6922e875140eeb3c2f089aac2bf0ebca63c512f826f91286d16983", size = 19231, upload-time = "2026-03-06T05:01:10.797Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/da/7d/a5f08da9e00e626b26beebcb94c5adfa26f78f54c1c9c3b61b8654ae5f02/django_resonant_settings-0.47.1-py3-none-any.whl", hash = "sha256:c96756aeac75248eca14b580228c6c41e2e6186030dbc47723cdb1b959f8a4ef", size = 26093, upload-time = "2026-02-26T15:46:41.69Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/f2/15b8afe28ed7b76e8e7f7d6bac8b49cc977691142659d5468671c0889536/django_resonant_settings-0.48.1-py3-none-any.whl", hash = "sha256:01e494132d05828c4a79b54d1e5013052b4e40cc034e7dd52cf8b4c93a57e4e7", size = 26102, upload-time = "2026-03-06T05:01:09.754Z" },
]
[package.optional-dependencies]
@@ -1471,6 +1528,23 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d2/e4/a5c84425feece1383ede342086720f8eba4a67e6afc2e4f990d2ce1d7e94/hdmf-4.1.0-py3-none-any.whl", hash = "sha256:d0cffd8e573d77368892d20351ecba07142a8a21b75c7665d732748132d7a696", size = 336653, upload-time = "2025-05-28T19:02:09.808Z" },
]
+[[package]]
+name = "hdmf-zarr"
+version = "0.12.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "hdmf" },
+ { name = "numcodecs" },
+ { name = "numpy" },
+ { name = "pynwb" },
+ { name = "threadpoolctl" },
+ { name = "zarr" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/9e/56/707bafae46727e0d69030fac436b96fb4ea8fefc693e661474ed45d12987/hdmf_zarr-0.12.0.tar.gz", hash = "sha256:9fa413fcddfc12e825b99f06ebdbc35439c6fad9f00a44936961b9ffd684e0c0", size = 3106640, upload-time = "2025-10-08T18:27:38.921Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/96/74/eeff5039149201bead00c27fab2ddf071899307bd578c3eabcd069ba4eba/hdmf_zarr-0.12.0-py3-none-any.whl", hash = "sha256:aaf866122799f547b9594f54fe906e2ffc4e8b9fe1928bf15a037dfcc864c98b", size = 33787, upload-time = "2025-10-08T18:27:37.44Z" },
+]
+
[[package]]
name = "humanize"
version = "4.13.0"
@@ -1516,6 +1590,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" },
]
+[[package]]
+name = "interleave"
+version = "0.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/cb/73/f06bcda00889d164ee1918126381f2d5e0030a6deaf80c9887e84ba18e31/interleave-0.3.0.tar.gz", hash = "sha256:4c4595e05c5c3286d306db7459972bada9a38088fb8649c1199782c8e4a60a32", size = 15689, upload-time = "2025-01-28T19:48:04.286Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/2b/13b5b2e418bc77574b7215c26be862f72d7850713116641c4ad56add61fd/interleave-0.3.0-py3-none-any.whl", hash = "sha256:09d772693b958c0cbb11e3cd8a6b726c6995c7e12b0530a10ae31a943b458c39", size = 11847, upload-time = "2025-01-28T19:48:03.081Z" },
+]
+
[[package]]
name = "ipython"
version = "9.6.0"
@@ -1549,6 +1632,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" },
]
+[[package]]
+name = "isodate"
+version = "0.7.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/54/4d/e940025e2ce31a8ce1202635910747e5a87cc3a6a6bb2d00973375014749/isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6", size = 29705, upload-time = "2024-10-08T23:04:11.5Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320, upload-time = "2024-10-08T23:04:09.501Z" },
+]
+
[[package]]
name = "isoduration"
version = "20.11.0"
@@ -1899,6 +1991,37 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/aa/d5/ecfa0a06ab0f0bd060a5908edc839d81c8f37da671a69d19cf9f5773595e/memray-1.18.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:45c3ac6152915df66ff7df4602a82171b981efcfba89b132458808cd47a57f7f", size = 10258751, upload-time = "2025-08-08T19:47:53.955Z" },
]
+[[package]]
+name = "ml-dtypes"
+version = "0.5.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/0e/4a/c27b42ed9b1c7d13d9ba8b6905dece787d6259152f2309338aed29b2447b/ml_dtypes-0.5.4.tar.gz", hash = "sha256:8ab06a50fb9bf9666dd0fe5dfb4676fa2b0ac0f31ecff72a6c3af8e22c063453", size = 692314, upload-time = "2025-11-17T22:32:31.031Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c760d85a2f82e2bed75867079188c9d18dae2ee77c25a54d60e9cc79be1bc48", size = 676888, upload-time = "2025-11-17T22:31:56.907Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce756d3a10d0c4067172804c9cc276ba9cc0ff47af9078ad439b075d1abdc29b", size = 5036993, upload-time = "2025-11-17T22:31:58.497Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:533ce891ba774eabf607172254f2e7260ba5f57bdd64030c9a4fcfbd99815d0d", size = 5010956, upload-time = "2025-11-17T22:31:59.931Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/8b/200088c6859d8221454825959df35b5244fa9bdf263fd0249ac5fb75e281/ml_dtypes-0.5.4-cp313-cp313-win_amd64.whl", hash = "sha256:f21c9219ef48ca5ee78402d5cc831bd58ea27ce89beda894428bc67a52da5328", size = 212224, upload-time = "2025-11-17T22:32:01.349Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/75/dfc3775cb36367816e678f69a7843f6f03bd4e2bcd79941e01ea960a068e/ml_dtypes-0.5.4-cp313-cp313-win_arm64.whl", hash = "sha256:35f29491a3e478407f7047b8a4834e4640a77d2737e0b294d049746507af5175", size = 160798, upload-time = "2025-11-17T22:32:02.864Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/74/e9ddb35fd1dd43b1106c20ced3f53c2e8e7fc7598c15638e9f80677f81d4/ml_dtypes-0.5.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:304ad47faa395415b9ccbcc06a0350800bc50eda70f0e45326796e27c62f18b6", size = 702083, upload-time = "2025-11-17T22:32:04.08Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f5/667060b0aed1aa63166b22897fdf16dca9eb704e6b4bbf86848d5a181aa7/ml_dtypes-0.5.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a0df4223b514d799b8a1629c65ddc351b3efa833ccf7f8ea0cf654a61d1e35d", size = 5354111, upload-time = "2025-11-17T22:32:05.546Z" },
+ { url = "https://files.pythonhosted.org/packages/40/49/0f8c498a28c0efa5f5c95a9e374c83ec1385ca41d0e85e7cf40e5d519a21/ml_dtypes-0.5.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:531eff30e4d368cb6255bc2328d070e35836aa4f282a0fb5f3a0cd7260257298", size = 5366453, upload-time = "2025-11-17T22:32:07.115Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/27/12607423d0a9c6bbbcc780ad19f1f6baa2b68b18ce4bddcdc122c4c68dc9/ml_dtypes-0.5.4-cp313-cp313t-win_amd64.whl", hash = "sha256:cb73dccfc991691c444acc8c0012bee8f2470da826a92e3a20bb333b1a7894e6", size = 225612, upload-time = "2025-11-17T22:32:08.615Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/80/5a5929e92c72936d5b19872c5fb8fc09327c1da67b3b68c6a13139e77e20/ml_dtypes-0.5.4-cp313-cp313t-win_arm64.whl", hash = "sha256:3bbbe120b915090d9dd1375e4684dd17a20a2491ef25d640a908281da85e73f1", size = 164145, upload-time = "2025-11-17T22:32:09.782Z" },
+ { url = "https://files.pythonhosted.org/packages/72/4e/1339dc6e2557a344f5ba5590872e80346f76f6cb2ac3dd16e4666e88818c/ml_dtypes-0.5.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2b857d3af6ac0d39db1de7c706e69c7f9791627209c3d6dedbfca8c7e5faec22", size = 673781, upload-time = "2025-11-17T22:32:11.364Z" },
+ { url = "https://files.pythonhosted.org/packages/04/f9/067b84365c7e83bda15bba2b06c6ca250ce27b20630b1128c435fb7a09aa/ml_dtypes-0.5.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:805cef3a38f4eafae3a5bf9ebdcdb741d0bcfd9e1bd90eb54abd24f928cd2465", size = 5036145, upload-time = "2025-11-17T22:32:12.783Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/bb/82c7dcf38070b46172a517e2334e665c5bf374a262f99a283ea454bece7c/ml_dtypes-0.5.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14a4fd3228af936461db66faccef6e4f41c1d82fcc30e9f8d58a08916b1d811f", size = 5010230, upload-time = "2025-11-17T22:32:14.38Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/93/2bfed22d2498c468f6bcd0d9f56b033eaa19f33320389314c19ef6766413/ml_dtypes-0.5.4-cp314-cp314-win_amd64.whl", hash = "sha256:8c6a2dcebd6f3903e05d51960a8058d6e131fe69f952a5397e5dbabc841b6d56", size = 221032, upload-time = "2025-11-17T22:32:15.763Z" },
+ { url = "https://files.pythonhosted.org/packages/76/a3/9c912fe6ea747bb10fe2f8f54d027eb265db05dfb0c6335e3e063e74e6e8/ml_dtypes-0.5.4-cp314-cp314-win_arm64.whl", hash = "sha256:5a0f68ca8fd8d16583dfa7793973feb86f2fbb56ce3966daf9c9f748f52a2049", size = 163353, upload-time = "2025-11-17T22:32:16.932Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/02/48aa7d84cc30ab4ee37624a2fd98c56c02326785750cd212bc0826c2f15b/ml_dtypes-0.5.4-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:bfc534409c5d4b0bf945af29e5d0ab075eae9eecbb549ff8a29280db822f34f9", size = 702085, upload-time = "2025-11-17T22:32:18.175Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/e7/85cb99fe80a7a5513253ec7faa88a65306be071163485e9a626fce1b6e84/ml_dtypes-0.5.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2314892cdc3fcf05e373d76d72aaa15fda9fb98625effa73c1d646f331fcecb7", size = 5355358, upload-time = "2025-11-17T22:32:19.7Z" },
+ { url = "https://files.pythonhosted.org/packages/79/2b/a826ba18d2179a56e144aef69e57fb2ab7c464ef0b2111940ee8a3a223a2/ml_dtypes-0.5.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d2ffd05a2575b1519dc928c0b93c06339eb67173ff53acb00724502cda231cf", size = 5366332, upload-time = "2025-11-17T22:32:21.193Z" },
+ { url = "https://files.pythonhosted.org/packages/84/44/f4d18446eacb20ea11e82f133ea8f86e2bf2891785b67d9da8d0ab0ef525/ml_dtypes-0.5.4-cp314-cp314t-win_amd64.whl", hash = "sha256:4381fe2f2452a2d7589689693d3162e876b3ddb0a832cde7a414f8e1adf7eab1", size = 236612, upload-time = "2025-11-17T22:32:22.579Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/3f/3d42e9a78fe5edf792a83c074b13b9b770092a4fbf3462872f4303135f09/ml_dtypes-0.5.4-cp314-cp314t-win_arm64.whl", hash = "sha256:11942cbf2cf92157db91e5022633c0d9474d4dfd813a909383bd23ce828a4b7d", size = 168825, upload-time = "2025-11-17T22:32:23.766Z" },
+]
+
[[package]]
name = "more-itertools"
version = "10.8.0"
@@ -2033,6 +2156,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
]
+[[package]]
+name = "natsort"
+version = "8.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575, upload-time = "2023-06-20T04:17:19.925Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268, upload-time = "2023-06-20T04:17:17.522Z" },
+]
+
[[package]]
name = "nodeenv"
version = "1.9.1"
@@ -2042,6 +2174,22 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" },
]
+[[package]]
+name = "numcodecs"
+version = "0.15.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "deprecated" },
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/63/fc/bb532969eb8236984ba65e4f0079a7da885b8ac0ce1f0835decbb3938a62/numcodecs-0.15.1.tar.gz", hash = "sha256:eeed77e4d6636641a2cc605fbc6078c7a8f2cc40f3dfa2b3f61e52e6091b04ff", size = 6267275, upload-time = "2025-02-10T10:23:33.254Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/78/57/acbc54b3419e5be65015e47177c76c0a73e037fd3ae2cde5808169194d4d/numcodecs-0.15.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3d82b70500cf61e8d115faa0d0a76be6ecdc24a16477ee3279d711699ad85f3", size = 1688220, upload-time = "2025-02-10T10:23:23.79Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/56/9863fa6dc679f40a31bea5e9713ee5507a31dcd3ee82ea4b1a9268ce52e8/numcodecs-0.15.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1d471a1829ce52d3f365053a2bd1379e32e369517557c4027ddf5ac0d99c591e", size = 1180294, upload-time = "2025-02-10T10:23:25.533Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/91/d96999b41e3146b6c0ce6bddc5ad85803cb4d743c95394562c2a4bb8cded/numcodecs-0.15.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1dfdea4a67108205edfce99c1cb6cd621343bc7abb7e16a041c966776920e7de", size = 8834323, upload-time = "2025-02-10T10:23:27.46Z" },
+ { url = "https://files.pythonhosted.org/packages/c3/32/233e5ede6568bdb044e6f99aaa9fa39827ff3109c6487fc137315f733586/numcodecs-0.15.1-cp313-cp313-win_amd64.whl", hash = "sha256:a4f7bdb26f1b34423cb56d48e75821223be38040907c9b5954eeb7463e7eb03c", size = 831955, upload-time = "2025-02-10T10:23:30.601Z" },
+]
+
[[package]]
name = "numpy"
version = "2.3.3"
@@ -2094,6 +2242,29 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/06/b9/33bba5ff6fb679aa0b1f8a07e853f002a6b04b9394db3069a1270a7784ca/numpy-2.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:78c9f6560dc7e6b3990e32df7ea1a50bbd0e2a111e05209963f5ddcab7073b0b", size = 10545953, upload-time = "2025-09-09T15:58:40.576Z" },
]
+[[package]]
+name = "nwbinspector"
+version = "0.6.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "aiohttp" },
+ { name = "click" },
+ { name = "fsspec" },
+ { name = "hdmf-zarr" },
+ { name = "isodate" },
+ { name = "jsonschema" },
+ { name = "natsort" },
+ { name = "packaging" },
+ { name = "pynwb" },
+ { name = "pyyaml" },
+ { name = "requests" },
+ { name = "tqdm" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/45/23/d50bb1dfef6eff622dff58ec64077f6b51ce9191ee4f093881b1394a6ddd/nwbinspector-0.6.5.tar.gz", hash = "sha256:93023bcd72c73add18644211fb26f6b005e012ec9c6a8b3f53e136ddeb58af16", size = 591999, upload-time = "2025-07-25T18:05:22.529Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8f/e7/01fd709430ee0178db611f1db9652bfca71599799c602101e13ce5bdeedc/nwbinspector-0.6.5-py3-none-any.whl", hash = "sha256:f0219a9b06482b07415e7beebddf3ae7d97371cc178e7bc05c7d3edf7285d135", size = 64409, upload-time = "2025-07-25T18:05:21.4Z" },
+]
+
[[package]]
name = "oauthlib"
version = "3.3.1"
@@ -3003,6 +3174,32 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" },
]
+[[package]]
+name = "tensorstore"
+version = "0.1.81"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "ml-dtypes" },
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/43/f6/e2403fc05b97ba74ad408a98a42c288e6e1b8eacc23780c153b0e5166179/tensorstore-0.1.81.tar.gz", hash = "sha256:687546192ea6f6c8ae28d18f13103336f68017d928b9f5a00325e9b0548d9c25", size = 7120819, upload-time = "2026-02-06T18:56:12.535Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/06/c0/32f7d52bfcf1728f557cccb17ac85f57bcc3fa92f4034368d6e7d7d06406/tensorstore-0.1.81-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:7bb563ad4d4d6c4748d9fe4f01f639ddf4ffef83ac180fc3b6d73f46ad854e62", size = 16521316, upload-time = "2026-02-06T18:55:39.557Z" },
+ { url = "https://files.pythonhosted.org/packages/38/b9/06ffc44e38ca18aeb3973f6b709d4d2102e17a8d700c7c3e2af3f2830722/tensorstore-0.1.81-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2ff7e6c457596cf21f31c690e451fe634ac804fc98ff8131188e99d5ef7d29bc", size = 14543212, upload-time = "2026-02-06T18:55:42.246Z" },
+ { url = "https://files.pythonhosted.org/packages/00/01/3c27962f7258ad0bb552c3cd324fa2e01f746c8b6e81bd25d468f72204e8/tensorstore-0.1.81-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b218a6fe09c72c002f2c6480fc58b78cdbba8bb9c6f3a0d7dd1f70625cb37995", size = 19044489, upload-time = "2026-02-06T18:55:44.957Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/ea/fe0f14a1da96d6e0aa6c24d6c31f3ce4b203f8e8a1a2e359489e52b33400/tensorstore-0.1.81-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f33e7c11035c14dad01aeba012051643110cbb95c239e512106fe1be692c98b6", size = 21052658, upload-time = "2026-02-06T18:55:47.138Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/e2/cc189d799982f02c200b22405c4d3f28845df6321de2ac3a35ae087758ed/tensorstore-0.1.81-cp313-cp313-win_amd64.whl", hash = "sha256:b55126bcf084cc5fe0151bf465f3a5dedb5b5da0133d01227f75d0e71f9cfae5", size = 13226848, upload-time = "2026-02-06T18:55:49.631Z" },
+ { url = "https://files.pythonhosted.org/packages/89/b0/0ca436391f832fad365977623f3c08c4fbbf553fd9a112604aa106646654/tensorstore-0.1.81-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a48c23e4df50681d8f4f365b08a0beb114ab210accbde9f34d37fd7b45c31005", size = 16525537, upload-time = "2026-02-06T18:55:51.708Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/02/c10052b86cf8d47b4cf41e5f139b4003c69bb69e506759b0eb87b873d213/tensorstore-0.1.81-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0be0ce646263820f3d4c9ba738d8e9be7da241cbe093ca2fd02e25023344347c", size = 14547490, upload-time = "2026-02-06T18:55:53.899Z" },
+ { url = "https://files.pythonhosted.org/packages/01/d1/bd86c46367624522967e896ca45d77ba9085de3f15081fdad6576ba70aa9/tensorstore-0.1.81-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93996e756dce82589f5a19e27b4e7c0b5b40221a7e41ddce46dc13d378dbd157", size = 19050938, upload-time = "2026-02-06T18:55:56.123Z" },
+ { url = "https://files.pythonhosted.org/packages/11/a2/59a8e9a33cd9e17461f918bda4a20712ed3c51c52e0e42b2f673441bc90d/tensorstore-0.1.81-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:444c088919a739c20ca1f87935d72de4fd87605eb2c0f093b8d49251b7884aef", size = 21055275, upload-time = "2026-02-06T18:55:58.259Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/ec/2988f210729b523975b1bee030cabd64b256943c08463331598f1e03bd4f/tensorstore-0.1.81-cp314-cp314-win_amd64.whl", hash = "sha256:f7aa0a3a470c4d832faff7d77dd688b1d352b718d110c95ceba54ec637ca3ffa", size = 13614713, upload-time = "2026-02-06T18:56:00.291Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/5d/60e990df3f1dc57c33644375a0eccb906a79fd8a5e2d81238f856c65ad7f/tensorstore-0.1.81-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:6c36d8a827120aa15e50ec5c36dd7e73978d86ba4f46d073fb648d8dda3948e9", size = 16605091, upload-time = "2026-02-06T18:56:02.807Z" },
+ { url = "https://files.pythonhosted.org/packages/85/22/f599576815227735d3e34f86f05a8b39d8b15fd979d0029383ebae23978d/tensorstore-0.1.81-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c31d831707c4ff3c6ecdcba129f7c39e982572837b2f93e02ccb83fc8581bca", size = 14631573, upload-time = "2026-02-06T18:56:04.892Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/76/b5d0b424b7af057a3d4de3f312eba9ddf8a3c750a766b42e0b7f6c2ebef0/tensorstore-0.1.81-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fba383f108d7450bf9a03487ac7fa3bb2c3080c91cee9d2da3bb217b560846b", size = 19065251, upload-time = "2026-02-06T18:56:06.972Z" },
+ { url = "https://files.pythonhosted.org/packages/54/6c/0f113eae73b1e8eb2f712cf5f1efd269452f0f0045158fae43ce7b4701b4/tensorstore-0.1.81-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f88c52f592e2982682045199cabf360462146749d48b7be2969cd640e877c6c3", size = 21066488, upload-time = "2026-02-06T18:56:10.236Z" },
+]
+
[[package]]
name = "textual"
version = "6.3.0"
@@ -3019,6 +3216,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ff/2a/bca677b0b05ee77b4105f73db0d8ef231a9f1db154d69388abd5c73f9dcc/textual-6.3.0-py3-none-any.whl", hash = "sha256:ec908b4b008662e7670af4a3e7c773847066b0950b1c50126c72fa939b514c97", size = 711457, upload-time = "2025-10-11T11:16:59.754Z" },
]
+[[package]]
+name = "threadpoolctl"
+version = "3.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" },
+]
+
[[package]]
name = "tox"
version = "4.31.0"
@@ -3302,6 +3508,51 @@ brotli = [
{ name = "brotli" },
]
+[[package]]
+name = "wrapt"
+version = "2.1.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f7/37/ae31f40bec90de2f88d9597d0b5281e23ffe85b893a47ca5d9c05c63a4f6/wrapt-2.1.1.tar.gz", hash = "sha256:5fdcb09bf6db023d88f312bd0767594b414655d58090fc1c46b3414415f67fac", size = 81329, upload-time = "2026-02-03T02:12:13.786Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f7/ca/3cf290212855b19af9fcc41b725b5620b32f470d6aad970c2593500817eb/wrapt-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ce9646e17fa7c3e2e7a87e696c7de66512c2b4f789a8db95c613588985a2e139", size = 61150, upload-time = "2026-02-03T02:12:50.575Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/33/5b8f89a82a9859ce82da4870c799ad11ce15648b6e1c820fec3e23f4a19f/wrapt-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:428cfc801925454395aa468ba7ddb3ed63dc0d881df7b81626cdd433b4e2b11b", size = 61743, upload-time = "2026-02-03T02:11:55.733Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/2f/60c51304fbdf47ce992d9eefa61fbd2c0e64feee60aaa439baf42ea6f40b/wrapt-2.1.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5797f65e4d58065a49088c3b32af5410751cd485e83ba89e5a45e2aa8905af98", size = 121341, upload-time = "2026-02-03T02:11:20.461Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/03/ce5256e66dd94e521ad5e753c78185c01b6eddbed3147be541f4d38c0cb7/wrapt-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a2db44a71202c5ae4bb5f27c6d3afbc5b23053f2e7e78aa29704541b5dad789", size = 122947, upload-time = "2026-02-03T02:11:33.596Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/ae/50ca8854b81b946a11a36fcd6ead32336e6db2c14b6e4a8b092b80741178/wrapt-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8d5350c3590af09c1703dd60ec78a7370c0186e11eaafb9dda025a30eee6492d", size = 121370, upload-time = "2026-02-03T02:11:09.886Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/d9/d6a7c654e0043319b4cc137a4caaf7aa16b46b51ee8df98d1060254705b7/wrapt-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d9b076411bed964e752c01b49fd224cc385f3a96f520c797d38412d70d08359", size = 120465, upload-time = "2026-02-03T02:11:37.592Z" },
+ { url = "https://files.pythonhosted.org/packages/55/90/65be41e40845d951f714b5a77e84f377a3787b1e8eee6555a680da6d0db5/wrapt-2.1.1-cp313-cp313-win32.whl", hash = "sha256:0bb7207130ce6486727baa85373503bf3334cc28016f6928a0fa7e19d7ecdc06", size = 58090, upload-time = "2026-02-03T02:12:53.342Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/66/6a09e0294c4fc8c26028a03a15191721c9271672467cc33e6617ee0d91d2/wrapt-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:cbfee35c711046b15147b0ae7db9b976f01c9520e6636d992cd9e69e5e2b03b1", size = 60341, upload-time = "2026-02-03T02:12:36.384Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f0/20ceb8b701e9a71555c87a5ddecbed76ec16742cf1e4b87bbaf26735f998/wrapt-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:7d2756061022aebbf57ba14af9c16e8044e055c22d38de7bf40d92b565ecd2b0", size = 58731, upload-time = "2026-02-03T02:12:01.328Z" },
+ { url = "https://files.pythonhosted.org/packages/80/b4/fe95beb8946700b3db371f6ce25115217e7075ca063663b8cca2888ba55c/wrapt-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4814a3e58bc6971e46baa910ecee69699110a2bf06c201e24277c65115a20c20", size = 62969, upload-time = "2026-02-03T02:11:51.245Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/89/477b0bdc784e3299edf69c279697372b8bd4c31d9c6966eae405442899df/wrapt-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:106c5123232ab9b9f4903692e1fa0bdc231510098f04c13c3081f8ad71c3d612", size = 63606, upload-time = "2026-02-03T02:12:02.64Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/55/9d0c1269ab76de87715b3b905df54dd25d55bbffd0b98696893eb613469f/wrapt-2.1.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1a40b83ff2535e6e56f190aff123821eea89a24c589f7af33413b9c19eb2c738", size = 152536, upload-time = "2026-02-03T02:11:24.492Z" },
+ { url = "https://files.pythonhosted.org/packages/44/18/2004766030462f79ad86efaa62000b5e39b1ff001dcce86650e1625f40ae/wrapt-2.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:789cea26e740d71cf1882e3a42bb29052bc4ada15770c90072cb47bf73fb3dbf", size = 158697, upload-time = "2026-02-03T02:12:32.214Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/bb/0a880fa0f35e94ee843df4ee4dd52a699c9263f36881311cfb412c09c3e5/wrapt-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ba49c14222d5e5c0ee394495a8655e991dc06cbca5398153aefa5ac08cd6ccd7", size = 155563, upload-time = "2026-02-03T02:11:49.737Z" },
+ { url = "https://files.pythonhosted.org/packages/42/ff/cd1b7c4846c8678fac359a6eb975dc7ab5bd606030adb22acc8b4a9f53f1/wrapt-2.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ac8cda531fe55be838a17c62c806824472bb962b3afa47ecbd59b27b78496f4e", size = 150161, upload-time = "2026-02-03T02:12:33.613Z" },
+ { url = "https://files.pythonhosted.org/packages/38/ec/67c90a7082f452964b4621e4890e9a490f1add23cdeb7483cc1706743291/wrapt-2.1.1-cp313-cp313t-win32.whl", hash = "sha256:b8af75fe20d381dd5bcc9db2e86a86d7fcfbf615383a7147b85da97c1182225b", size = 59783, upload-time = "2026-02-03T02:11:39.863Z" },
+ { url = "https://files.pythonhosted.org/packages/ec/08/466afe4855847d8febdfa2c57c87e991fc5820afbdef01a273683dfd15a0/wrapt-2.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:45c5631c9b6c792b78be2d7352129f776dd72c605be2c3a4e9be346be8376d83", size = 63082, upload-time = "2026-02-03T02:12:09.075Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/62/60b629463c28b15b1eeadb3a0691e17568622b12aa5bfa7ebe9b514bfbeb/wrapt-2.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:da815b9263947ac98d088b6414ac83507809a1d385e4632d9489867228d6d81c", size = 60251, upload-time = "2026-02-03T02:11:21.794Z" },
+ { url = "https://files.pythonhosted.org/packages/95/a0/1c2396e272f91efe6b16a6a8bce7ad53856c8f9ae4f34ceaa711d63ec9e1/wrapt-2.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9aa1765054245bb01a37f615503290d4e207e3fd59226e78341afb587e9c1236", size = 61311, upload-time = "2026-02-03T02:12:44.41Z" },
+ { url = "https://files.pythonhosted.org/packages/b0/9a/d2faba7e61072a7507b5722db63562fdb22f5a24e237d460d18755627f15/wrapt-2.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:feff14b63a6d86c1eee33a57f77573649f2550935981625be7ff3cb7342efe05", size = 61805, upload-time = "2026-02-03T02:11:59.905Z" },
+ { url = "https://files.pythonhosted.org/packages/db/56/073989deb4b5d7d6e7ea424476a4ae4bda02140f2dbeaafb14ba4864dd60/wrapt-2.1.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81fc5f22d5fcfdbabde96bb3f5379b9f4476d05c6d524d7259dc5dfb501d3281", size = 120308, upload-time = "2026-02-03T02:12:04.46Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/b6/84f37261295e38167a29eb82affaf1dc15948dc416925fe2091beee8e4ac/wrapt-2.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:951b228ecf66def855d22e006ab9a1fc12535111ae7db2ec576c728f8ddb39e8", size = 122688, upload-time = "2026-02-03T02:11:23.148Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/80/32db2eec6671f80c65b7ff175be61bc73d7f5223f6910b0c921bbc4bd11c/wrapt-2.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ddf582a95641b9a8c8bd643e83f34ecbbfe1b68bc3850093605e469ab680ae3", size = 121115, upload-time = "2026-02-03T02:12:39.068Z" },
+ { url = "https://files.pythonhosted.org/packages/49/ef/dcd00383df0cd696614127902153bf067971a5aabcd3c9dcb2d8ef354b2a/wrapt-2.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:fc5c500966bf48913f795f1984704e6d452ba2414207b15e1f8c339a059d5b16", size = 119484, upload-time = "2026-02-03T02:11:48.419Z" },
+ { url = "https://files.pythonhosted.org/packages/76/29/0630280cdd2bd8f86f35cb6854abee1c9d6d1a28a0c6b6417cd15d378325/wrapt-2.1.1-cp314-cp314-win32.whl", hash = "sha256:4aa4baadb1f94b71151b8e44a0c044f6af37396c3b8bcd474b78b49e2130a23b", size = 58514, upload-time = "2026-02-03T02:11:58.616Z" },
+ { url = "https://files.pythonhosted.org/packages/db/19/5bed84f9089ed2065f6aeda5dfc4f043743f642bc871454b261c3d7d322b/wrapt-2.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:860e9d3fd81816a9f4e40812f28be4439ab01f260603c749d14be3c0a1170d19", size = 60763, upload-time = "2026-02-03T02:12:24.553Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/cb/b967f2f9669e4249b4fe82e630d2a01bc6b9e362b9b12ed91bbe23ae8df4/wrapt-2.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:3c59e103017a2c1ea0ddf589cbefd63f91081d7ce9d491d69ff2512bb1157e23", size = 59051, upload-time = "2026-02-03T02:11:29.602Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/19/6fed62be29f97eb8a56aff236c3f960a4b4a86e8379dc7046a8005901a97/wrapt-2.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9fa7c7e1bee9278fc4f5dd8275bc8d25493281a8ec6c61959e37cc46acf02007", size = 63059, upload-time = "2026-02-03T02:12:06.368Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/1c/b757fd0adb53d91547ed8fad76ba14a5932d83dde4c994846a2804596378/wrapt-2.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:39c35e12e8215628984248bd9c8897ce0a474be2a773db207eb93414219d8469", size = 63618, upload-time = "2026-02-03T02:12:23.197Z" },
+ { url = "https://files.pythonhosted.org/packages/10/fe/e5ae17b1480957c7988d991b93df9f2425fc51f128cf88144d6a18d0eb12/wrapt-2.1.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:94ded4540cac9125eaa8ddf5f651a7ec0da6f5b9f248fe0347b597098f8ec14c", size = 152544, upload-time = "2026-02-03T02:11:43.915Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/cc/99aed210c6b547b8a6e4cb9d1425e4466727158a6aeb833aa7997e9e08dd/wrapt-2.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da0af328373f97ed9bdfea24549ac1b944096a5a71b30e41c9b8b53ab3eec04a", size = 158700, upload-time = "2026-02-03T02:12:30.684Z" },
+ { url = "https://files.pythonhosted.org/packages/81/0e/d442f745f4957944d5f8ad38bc3a96620bfff3562533b87e486e979f3d99/wrapt-2.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4ad839b55f0bf235f8e337ce060572d7a06592592f600f3a3029168e838469d3", size = 155561, upload-time = "2026-02-03T02:11:28.164Z" },
+ { url = "https://files.pythonhosted.org/packages/51/ac/9891816280e0018c48f8dfd61b136af7b0dcb4a088895db2531acde5631b/wrapt-2.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0d89c49356e5e2a50fa86b40e0510082abcd0530f926cbd71cf25bee6b9d82d7", size = 150188, upload-time = "2026-02-03T02:11:57.053Z" },
+ { url = "https://files.pythonhosted.org/packages/24/98/e2f273b6d70d41f98d0739aa9a269d0b633684a5fb17b9229709375748d4/wrapt-2.1.1-cp314-cp314t-win32.whl", hash = "sha256:f4c7dd22cf7f36aafe772f3d88656559205c3af1b7900adfccb70edeb0d2abc4", size = 60425, upload-time = "2026-02-03T02:11:35.007Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/06/b500bfc38a4f82d89f34a13069e748c82c5430d365d9e6b75afb3ab74457/wrapt-2.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f76bc12c583ab01e73ba0ea585465a41e48d968f6d1311b4daec4f8654e356e3", size = 63855, upload-time = "2026-02-03T02:12:15.47Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/cc/5f6193c32166faee1d2a613f278608e6f3b95b96589d020f0088459c46c9/wrapt-2.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7ea74fc0bec172f1ae5f3505b6655c541786a5cabe4bbc0d9723a56ac32eb9b9", size = 60443, upload-time = "2026-02-03T02:11:30.869Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/da/5a086bf4c22a41995312db104ec2ffeee2cf6accca9faaee5315c790377d/wrapt-2.1.1-py3-none-any.whl", hash = "sha256:3b0f4629eb954394a3d7c7a1c8cca25f0b07cefe6aa8545e862e9778152de5b7", size = 43886, upload-time = "2026-02-03T02:11:45.048Z" },
+]
+
[[package]]
name = "yarl"
version = "1.22.0"
@@ -3380,6 +3631,21 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" },
]
+[[package]]
+name = "zarr"
+version = "2.18.7"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "asciitree" },
+ { name = "fasteners", marker = "sys_platform != 'emscripten'" },
+ { name = "numcodecs" },
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/da/1d/01cf9e3ab2d85190278efc3fca9f68563de35ae30ee59e7640e3af98abe3/zarr-2.18.7.tar.gz", hash = "sha256:b2b8f66f14dac4af66b180d2338819981b981f70e196c9a66e6bfaa9e59572f5", size = 3604558, upload-time = "2025-04-09T07:59:28.482Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5e/d8/9ffd8c237b3559945bb52103cf0eed64ea098f7b7f573f8d2962ef27b4b2/zarr-2.18.7-py3-none-any.whl", hash = "sha256:ac3dc4033e9ae4e9d7b5e27c97ea3eaf1003cc0a07f010bd83d5134bf8c4b223", size = 211273, upload-time = "2025-04-09T07:59:27.039Z" },
+]
+
[[package]]
name = "zarr-checksum"
version = "0.4.7"
diff --git a/web/package-lock.json b/web/package-lock.json
index 6ee446c50..8e0a6cfb5 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -12,7 +12,7 @@
"@koumoul/vjsf": "^3.12.0",
"@mdi/font": "7.4.47",
"@resonant/oauth-client": "^1.0.3",
- "@sentry/vue": "^9.10.0",
+ "@sentry/vue": "^10.0.0",
"axios": "^1.8.1",
"core-js": "^3.41.0",
"dompurify": "^3.2.3",
@@ -33,7 +33,7 @@
"@tsconfig/node22": "^22.0.0",
"@types/js-yaml": "^4.0.9",
"@types/lodash": "^4.17.16",
- "@types/node": "^22.9.0",
+ "@types/node": "^24.0.0",
"@vitejs/plugin-vue": "^5.1.4",
"@vue/eslint-config-typescript": "^14.1.3",
"@vue/tsconfig": "^0.5.1",
@@ -804,7 +804,6 @@
"resolved": "https://registry.npmjs.org/@json-layout/vocabulary/-/vocabulary-2.1.0.tgz",
"integrity": "sha512-5B6jMvxGU9+jONoY7tDVfWuPT9vjyPwz4YHWCtysNwDKaWHnMCv/1JdHH1EcyQXMh4BlXGsSLKmOKo9OtG+Uew==",
"license": "MIT",
- "peer": true,
"dependencies": {
"ajv": "^8.17.1",
"ajv-errors": "^3.0.0",
@@ -1488,97 +1487,101 @@
]
},
"node_modules/@sentry-internal/browser-utils": {
- "version": "9.10.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.10.0.tgz",
- "integrity": "sha512-AJDqCNG+bjDwiww80+0aWtLj6wCm+OrQ24IOwz3NXEAv0G6o2RpjQcfgYZ3Qo8u1fqwsNX1TfzVdA7ipDzyoiw==",
+ "version": "10.44.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.44.0.tgz",
+ "integrity": "sha512-z9xz3T/v+MnfHY6kdUCmOZI8CiAl3LlKYtGH2p3rAsrxhwX+BTnUp01VhMVnEZIDgUXNt3AhJac+4kcDIPu1Hg==",
"license": "MIT",
"dependencies": {
- "@sentry/core": "9.10.0"
+ "@sentry/core": "10.44.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/feedback": {
- "version": "9.10.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.10.0.tgz",
- "integrity": "sha512-C5VFKrIqrD+seM927wiqYmPlKkhijbIGIpQCLx53e4nxs2E9xc7aIb5zksFrpM+G0gAB6E12Cf54ATcxFMXd8A==",
+ "version": "10.44.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.44.0.tgz",
+ "integrity": "sha512-yNS2EGK1bNm8YUI+Orzpa7yr05Da+b1VEe/9x7dl7gTjw/+tfutoXlG6Y+iFZBB3gQ9QU+nxZAhU+KcxiPEURw==",
"license": "MIT",
"dependencies": {
- "@sentry/core": "9.10.0"
+ "@sentry/core": "10.44.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay": {
- "version": "9.10.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.10.0.tgz",
- "integrity": "sha512-OvVA7zMXkQ++p75sriICOINJCAscnnulDPuYGHn3SJgZdkHwQMMcTv+BN1q7SBz2xzxRriqW9/vKGZlGeS8rbw==",
+ "version": "10.44.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.44.0.tgz",
+ "integrity": "sha512-KDmoqBsRmkaoc+eKLR2CbScd2eBmLcw+1+D441lLttAO3WWhvYyCaYdu/HIGGUoybuSgt+IcpCJdi7hFuCvYqw==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/browser-utils": "9.10.0",
- "@sentry/core": "9.10.0"
+ "@sentry-internal/browser-utils": "10.44.0",
+ "@sentry/core": "10.44.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay-canvas": {
- "version": "9.10.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.10.0.tgz",
- "integrity": "sha512-DsM+v27w87ZFbGo0AmerS3DokbUGOo805GmAcDeZMekYe40TR7xXy5E4EJIY4v/da6aIlmo3CQcIGbcJ/QS9+g==",
+ "version": "10.44.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.44.0.tgz",
+ "integrity": "sha512-RA7XgYZWHY7M+vaHvuMxDFT51wCs4puS2smElM5oh+j3YqbFXY7P16fOCwIAGoyI4gVsj8aTeBgVqUmrmzhAXQ==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/replay": "9.10.0",
- "@sentry/core": "9.10.0"
+ "@sentry-internal/replay": "10.44.0",
+ "@sentry/core": "10.44.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/browser": {
- "version": "9.10.0",
- "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.10.0.tgz",
- "integrity": "sha512-q9WZ50uJLuWbtyk1MoCc7L3y9aokL+0wkWksbwjkJL3icRdDnKumJyP8nWCjHLyyeSSJhwtHDidajAP79JFW0Q==",
+ "version": "10.44.0",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.44.0.tgz",
+ "integrity": "sha512-UpMx5forbVKieNULma3gT2SsLYqsYT4nLXa6s1io/Y8BFej9sH2dD5ExA8TrkQThQwAWFI3qKsQzYnF+EX/Bfg==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/browser-utils": "9.10.0",
- "@sentry-internal/feedback": "9.10.0",
- "@sentry-internal/replay": "9.10.0",
- "@sentry-internal/replay-canvas": "9.10.0",
- "@sentry/core": "9.10.0"
+ "@sentry-internal/browser-utils": "10.44.0",
+ "@sentry-internal/feedback": "10.44.0",
+ "@sentry-internal/replay": "10.44.0",
+ "@sentry-internal/replay-canvas": "10.44.0",
+ "@sentry/core": "10.44.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/core": {
- "version": "9.10.0",
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.10.0.tgz",
- "integrity": "sha512-l3U/dOj9R2jcSLrSfPVkU7v6EUaEH7jgPYYyR+ug61oeSZ1/i/mgD2BpGk5FJd1e5mXCuNVmeFxirwCUZF3+ZA==",
+ "version": "10.44.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.44.0.tgz",
+ "integrity": "sha512-aa7CiDaNFZvHpqd97LJhuskolfJ/4IH5xyuVVLnv7l6B0v9KTwskPUxb0tH1ej3FxuzfH+i8iTiTFuqpfHS3QA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/vue": {
- "version": "9.10.0",
- "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-9.10.0.tgz",
- "integrity": "sha512-iyHRInfOjmuYSmcu1S1R9HaFi1k+VvTT/t1Of22FFxdsSzt6NTpXlrhPkmh+3ssct4kd9gx6jhpthOP8wM6GjQ==",
+ "version": "10.44.0",
+ "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-10.44.0.tgz",
+ "integrity": "sha512-XAjvUPhfqkEULt3kly4fSmwQ7fi9XuBWU8Hq9Fme3WN3Ti5q1lTqFBvxlpGeUDKzb2g/J9NVRq9G10m7d438Fg==",
"license": "MIT",
"dependencies": {
- "@sentry/browser": "9.10.0",
- "@sentry/core": "9.10.0"
+ "@sentry/browser": "10.44.0",
+ "@sentry/core": "10.44.0"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
+ "@tanstack/vue-router": "^1.64.0",
"pinia": "2.x || 3.x",
"vue": "2.x || 3.x"
},
"peerDependenciesMeta": {
+ "@tanstack/vue-router": {
+ "optional": true
+ },
"pinia": {
"optional": true
}
@@ -1634,14 +1637,13 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.13.4",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz",
- "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==",
+ "version": "24.12.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
+ "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"dependencies": {
- "undici-types": "~6.20.0"
+ "undici-types": "~7.16.0"
}
},
"node_modules/@types/sizzle": {
@@ -1699,7 +1701,6 @@
"integrity": "sha512-MFDaO9CYiard9j9VepMNa9MTcqVvSny2N4hkY6roquzj8pdCBRENhErrteaQuu7Yjn1ppk0v1/ZF9CG3KIlrTA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.24.0",
"@typescript-eslint/types": "8.24.0",
@@ -2262,7 +2263,6 @@
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2285,7 +2285,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -3363,7 +3362,6 @@
"integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -3424,7 +3422,6 @@
"integrity": "sha512-b/Y05HYmnB/32wqVcjxjHZzNpwxj1onBOvqW89W+V+XNG1dRuaFbNd3vT9CLbr2LXjEoq+3vn8DanWf7XU22Ug==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"globals": "^13.24.0",
@@ -5111,7 +5108,6 @@
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -5124,7 +5120,6 @@
"resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.1.tgz",
"integrity": "sha512-WXglsDzztOTH6IfcJ99ltYZin2mY8XZCXujkYWVIJlBjqsP6ST7zw+Aarh63E1cDVYeyUcPCxPHzJpEOmzB6Wg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@vue/devtools-api": "^7.7.2"
},
@@ -5510,7 +5505,6 @@
"integrity": "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/estree": "1.0.6"
},
@@ -5623,7 +5617,6 @@
"integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"chokidar": "^4.0.0",
"immutable": "^5.0.2",
@@ -5645,7 +5638,6 @@
"integrity": "sha512-0i+3h2Df/c71afluxC1SXqyyMmJlnKWfu9ZGdzwuKRM1OftEa2XM2myt5tR36CF3PanYrMjFKtRIj8PfSf838w==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@bufbuild/protobuf": "^2.0.0",
"buffer-builder": "^0.2.0",
@@ -6861,7 +6853,6 @@
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"devOptional": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -6901,9 +6892,9 @@
"license": "MIT"
},
"node_modules/undici-types": {
- "version": "6.20.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
- "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
"devOptional": true,
"license": "MIT"
},
@@ -7170,7 +7161,6 @@
"integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"postcss": "^8.5.3",
@@ -7260,7 +7250,6 @@
"integrity": "sha512-4wEAQtZaigPpwbFcZbrKpYwutOsWwWdeXn22B9XHzDPQNxVsKT+K9lKcXZnI5JESO1Iaql48S9rOk8RZZEt+Mw==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@vuetify/loader-shared": "^2.1.0",
"debug": "^4.3.3",
@@ -7294,7 +7283,6 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz",
"integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.13",
"@vue/compiler-sfc": "3.5.13",
@@ -7377,7 +7365,6 @@
"integrity": "sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@vue/devtools-api": "^6.6.4"
},
@@ -7434,7 +7421,6 @@
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.7.15.tgz",
"integrity": "sha512-kBZzwXI5EcAMiW5TRMgK1reXQd0K/PpUt+ekX4Alvm7n09uzJ1my1TLNbX1sQ8/0KYgoxOf17C8qOJzBGkT+PA==",
"license": "MIT",
- "peer": true,
"engines": {
"node": "^12.20 || >=14.13"
},
diff --git a/web/package.json b/web/package.json
index bce14a408..a18ebdde8 100644
--- a/web/package.json
+++ b/web/package.json
@@ -25,7 +25,7 @@
"@koumoul/vjsf": "^3.12.0",
"@mdi/font": "7.4.47",
"@resonant/oauth-client": "^1.0.3",
- "@sentry/vue": "^9.10.0",
+ "@sentry/vue": "^10.0.0",
"axios": "^1.8.1",
"core-js": "^3.41.0",
"dompurify": "^3.2.3",
@@ -46,7 +46,7 @@
"@tsconfig/node22": "^22.0.0",
"@types/js-yaml": "^4.0.9",
"@types/lodash": "^4.17.16",
- "@types/node": "^22.9.0",
+ "@types/node": "^24.0.0",
"@vitejs/plugin-vue": "^5.1.4",
"@vue/eslint-config-typescript": "^14.1.3",
"@vue/tsconfig": "^0.5.1",
diff --git a/web/src/components/AppBar/AppBar.vue b/web/src/components/AppBar/AppBar.vue
index 068db7e1d..b0ddfc6d3 100644
--- a/web/src/components/AppBar/AppBar.vue
+++ b/web/src/components/AppBar/AppBar.vue
@@ -157,7 +157,7 @@ import {
user,
} from '@/rest';
import {
- emberAboutUrl, emberDocumentationUrl, dandihubUrl
+ emberAboutUrl, emberDocumentationUrl, dandiBlogUrl, dandihubUrl
} from '@/utils/constants';
import UserMenu from '@/components/AppBar/UserMenu.vue';
import logo from '@/assets/ember-logo.png';
@@ -199,6 +199,11 @@ const navItems: NavigationItem[] = [
to: emberAboutUrl,
external: true,
},
+ {
+ text: 'Blog',
+ to: dandiBlogUrl,
+ external: true,
+ },
{
text: 'Documentation',
to: emberDocumentationUrl,
diff --git a/web/src/types/index.ts b/web/src/types/index.ts
index 71a2db668..10f64b2b0 100644
--- a/web/src/types/index.ts
+++ b/web/src/types/index.ts
@@ -88,6 +88,8 @@ export interface Info {
};
schema_url: string;
schema_version: string;
+ 'cli-minimal-version': string;
+ 'cli-requires-python': string;
}
export interface DandisetStats {
diff --git a/web/src/utils/constants.ts b/web/src/utils/constants.ts
index 449a5a0c4..e9861eede 100644
--- a/web/src/utils/constants.ts
+++ b/web/src/utils/constants.ts
@@ -1,5 +1,6 @@
const dandiUrl = 'https://dandiarchive.org';
const dandiAboutUrl = 'https://about.dandiarchive.org/';
+const dandiBlogUrl = 'https://about.dandiarchive.org/blog/';
const dandiDocumentationUrl = 'https://docs.dandiarchive.org';
const dandiHelpUrl = 'https://docs.dandiarchive.org/support/';
const dandihubUrl = 'https://hub.dandiarchive.org/';
@@ -61,6 +62,7 @@ const DANDISETS_PER_PAGE = 8;
export {
dandiUrl,
dandiAboutUrl,
+ dandiBlogUrl,
dandiDocumentationUrl,
dandihubUrl,
sandboxDocsUrl,
diff --git a/web/src/views/DandisetLandingView/DownloadDialog.vue b/web/src/views/DandisetLandingView/DownloadDialog.vue
index b3ef95374..a38ddcad6 100644
--- a/web/src/views/DandisetLandingView/DownloadDialog.vue
+++ b/web/src/views/DandisetLandingView/DownloadDialog.vue
@@ -116,10 +116,10 @@
Install the Python client (DANDI CLI)
- in a Python 3.8+ environment using command:
+ in a Python {{ cliRequiresPython }} environment using command:
- pip install "dandi>=0.60.0"
+ pip install "dandi>={{ cliMinimalVersion }}"
@@ -130,10 +130,11 @@