bioimageio.spec.pretty_validation_errors
1from pprint import pformat 2from types import TracebackType 3from typing import Any, List, Type, Union 4 5from pydantic import ValidationError 6 7from .summary import format_loc 8 9try: 10 from IPython.core.getipython import get_ipython 11 from IPython.core.interactiveshell import InteractiveShell 12 13 class PrettyValidationError(ValueError): 14 """Wrap a pydantic.ValidationError to custumize formatting.""" 15 16 def __init__(self, validation_error: ValidationError): 17 super().__init__() 18 self.error = validation_error 19 20 def __str__(self): 21 errors: List[str] = [] 22 for e in self.error.errors(include_url=False): 23 ipt_lines = pformat( 24 e["input"], sort_dicts=False, depth=1, compact=True, width=30 25 ).split("\n") 26 if len(ipt_lines) > 2: 27 ipt_lines[1:-1] = ["..."] 28 29 ipt = " ".join([il.strip() for il in ipt_lines]) 30 31 errors.append( 32 f"\n{format_loc(e['loc'], enclose_in='')}\n {e['msg']} [input={ipt}]" 33 ) 34 35 return ( 36 f"{self.error.error_count()} validation errors for" 37 f" {self.error.title}:{''.join(errors)}" 38 ) 39 40 def _custom_exception_handler( 41 self: InteractiveShell, 42 etype: Type[ValidationError], 43 evalue: ValidationError, 44 tb: TracebackType, 45 tb_offset: Any = None, 46 ): 47 assert issubclass(etype, ValidationError), type(etype) 48 assert isinstance(evalue, ValidationError), type(etype) 49 50 stb: Union[Any, List[Union[str, Any]]] 51 stb = self.InteractiveTB.structured_traceback( # pyright: ignore[reportUnknownVariableType] 52 etype, PrettyValidationError(evalue), tb, tb_offset=tb_offset 53 ) 54 55 if isinstance(stb, list): 56 stb_clean = [] 57 for line in stb: # pyright: ignore[reportUnknownVariableType] 58 if ( 59 isinstance(line, str) 60 and "pydantic" in line 61 and "__tracebackhide__" in line 62 ): 63 # ignore pydantic internal frame in traceback 64 continue 65 stb_clean.append(line) 66 67 stb = stb_clean 68 69 self._showtraceback(etype, PrettyValidationError(evalue), stb) # type: ignore 70 71 def enable_pretty_validation_errors_in_ipynb(): 72 """A modestly hacky way to display prettified validaiton error messages and traceback 73 in interactive Python notebooks""" 74 ipy = get_ipython() 75 if ipy is not None: 76 ipy.set_custom_exc((ValidationError,), _custom_exception_handler) 77 78except ImportError: 79 80 def enable_pretty_validation_errors_in_ipynb(): 81 return
class
PrettyValidationError(builtins.ValueError):
14 class PrettyValidationError(ValueError): 15 """Wrap a pydantic.ValidationError to custumize formatting.""" 16 17 def __init__(self, validation_error: ValidationError): 18 super().__init__() 19 self.error = validation_error 20 21 def __str__(self): 22 errors: List[str] = [] 23 for e in self.error.errors(include_url=False): 24 ipt_lines = pformat( 25 e["input"], sort_dicts=False, depth=1, compact=True, width=30 26 ).split("\n") 27 if len(ipt_lines) > 2: 28 ipt_lines[1:-1] = ["..."] 29 30 ipt = " ".join([il.strip() for il in ipt_lines]) 31 32 errors.append( 33 f"\n{format_loc(e['loc'], enclose_in='')}\n {e['msg']} [input={ipt}]" 34 ) 35 36 return ( 37 f"{self.error.error_count()} validation errors for" 38 f" {self.error.title}:{''.join(errors)}" 39 )
Wrap a pydantic.ValidationError to custumize formatting.
def
enable_pretty_validation_errors_in_ipynb():
72 def enable_pretty_validation_errors_in_ipynb(): 73 """A modestly hacky way to display prettified validaiton error messages and traceback 74 in interactive Python notebooks""" 75 ipy = get_ipython() 76 if ipy is not None: 77 ipy.set_custom_exc((ValidationError,), _custom_exception_handler)
A modestly hacky way to display prettified validaiton error messages and traceback in interactive Python notebooks