Coverage for src/bioimageio/spec/_internal/node.py: 90%

29 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-18 09:17 +0000

1from __future__ import annotations 

2 

3import collections.abc 

4import warnings 

5from typing import ( 

6 Any, 

7 Callable, 

8 Literal, 

9 Mapping, 

10) 

11 

12import pydantic 

13from typing_extensions import ParamSpec, Self, TypeVar 

14 

15from .type_guards import is_kwargs 

16from .validation_context import ValidationContext, get_validation_context 

17 

18 

19def _node_title_generator(node: type[Node]) -> str: 

20 return ( 

21 f"{node.implemented_type} {node.implemented_format_version}" # pyright: ignore[reportAttributeAccessIssue] 

22 if hasattr(node, "implemented_type") 

23 and hasattr(node, "implemented_format_version") 

24 else f"{node.__module__.replace('bioimageio.spec.', '')}.{node.__name__}" 

25 ) 

26 

27 

28P = ParamSpec("P") 

29T = TypeVar("T") 

30 

31 

32class Node( 

33 pydantic.BaseModel, 

34 allow_inf_nan=False, 

35 extra="forbid", 

36 frozen=False, 

37 model_title_generator=_node_title_generator, 

38 populate_by_name=True, 

39 revalidate_instances="always", 

40 use_attribute_docstrings=True, 

41 validate_assignment=True, 

42 validate_default=True, 

43 validate_return=True, 

44): 

45 # empty docstring to remove all pydantic docstrings from the pdoc spec docs 

46 """""" # ruff: ignore[D419] 

47 

48 @classmethod 

49 def model_validate( 

50 cls, 

51 obj: Any | Mapping[str, Any], 

52 *, 

53 strict: bool | None = None, 

54 extra: Literal["allow", "ignore", "forbid"] | None = None, 

55 from_attributes: bool | None = None, 

56 context: ValidationContext | Mapping[str, Any] | None = None, 

57 by_alias: bool | None = None, 

58 by_name: bool | None = None, 

59 ) -> Self: 

60 """Validate a pydantic model instance. 

61 

62 Args: 

63 obj: The object to validate. 

64 strict: Whether to raise an exception on invalid fields. 

65 from_attributes: Whether to extract data from object attributes. 

66 context: Additional context to pass to the validator. 

67 

68 Raises: 

69 ValidationError: If the object failed validation. 

70 

71 Returns: 

72 The validated description instance. 

73 """ 

74 __tracebackhide__ = True 

75 

76 if context is None: 

77 context = get_validation_context() 

78 elif isinstance(context, collections.abc.Mapping): 

79 context = ValidationContext(**context) 

80 

81 assert not isinstance(obj, collections.abc.Mapping) or is_kwargs(obj), obj 

82 

83 # TODO: pass on extra with pydantic >=2.12 

84 if extra is not None: 

85 warnings.warn("`extra` argument is currently ignored") 

86 

87 with context: 

88 # use validation context as context manager for equal behavior of __init__ and model_validate 

89 return super().model_validate( 

90 obj, strict=strict, from_attributes=from_attributes 

91 ) 

92 

93 @classmethod 

94 def dict_from_kwargs( 

95 cls: Callable[P, T], *args: P.args, **kwargs: P.kwargs 

96 ) -> dict[str, Any]: 

97 assert not args, "Did not expected any args" 

98 return dict(kwargs)