From 05596c3c3bc7c4a2607a3e41b01d17c54e90e1d5 Mon Sep 17 00:00:00 2001 From: "John T. Wodder II" Date: Wed, 8 Feb 2023 13:14:14 -0500 Subject: [PATCH 1/3] Make `RemoteDandiset.get_version()` return a `VersionInfo` instance with validation error fields --- dandi/dandiapi.py | 51 ++++++++++++++++++++++----------- docs/source/modref/dandiapi.rst | 6 ++++ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/dandi/dandiapi.py b/dandi/dandiapi.py index 4e90526f0..8ec10ab86 100644 --- a/dandi/dandiapi.py +++ b/dandi/dandiapi.py @@ -650,6 +650,23 @@ def __str__(self) -> str: return self.identifier +class ValidationError(APIBase): + field: str + message: str + + +class VersionInfo(Version): + """ + .. versionadded:: 0.49.0 + + Version information for a Dandiset, including information about validation + errors + """ + + asset_validation_errors: List[ValidationError] + version_validation_errors: List[ValidationError] + + class RemoteDandisetData(APIBase): """ Class for storing the data for a Dandiset retrieved from the API. @@ -876,15 +893,20 @@ def get_versions(self, order: Optional[str] = None) -> Iterator[Version]: except HTTP404Error: raise NotFoundError(f"No such Dandiset: {self.identifier!r}") - def get_version(self, version_id: str) -> Version: + def get_version(self, version_id: str) -> VersionInfo: """ Get information about a given version of the Dandiset. If the given version does not exist, a `NotFoundError` is raised. + + .. versionchanged:: 0.49.0 + + This method now returns a `VersionInfo` instance instead of just a + `Version`. """ try: - return Version.parse_obj( + return VersionInfo.parse_obj( self.client.get( - f"/dandisets/{self.identifier}/versions/{version_id}/info" + f"/dandisets/{self.identifier}/versions/{version_id}/info/" ) ) except HTTP404Error: @@ -958,26 +980,21 @@ def wait_until_valid(self, max_time: float = 120) -> None: lgr.debug("Waiting for Dandiset %s to complete validation ...", self.identifier) start = time() while time() - start < max_time: - try: - r = self.client.get(f"{self.version_api_path}info/") - except HTTP404Error: - raise NotFoundError( - f"No such version: {self.version_id!r} of Dandiset {self.identifier}" - ) - if "status" not in r: - # Running against older version of dandi-api that doesn't - # validate - return - if r["status"] == "Valid": + v = self.get_version(self.version_id) + if v.status is VersionStatus.VALID: return sleep(0.5) # TODO: Improve the presentation of the error messages about = { - "asset_validation_errors": r.get("asset_validation_errors"), - "version_validation_errors": r.get("version_validation_errors"), + "asset_validation_errors": [ + e.json_dict() for e in v.asset_validation_errors + ], + "version_validation_errors": [ + e.json_dict() for e in v.asset_validation_errors + ], } raise ValueError( - f"Dandiset {self.identifier} is {r['status']}: {json.dumps(about, indent=4)}" + f"Dandiset {self.identifier} is {v.status.value}: {json.dumps(about, indent=4)}" ) def publish(self, max_time: float = 120) -> "RemoteDandiset": diff --git a/docs/source/modref/dandiapi.rst b/docs/source/modref/dandiapi.rst index bddd485c3..01f762928 100644 --- a/docs/source/modref/dandiapi.rst +++ b/docs/source/modref/dandiapi.rst @@ -43,6 +43,12 @@ Dandisets :inherited-members: BaseModel :exclude-members: Config, JSON_EXCLUDE +.. autoclass:: VersionInfo() + :show-inheritance: + +.. autoclass:: ValidationError() + :inherited-members: BaseModel + Assets ------ From 9a36d21736c4ba268889bf2764265752e0255937 Mon Sep 17 00:00:00 2001 From: "John T. Wodder II" Date: Wed, 8 Feb 2023 14:15:01 -0500 Subject: [PATCH 2/3] Update dandi/dandiapi.py Co-authored-by: Yaroslav Halchenko --- dandi/dandiapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dandi/dandiapi.py b/dandi/dandiapi.py index 8ec10ab86..4a6279f4b 100644 --- a/dandi/dandiapi.py +++ b/dandi/dandiapi.py @@ -990,7 +990,7 @@ def wait_until_valid(self, max_time: float = 120) -> None: e.json_dict() for e in v.asset_validation_errors ], "version_validation_errors": [ - e.json_dict() for e in v.asset_validation_errors + e.json_dict() for e in v.version_validation_errors ], } raise ValueError( From f1d752b11dee180c41b4042481d893c08602ff0f Mon Sep 17 00:00:00 2001 From: "John T. Wodder II" Date: Wed, 8 Feb 2023 14:19:41 -0500 Subject: [PATCH 3/3] Rename & document (Remote)ValidationError --- dandi/dandiapi.py | 14 +++++++++++--- docs/source/modref/dandiapi.rst | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/dandi/dandiapi.py b/dandi/dandiapi.py index 4a6279f4b..c1af68a51 100644 --- a/dandi/dandiapi.py +++ b/dandi/dandiapi.py @@ -650,7 +650,15 @@ def __str__(self) -> str: return self.identifier -class ValidationError(APIBase): +class RemoteValidationError(APIBase): + """ + .. versionadded:: 0.49.0 + + Validation error record obtained from a server. Not to be confused with + :class:`dandi.validate_types.ValidationResult`, which provides richer + representation of validation errors. + """ + field: str message: str @@ -663,8 +671,8 @@ class VersionInfo(Version): errors """ - asset_validation_errors: List[ValidationError] - version_validation_errors: List[ValidationError] + asset_validation_errors: List[RemoteValidationError] + version_validation_errors: List[RemoteValidationError] class RemoteDandisetData(APIBase): diff --git a/docs/source/modref/dandiapi.rst b/docs/source/modref/dandiapi.rst index 01f762928..90fb9fc29 100644 --- a/docs/source/modref/dandiapi.rst +++ b/docs/source/modref/dandiapi.rst @@ -46,7 +46,7 @@ Dandisets .. autoclass:: VersionInfo() :show-inheritance: -.. autoclass:: ValidationError() +.. autoclass:: RemoteValidationError() :inherited-members: BaseModel Assets