Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jsonschema/protocols.py: 86%

28 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-01 06:54 +0000

1""" 

2typing.Protocol classes for jsonschema interfaces. 

3""" 

4 

5# for reference material on Protocols, see 

6# https://www.python.org/dev/peps/pep-0544/ 

7 

8from __future__ import annotations 

9 

10from collections.abc import Callable, Mapping 

11from typing import TYPE_CHECKING, Any, ClassVar, Iterable 

12import sys 

13 

14# doing these imports with `try ... except ImportError` doesn't pass mypy 

15# checking because mypy sees `typing._SpecialForm` and 

16# `typing_extensions._SpecialForm` as incompatible 

17# 

18# see: 

19# https://mypy.readthedocs.io/en/stable/runtime_troubles.html#using-new-additions-to-the-typing-module 

20# https://github.com/python/mypy/issues/4427 

21if sys.version_info >= (3, 8): 

22 from typing import Protocol, runtime_checkable 

23else: 

24 from typing_extensions import Protocol, runtime_checkable 

25 

26# in order for Sphinx to resolve references accurately from type annotations, 

27# it needs to see names like `jsonschema.TypeChecker` 

28# therefore, only import at type-checking time (to avoid circular references), 

29# but use `jsonschema` for any types which will otherwise not be resolvable 

30if TYPE_CHECKING: 

31 import jsonschema 

32 import jsonschema.validators 

33 

34from jsonschema.exceptions import ValidationError 

35 

36# For code authors working on the validator protocol, these are the three 

37# use-cases which should be kept in mind: 

38# 

39# 1. As a protocol class, it can be used in type annotations to describe the 

40# available methods and attributes of a validator 

41# 2. It is the source of autodoc for the validator documentation 

42# 3. It is runtime_checkable, meaning that it can be used in isinstance() 

43# checks. 

44# 

45# Since protocols are not base classes, isinstance() checking is limited in 

46# its capabilities. See docs on runtime_checkable for detail 

47 

48 

49@runtime_checkable 

50class Validator(Protocol): 

51 """ 

52 The protocol to which all validator classes adhere. 

53 

54 Arguments: 

55 

56 schema: 

57 

58 The schema that the validator object will validate with. 

59 It is assumed to be valid, and providing 

60 an invalid schema can lead to undefined behavior. See 

61 `Validator.check_schema` to validate a schema first. 

62 

63 resolver: 

64 

65 a resolver that will be used to resolve :kw:`$ref` 

66 properties (JSON references). If unprovided, one will be created. 

67 

68 format_checker: 

69 

70 if provided, a checker which will be used to assert about 

71 :kw:`format` properties present in the schema. If unprovided, 

72 *no* format validation is done, and the presence of format 

73 within schemas is strictly informational. Certain formats 

74 require additional packages to be installed in order to assert 

75 against instances. Ensure you've installed `jsonschema` with 

76 its `extra (optional) dependencies <index:extras>` when 

77 invoking ``pip``. 

78 

79 .. deprecated:: v4.12.0 

80 

81 Subclassing validator classes now explicitly warns this is not part of 

82 their public API. 

83 """ 

84 

85 #: An object representing the validator's meta schema (the schema that 

86 #: describes valid schemas in the given version). 

87 META_SCHEMA: ClassVar[Mapping] 

88 

89 #: A mapping of validation keywords (`str`\s) to functions that 

90 #: validate the keyword with that name. For more information see 

91 #: `creating-validators`. 

92 VALIDATORS: ClassVar[Mapping] 

93 

94 #: A `jsonschema.TypeChecker` that will be used when validating 

95 #: :kw:`type` keywords in JSON schemas. 

96 TYPE_CHECKER: ClassVar[jsonschema.TypeChecker] 

97 

98 #: A `jsonschema.FormatChecker` that will be used when validating 

99 #: :kw:`format` keywords in JSON schemas. 

100 FORMAT_CHECKER: ClassVar[jsonschema.FormatChecker] 

101 

