Coverage for src/bioimageio/spec/_internal/field_validation.py: 74%

43 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-16 10:20 +0000

1from __future__ import annotations 

2 

3from datetime import date, datetime 

4from typing import ( 

5 Any, 

6 Hashable, 

7 Mapping, 

8 Sequence, 

9) 

10 

11import httpx 

12from typing_extensions import TypeGuard 

13 

14from ._settings import settings 

15from .constants import KNOWN_GITHUB_USERS, KNOWN_INVALID_GITHUB_USERS 

16from .field_warning import issue_warning 

17from .io import YamlKey, YamlLeafValue, YamlValue 

18from .type_guards import is_mapping, is_sequence, is_tuple 

19from .validation_context import get_validation_context 

20 

21 

22def is_valid_yaml_leaf_value( 

23 value: Any, 

24) -> TypeGuard[YamlLeafValue]: 

25 return value is None or isinstance(value, (bool, date, datetime, int, float, str)) 

26 

27 

28def is_valid_yaml_key(value: Any | Sequence[Any]) -> TypeGuard[YamlKey]: 

29 return ( 

30 is_valid_yaml_leaf_value(value) 

31 or is_tuple(value) 

32 and all(is_valid_yaml_leaf_value(v) for v in value) 

33 ) 

34 

35 

36def is_valid_yaml_mapping(value: Any) -> TypeGuard[Mapping[YamlKey, YamlValue]]: 

37 return is_mapping(value) and all( 

38 is_valid_yaml_key(k) and is_valid_yaml_value(v) for k, v in value.items() 

39 ) 

40 

41 

42def is_valid_yaml_sequence(value: Any) -> TypeGuard[Sequence[YamlValue]]: 

43 return is_sequence(value) and all(is_valid_yaml_value(v) for v in value) 

44 

45 

46def is_valid_yaml_value(value: Any) -> TypeGuard[YamlValue]: 

47 return any( 

48 is_valid(value) 

49 for is_valid in ( 

50 is_valid_yaml_key, 

51 is_valid_yaml_mapping, 

52 is_valid_yaml_sequence, 

53 ) 

54 ) 

55 

56 

57def validate_unique_entries(seq: Sequence[Hashable]): 

58 if len(seq) != len(set(seq)): 

59 raise ValueError("Entries are not unique.") 

60 return seq 

61 

62 

63def validate_github_user( 

64 username: str, hotfix_known_errorenous_names: bool = True 

65) -> str: 

66 if hotfix_known_errorenous_names and username == "Constantin Pape": 

67 return "constantinpape" 

68 

69 if ( 

70 username.lower() in KNOWN_GITHUB_USERS 

71 or not get_validation_context().perform_io_checks 

72 ): 

73 return username 

74 

75 if username.lower() in KNOWN_INVALID_GITHUB_USERS: 

76 raise ValueError(f"Known invalid GitHub user '{username}'") 

77 

78 try: 

79 r = httpx.get( 

80 f"https://api.github.com/users/{username}", 

81 auth=settings.github_auth, 

82 timeout=settings.http_timeout, 

83 ) 

84 except httpx.TimeoutException: 

85 issue_warning( 

86 "Could not verify GitHub user '{value}' due to connection timeout", 

87 value=username, 

88 ) 

89 else: 

90 if r.status_code == 403 and r.reason_phrase == "rate limit exceeded": 

91 issue_warning( 

92 "Could not verify GitHub user '{value}' due to GitHub API rate limit", 

93 value=username, 

94 ) 

95 elif r.status_code != 200: 

96 KNOWN_INVALID_GITHUB_USERS.add(username.lower()) 

97 raise ValueError(f"Could not find GitHub user '{username}'") 

98 

99 KNOWN_GITHUB_USERS.add(username.lower()) 

100 

101 return username