Skip to content

Commit 3cedc2d

Browse files
authored
Merge pull request #2714 from dandi/gui-use-cli-minimum-version
Display the correct CLI and required python version in the GUI
2 parents 48445fd + ccb3ca5 commit 3cedc2d

File tree

4 files changed

+53
-4
lines changed

4 files changed

+53
-4
lines changed

dandiapi/api/tests/test_info.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
from __future__ import annotations
22

3+
import importlib.metadata
4+
35
from dandischema.conf import get_instance_config
6+
from packaging.specifiers import SpecifierSet
47
import pytest
8+
import requests
59

610

711
@pytest.mark.django_db
@@ -16,3 +20,35 @@ def test_rest_info_instance_config_include_none(api_client):
1620
resp.json()['instance_config'].keys()
1721
== get_instance_config().model_dump(mode='json', exclude_none=False).keys()
1822
)
23+
24+
25+
def test_cli_minimal_version_matches_dandischema(api_client):
26+
"""Test that local dandischema and minimal cli dandischema are compatible."""
27+
# Get CLI version info from pypi
28+
minimal_version = api_client.get('/api/info/').json()['cli-minimal-version']
29+
data = requests.get(f'https://pypi.org/pypi/dandi/{minimal_version}/json').json()
30+
31+
# Extract the dandischema requirement
32+
dandischema_requires = [x for x in data['info']['requires_dist'] if x.startswith('dandischema')]
33+
assert len(dandischema_requires) == 1
34+
dandischema_version: str = dandischema_requires[0]
35+
version_range = SpecifierSet(
36+
dandischema_version.split(';', maxsplit=1)[0].removeprefix('dandischema').strip()
37+
)
38+
39+
# Ensure that local dandischema is compatible with the CLI version
40+
local_version = importlib.metadata.version('dandischema')
41+
assert version_range.contains(local_version)
42+
43+
44+
def test_cli_requires_python_compatible_with_minimal_version(api_client):
45+
"""Test that the CLI's required python version is compatible with the minimal version."""
46+
info = api_client.get('/api/info/').json()
47+
minimal_version: str = info['cli-minimal-version']
48+
data = requests.get(f'https://pypi.org/pypi/dandi/{minimal_version}/json').json()
49+
50+
cli_requires_python: str = info['cli-requires-python']
51+
dandischema_requires_python: str = data['info']['requires_python']
52+
53+
# Test for exact match
54+
assert cli_requires_python == dandischema_requires_python

dandiapi/api/views/info.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def __init__(self, *args, **kwargs):
4848
self.fields.update(
4949
{
5050
'cli-minimal-version': serializers.CharField(),
51+
'cli-requires-python': serializers.CharField(),
5152
'cli-bad-versions': serializers.ListField(child=serializers.CharField()),
5253
}
5354
)
@@ -84,7 +85,8 @@ def info_view(request):
8485
'schema_url': get_schema_url(),
8586
'allowed_schema_versions': ALLOWED_INPUT_SCHEMAS,
8687
'version': importlib.metadata.version('dandiapi'),
87-
'cli-minimal-version': '0.60.0',
88+
'cli-minimal-version': '0.74.0',
89+
'cli-requires-python': '>=3.10',
8890
'cli-bad-versions': [],
8991
'services': {
9092
'api': {'url': api_url},

web/src/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ export interface Info {
8888
};
8989
schema_url: string;
9090
schema_version: string;
91+
'cli-minimal-version': string;
92+
'cli-requires-python': string;
9193
}
9294

9395
export interface DandisetStats {

web/src/views/DandisetLandingView/DownloadDialog.vue

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,10 @@
116116
<v-list>
117117
<v-list-item>
118118
Install the Python client (DANDI CLI)
119-
in a Python 3.8+ environment using command:
119+
in a Python {{ cliRequiresPython }} environment using command:
120120
</v-list-item>
121121
<v-list-item>
122-
<kbd>pip install "dandi>=0.60.0"</kbd>
122+
<kbd>pip install "dandi>={{ cliMinimalVersion }}"</kbd>
123123
</v-list-item>
124124
</v-list>
125125
</v-expansion-panel-text>
@@ -130,10 +130,11 @@
130130
</v-menu>
131131
</template>
132132
<script setup lang="ts">
133-
import { computed, ref } from 'vue';
133+
import { computed, onMounted, ref } from 'vue';
134134
import { useDandisetStore } from '@/stores/dandiset';
135135
import CopyText from '@/components/CopyText.vue';
136136
import { dandiDocumentationUrl } from '@/utils/constants';
137+
import { dandiRest } from '@/rest';
137138
138139
function downloadCommand(identifier: string, version: string): string {
139140
// Use the special 'DANDI:' url prefix if appropriate.
@@ -153,6 +154,14 @@ const currentDandiset = computed(() => store.dandiset);
153154
const publishedVersions = computed(() => store.versions);
154155
const currentVersion = computed(() => store.version);
155156
157+
const cliMinimalVersion = ref<string>();
158+
const cliRequiresPython = ref<string>();
159+
onMounted(async () => {
160+
const info = await dandiRest.info();
161+
cliMinimalVersion.value = info['cli-minimal-version'];
162+
cliRequiresPython.value = info['cli-requires-python'];
163+
});
164+
156165
const selectedDownloadOption = ref('draft');
157166
const selectedVersion = ref(0);
158167

0 commit comments

Comments
 (0)