102 #: A function which given a schema returns its ID. 

103 ID_OF: Callable[[Any], str | None] 

104 

105 #: The schema that will be used to validate instances 

106 schema: Mapping | bool 

107 

108 def __init__( 

109 self, 

110 schema: Mapping | bool, 

111 resolver: jsonschema.validators.RefResolver | None = None, 

112 format_checker: jsonschema.FormatChecker | None = None, 

113 ) -> None: 

114 ... 

115 

116 @classmethod 

117 def check_schema(cls, schema: Mapping | bool) -> None: 

118 """ 

119 Validate the given schema against the validator's `META_SCHEMA`. 

120 

121 Raises: 

122 

123 `jsonschema.exceptions.SchemaError`: 

124 

125 if the schema is invalid 

126 """ 

127 

128 def is_type(self, instance: Any, type: str) -> bool: 

129 """ 

130 Check if the instance is of the given (JSON Schema) type. 

131 

132 Arguments: 

133 

134 instance: 

135 

136 the value to check 

137 

138 type: 

139 

140 the name of a known (JSON Schema) type 

141 

142 Returns: 

143 

144 whether the instance is of the given type 

145 

146 Raises: 

147 

148 `jsonschema.exceptions.UnknownType`: 

149 

150 if ``type`` is not a known type 

151 """ 

152 

153 def is_valid(self, instance: Any) -> bool: 

154 """ 

155 Check if the instance is valid under the current `schema`. 

156 

157 Returns: 

158 

159 whether the instance is valid or not 

160 

161 >>> schema = {"maxItems" : 2} 

162 >>> Draft202012Validator(schema).is_valid([2, 3, 4]) 

163 False 

164 """ 

165 

166 def iter_errors(self, instance: Any) -> Iterable[ValidationError]: 

167 r""" 

168 Lazily yield each of the validation errors in the given instance. 

169 

170 >>> schema = { 

171 ... "type" : "array", 

172 ... "items" : {"enum" : [1, 2, 3]}, 

173 ... "maxItems" : 2, 

174 ... } 

175 >>> v = Draft202012Validator(schema) 

176 >>> for error in sorted(v.iter_errors([2, 3, 4]), key=str): 

177 ... print(error.message) 

178 4 is not one of [1, 2, 3] 

179 [2, 3, 4] is too long 

180 

181 .. deprecated:: v4.0.0 

182 

183 Calling this function with a second schema argument is deprecated. 

184 Use `Validator.evolve` instead. 

185 """ 

186 

187 def validate(self, instance: Any) -> None: 

188 """ 

189 Check if the instance is valid under the current `schema`. 

190 

191 Raises: 

192 

193 `jsonschema.exceptions.ValidationError`: 

194 

195 if the instance is invalid 

196 

197 >>> schema = {"maxItems" : 2} 

198 >>> Draft202012Validator(schema).validate([2, 3, 4]) 

199 Traceback (most recent call last): 

200 ... 

201 ValidationError: [2, 3, 4] is too long 

202 """ 

203 

204 def evolve(self, **kwargs) -> "Validator": 

205 """ 

206 Create a new validator like this one, but with given changes. 

207 

208 Preserves all other attributes, so can be used to e.g. create a 

209 validator with a different schema but with the same :kw:`$ref` 

210 resolution behavior. 

211 

212 >>> validator = Draft202012Validator({}) 

213 >>> validator.evolve(schema={"type": "number"}) 

214 Draft202012Validator(schema={'type': 'number'}, format_checker=None) 

215 

216 The returned object satisfies the validator protocol, but may not 

217 be of the same concrete class! In particular this occurs 

218 when a :kw:`$ref` occurs to a schema with a different 

219 :kw:`$schema` than this one (i.e. for a different draft). 

220 

221 >>> validator.evolve( 

222 ... schema={"$schema": Draft7Validator.META_SCHEMA["$id"]} 

223 ... ) 

224 Draft7Validator(schema=..., format_checker=None) 

225 """