Skip to content

Commit

Permalink
ENH - Better handling of pydantic error msgs (#546)
Browse files Browse the repository at this point in the history
* better handling of pydantic error msgs

* Better handling of spec validation errors

* Fix - forgotten return

* pydantic errors : custom exception

* linting
  • Loading branch information
pierrotsmnrd authored Oct 9, 2023
1 parent 0f26920 commit 6d66e77
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
40 changes: 38 additions & 2 deletions conda-store-server/conda_store_server/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import sys
from typing import Any, Callable, Dict, List, Optional, Union

from conda_store_server import conda_utils
from pydantic import BaseModel, Field, constr, validator
from conda_store_server import conda_utils, utils
from pydantic import BaseModel, Field, ValidationError, constr, validator


def _datetime_factory(offset: datetime.timedelta):
Expand Down Expand Up @@ -406,6 +406,42 @@ def check_dependencies(cls, v):

return v

@classmethod
def parse_obj(cls, specification):
try:
return super().parse_obj(specification)
except ValidationError as e:
# there can be multiple errors. Let's build a comprehensive summary
# to return to the end user.

# hr stands for "human readable"
all_errors_hr = []

for err in e.errors():
error_type = err["type"]
error_loc = err["loc"]

# fallback case : if we can't figure out the error, let's build a default
# one based on the data returned by Pydantic.
human_readable_error = (
f"{err['msg']} (type={error_type}, loc={error_loc})"
)

if error_type == "type_error.none.not_allowed":
if error_loc[0] == "name":
human_readable_error = (
"The name of the environment cannot be empty."
)
else:
if len(error_loc) == 1:
human_readable_error = f"Invalid YAML : A forbidden `None` value has been encountered in section {error_loc[0]}"
elif len(error_loc) == 2:
human_readable_error = f"Invalid YAML : A forbidden `None` value has been encountered in section `{error_loc[0]}`, line {error_loc[1]}"

all_errors_hr.append(human_readable_error)

raise utils.CondaStoreError(all_errors_hr)


###############################
# Docker Registry Schema
Expand Down
2 changes: 2 additions & 0 deletions conda-store-server/conda_store_server/server/views/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,8 @@ async def api_post_specification(
specification = schema.CondaSpecification.parse_obj(specification)
except yaml.error.YAMLError:
raise HTTPException(status_code=400, detail="Unable to parse. Invalid YAML")
except utils.CondaStoreError as e:
raise HTTPException(status_code=400, detail="\n".join(e.args[0]))
except pydantic.ValidationError as e:
raise HTTPException(status_code=400, detail=str(e))

Expand Down

0 comments on commit 6d66e77

Please sign in to comment.