Coverage for src/bioimageio/spec/_internal/json_schema.py: 32%

34 statements  

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

1from __future__ import annotations 

2 

3import difflib 

4import re 

5from typing import Any 

6 

7from loguru import logger 

8from pydantic import ConfigDict 

9 

10from .._description import DESCRIPTIONS_MAP, SpecificResourceDescr 

11from .._version import VERSION 

12from .type_guards import is_dict, is_list 

13 

14 

15def _patch_desccription( 

16 json_schema: dict[str, Any], path: tuple[str, ...] = () 

17) -> None: 

18 """Patch descriptions: 

19 

20 - replace mkdocstrings cross-reference syntax [object][] by `object` 

21 """ 

22 if isinstance(descr := json_schema.get("description"), str) and descr: 

23 # Replace markdown link references like [object][] with `object` 

24 new_descr = re.sub(r"\[([^\]]+)\]\[\]", r"`\1`", descr) 

25 if descr != new_descr: 

26 diff = difflib.Differ().compare(descr.splitlines(), new_descr.splitlines()) 

27 logger.trace(f"updated {'.'.join(path)}:\n" + "\n".join(diff)) 

28 json_schema["description"] = new_descr 

29 

30 for k, v in json_schema.items(): 

31 if is_dict(v): 

32 _patch_desccription(v, path + (str(k),)) 

33 elif is_list(v): 

34 for index, item in enumerate(v): 

35 if is_dict(item): 

36 _patch_desccription(item, path + (str(k), str(index))) 

37 

38 

39def generate_json_schema( 

40 type_format: tuple[str, str] | None = None, 

41) -> dict[str, Any]: 

42 """generate the bioimageio specification as a JSON schema""" 

43 from pydantic import TypeAdapter 

44 

45 spec_format_version = ".".join(VERSION.split(".")[:3]) # strip library version 

46 if type_format is None: 

47 adapter: TypeAdapter[Any] = TypeAdapter( 

48 SpecificResourceDescr, 

49 config=ConfigDict( 

50 title=f"bioimage.io resource description {spec_format_version}" 

51 ), 

52 ) 

53 else: 

54 typ, format_version = type_format 

55 rd_class = DESCRIPTIONS_MAP[typ][format_version] 

56 adapter = TypeAdapter(rd_class) 

57 

58 json_schema = adapter.json_schema() 

59 _patch_desccription(json_schema) 

60 return json_schema