Skip to content

Commit

Permalink
Merge pull request #724 from dandi/gh-722
Browse files Browse the repository at this point in the history
Make upload() fail if client & server schema versions are not in sync
  • Loading branch information
yarikoptic committed Jul 22, 2021
2 parents cf0c118 + 5e6a9a1 commit 7a3ff79
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 2 deletions.
20 changes: 19 additions & 1 deletion dandi/dandiapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@
from xml.etree.ElementTree import fromstring

import click
from dandischema.models import get_schema_version
from pydantic import BaseModel, Field, PrivateAttr
import requests
import tenacity

from . import get_logger
from .consts import MAX_CHUNK_SIZE, known_instances, known_instances_rev
from .exceptions import NotFoundError
from .exceptions import NotFoundError, SchemaVersionError
from .keyring import keyring_lookup
from .utils import USER_AGENT, is_interactive, try_multiple

Expand Down Expand Up @@ -295,6 +296,23 @@ def create_dandiset(self, name: str, metadata: Dict[str, Any]) -> "RemoteDandise
self, self.post("/dandisets/", json={"name": name, "metadata": metadata})
)

def check_schema_version(self, schema_version: Optional[str] = None) -> None:
if schema_version is None:
schema_version = get_schema_version()
server_info = self.get("/info/")
server_schema_version = server_info.get("schema_version")
if not server_schema_version:
raise RuntimeError(
"Server did not provide schema_version in /info/;"
f" returned {server_info!r}"
)
if server_schema_version != schema_version:
raise SchemaVersionError(
f"Server requires schema version {server_schema_version};"
f" client only supports {schema_version}. You may need to"
" upgrade dandi and/or dandischema."
)


class APIBase(BaseModel):
"""Base class for API objects"""
Expand Down
4 changes: 4 additions & 0 deletions dandi/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ def __str__(self):
f"Client version {self.our_version} is rejected by server! "
+ self.server_requirements()
)


class SchemaVersionError(Exception):
pass
31 changes: 30 additions & 1 deletion dandi/tests/test_dandiapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
from shutil import rmtree

import click
from dandischema.models import UUID_PATTERN
from dandischema.models import UUID_PATTERN, get_schema_version
import pytest
import responses

from .. import dandiapi
from ..consts import dandiset_metadata_file
from ..dandiapi import DandiAPIClient
from ..download import download
from ..exceptions import SchemaVersionError
from ..upload import upload
from ..utils import find_files

Expand Down Expand Up @@ -311,3 +314,29 @@ def test_remote_asset_json_dict(text_dandiset):
assert sorted(data.keys()) == ["asset_id", "modified", "path", "size"]
for v in data.values():
assert isinstance(v, (str, int))


@responses.activate
def test_check_schema_version_matches_default():
responses.add(
responses.GET,
"https://test.nil/api/info/",
json={"schema_version": get_schema_version()},
)
client = DandiAPIClient("https://test.nil/api")
client.check_schema_version()


@responses.activate
def test_check_schema_version_mismatch():
responses.add(
responses.GET, "https://test.nil/api/info/", json={"schema_version": "4.5.6"}
)
client = DandiAPIClient("https://test.nil/api")
with pytest.raises(SchemaVersionError) as excinfo:
client.check_schema_version("1.2.3")
assert (
str(excinfo.value)
== "Server requires schema version 4.5.6; client only supports 1.2.3. "
"You may need to upgrade dandi and/or dandischema."
)
1 change: 1 addition & 0 deletions dandi/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def upload(
api_url = instance.api

client = DandiAPIClient(api_url)
client.check_schema_version()
client.dandi_authenticate()

dandiset = APIDandiset(dandiset.path) # "cast" to a new API based dandiset
Expand Down

0 comments on commit 7a3ff79

Please sign in to comment.