|
1 | | -import six |
2 | | -from python_jsonschema_objects import util |
3 | | -import collections |
4 | 1 | import logging |
| 2 | + |
| 3 | +import six |
| 4 | + |
5 | 5 | logger = logging.getLogger(__name__) |
6 | 6 |
|
7 | 7 | SCHEMA_TYPE_MAPPING = ( |
@@ -167,217 +167,3 @@ def check_type(param, value, type_data): |
167 | 167 | type_check(param, value, type_data) |
168 | 168 |
|
169 | 169 |
|
170 | | -class ArrayValidator(object): |
171 | | - |
172 | | - def __init__(self, ary): |
173 | | - if isinstance(ary, (list, tuple, collections.Sequence)): |
174 | | - self.data = ary |
175 | | - elif isinstance(ary, ArrayValidator): |
176 | | - self.data = ary.data |
177 | | - else: |
178 | | - raise TypeError("Invalid value given to array validator: {0}" |
179 | | - .format(ary)) |
180 | | - |
181 | | - @classmethod |
182 | | - def from_json(cls, jsonmsg): |
183 | | - import json |
184 | | - msg = json.loads(jsonmsg) |
185 | | - obj = cls(msg) |
186 | | - obj.validate() |
187 | | - return obj |
188 | | - |
189 | | - def serialize(self): |
190 | | - d = self.validate() |
191 | | - enc = util.ProtocolJSONEncoder() |
192 | | - return enc.encode(d) |
193 | | - |
194 | | - def for_json(self): |
195 | | - return self.validate() |
196 | | - |
197 | | - def validate(self): |
198 | | - converted = self.validate_items() |
199 | | - self.validate_length() |
200 | | - self.validate_uniqueness() |
201 | | - return converted |
202 | | - |
203 | | - def validate_uniqueness(self): |
204 | | - from python_jsonschema_objects import classbuilder |
205 | | - |
206 | | - if getattr(self, 'uniqueItems', None) is not None: |
207 | | - testset = set(self.data) |
208 | | - if len(testset) != len(self.data): |
209 | | - raise ValidationError( |
210 | | - "{0} has duplicate elements, but uniqueness required" |
211 | | - .format(self.data)) |
212 | | - |
213 | | - def validate_length(self): |
214 | | - from python_jsonschema_objects import classbuilder |
215 | | - |
216 | | - if getattr(self, 'minItems', None) is not None: |
217 | | - if len(self.data) < self.minItems: |
218 | | - raise ValidationError( |
219 | | - "{1} has too few elements. Wanted {0}." |
220 | | - .format(self.minItems, self.data)) |
221 | | - |
222 | | - if getattr(self, 'maxItems', None) is not None: |
223 | | - if len(self.data) > self.maxItems: |
224 | | - raise ValidationError( |
225 | | - "{1} has too few elements. Wanted {0}." |
226 | | - .format(self.maxItems, self.data)) |
227 | | - |
228 | | - def validate_items(self): |
229 | | - from python_jsonschema_objects import classbuilder |
230 | | - |
231 | | - if self.__itemtype__ is None: |
232 | | - return |
233 | | - |
234 | | - type_checks = self.__itemtype__ |
235 | | - if not isinstance(type_checks, (tuple, list)): |
236 | | - # we were given items = {'type': 'blah'} ; thus ensure the type for all data. |
237 | | - type_checks = [type_checks] * len(self.data) |
238 | | - elif len(type_checks) > len(self.data): |
239 | | - raise ValidationError( |
240 | | - "{1} does not have sufficient elements to validate against {0}" |
241 | | - .format(self.__itemtype__, self.data)) |
242 | | - |
243 | | - typed_elems = [] |
244 | | - for elem, typ in zip(self.data, type_checks): |
245 | | - if isinstance(typ, dict): |
246 | | - for param, paramval in six.iteritems(typ): |
247 | | - validator = registry(param) |
248 | | - if validator is not None: |
249 | | - validator(paramval, elem, typ) |
250 | | - typed_elems.append(elem) |
251 | | - |
252 | | - elif util.safe_issubclass(typ, classbuilder.LiteralValue): |
253 | | - val = typ(elem) |
254 | | - val.validate() |
255 | | - typed_elems.append(val) |
256 | | - elif util.safe_issubclass(typ, classbuilder.ProtocolBase): |
257 | | - if not isinstance(elem, typ): |
258 | | - try: |
259 | | - if isinstance(elem, (six.string_types, six.integer_types, float)): |
260 | | - val = typ(elem) |
261 | | - else: |
262 | | - val = typ(**util.coerce_for_expansion(elem)) |
263 | | - except TypeError as e: |
264 | | - raise ValidationError("'{0}' is not a valid value for '{1}': {2}" |
265 | | - .format(elem, typ, e)) |
266 | | - else: |
267 | | - val = elem |
268 | | - val.validate() |
269 | | - typed_elems.append(val) |
270 | | - |
271 | | - elif util.safe_issubclass(typ, ArrayValidator): |
272 | | - val = typ(elem) |
273 | | - val.validate() |
274 | | - typed_elems.append(val) |
275 | | - |
276 | | - elif isinstance(typ, classbuilder.TypeProxy): |
277 | | - try: |
278 | | - if isinstance(elem, (six.string_types, six.integer_types, float)): |
279 | | - val = typ(elem) |
280 | | - else: |
281 | | - val = typ(**util.coerce_for_expansion(elem)) |
282 | | - except TypeError as e: |
283 | | - raise ValidationError("'{0}' is not a valid value for '{1}': {2}" |
284 | | - .format(elem, typ, e)) |
285 | | - else: |
286 | | - val.validate() |
287 | | - typed_elems.append(val) |
288 | | - |
289 | | - return typed_elems |
290 | | - |
291 | | - @staticmethod |
292 | | - def create(name, item_constraint=None, **addl_constraints): |
293 | | - """ Create an array validator based on the passed in constraints. |
294 | | -
|
295 | | - If item_constraint is a tuple, it is assumed that tuple validation |
296 | | - is being performed. If it is a class or dictionary, list validation |
297 | | - will be performed. Classes are assumed to be subclasses of ProtocolBase, |
298 | | - while dictionaries are expected to be basic types ('string', 'number', ...). |
299 | | -
|
300 | | - addl_constraints is expected to be key-value pairs of any of the other |
301 | | - constraints permitted by JSON Schema v4. |
302 | | - """ |
303 | | - from python_jsonschema_objects import classbuilder |
304 | | - klassbuilder = addl_constraints.pop("classbuilder", None) |
305 | | - props = {} |
306 | | - |
307 | | - if item_constraint is not None: |
308 | | - if isinstance(item_constraint, (tuple, list)): |
309 | | - for i, elem in enumerate(item_constraint): |
310 | | - isdict = isinstance(elem, (dict,)) |
311 | | - isklass = isinstance( elem, type) and util.safe_issubclass( |
312 | | - elem, (classbuilder.ProtocolBase, classbuilder.LiteralValue)) |
313 | | - |
314 | | - if not any([isdict, isklass]): |
315 | | - raise TypeError( |
316 | | - "Item constraint (position {0}) is not a schema".format(i)) |
317 | | - elif isinstance(item_constraint, classbuilder.TypeProxy): |
318 | | - pass |
319 | | - elif util.safe_issubclass(item_constraint, ArrayValidator): |
320 | | - pass |
321 | | - else: |
322 | | - isdict = isinstance(item_constraint, (dict,)) |
323 | | - isklass = isinstance( item_constraint, type) and util.safe_issubclass( |
324 | | - item_constraint, (classbuilder.ProtocolBase, classbuilder.LiteralValue)) |
325 | | - |
326 | | - if not any([isdict, isklass]): |
327 | | - raise TypeError("Item constraint is not a schema") |
328 | | - |
329 | | - if isdict and '$ref' in item_constraint: |
330 | | - if klassbuilder is None: |
331 | | - raise TypeError("Cannot resolve {0} without classbuilder" |
332 | | - .format(item_constraint['$ref'])) |
333 | | - |
334 | | - uri = item_constraint['$ref'] |
335 | | - if uri in klassbuilder.resolved: |
336 | | - logger.debug(util.lazy_format( |
337 | | - "Using previously resolved object for {0}", uri)) |
338 | | - else: |
339 | | - logger.debug(util.lazy_format("Resolving object for {0}", uri)) |
340 | | - |
341 | | - with klassbuilder.resolver.resolving(uri) as resolved: |
342 | | - # Set incase there is a circular reference in schema definition |
343 | | - klassbuilder.resolved[uri] = None |
344 | | - klassbuilder.resolved[uri] = klassbuilder.construct( |
345 | | - uri, |
346 | | - resolved, |
347 | | - (classbuilder.ProtocolBase,)) |
348 | | - |
349 | | - item_constraint = klassbuilder.resolved[uri] |
350 | | - |
351 | | - elif isdict and item_constraint.get('type') == 'array': |
352 | | - # We need to create a sub-array validator. |
353 | | - item_constraint = ArrayValidator.create(name + "#sub", |
354 | | - item_constraint=item_constraint[ |
355 | | - 'items'], |
356 | | - addl_constraints=item_constraint) |
357 | | - elif isdict and 'oneOf' in item_constraint: |
358 | | - # We need to create a TypeProxy validator |
359 | | - uri = "{0}_{1}".format(name, "<anonymous_list_type>") |
360 | | - type_array = [] |
361 | | - for i, item_detail in enumerate(item_constraint['oneOf']): |
362 | | - if '$ref' in item_detail: |
363 | | - subtype = klassbuilder.construct( |
364 | | - util.resolve_ref_uri( |
365 | | - klassbuilder.resolver.resolution_scope, |
366 | | - item_detail['$ref']), |
367 | | - item_detail) |
368 | | - else: |
369 | | - subtype = klassbuilder.construct( |
370 | | - uri + "_%s" % i, item_detail) |
371 | | - |
372 | | - type_array.append(subtype) |
373 | | - |
374 | | - item_constraint = classbuilder.TypeProxy(type_array) |
375 | | - |
376 | | - props['__itemtype__'] = item_constraint |
377 | | - |
378 | | - props.update(addl_constraints) |
379 | | - |
380 | | - validator = type(str(name), (ArrayValidator,), props) |
381 | | - |
382 | | - return validator |
383 | | - |
0 commit comments