Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/nbformat/json_compat.py: 37%

59 statements  

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

1""" 

2Common validator wrapper to provide a uniform usage of other schema validation 

3libraries. 

4""" 

5# Copyright (c) Jupyter Development Team. 

6# Distributed under the terms of the Modified BSD License. 

7 

8import os 

9 

10import fastjsonschema 

11import jsonschema 

12from fastjsonschema import JsonSchemaException as _JsonSchemaException 

13from jsonschema import Draft4Validator as _JsonSchemaValidator 

14from jsonschema import ErrorTree, ValidationError 

15 

16 

17class JsonSchemaValidator: 

18 """A json schema validator.""" 

19 

20 name = "jsonschema" 

21 

22 def __init__(self, schema): 

23 """Initialize the validator.""" 

24 self._schema = schema 

25 self._default_validator = _JsonSchemaValidator(schema) # Default 

26 self._validator = self._default_validator 

27 

28 def validate(self, data): 

29 """Validate incoming data.""" 

30 self._default_validator.validate(data) 

31 

32 def iter_errors(self, data, schema=None): 

33 """Iterate over errors in incoming data.""" 

34 if schema is None: 

35 return self._default_validator.iter_errors(data) 

36 if hasattr(self._default_validator, "evolve"): 

37 return self._default_validator.evolve(schema=schema).iter_errors(data) 

38 return self._default_validator.iter_errors(data, schema) 

39 

40 def error_tree(self, errors): 

41 """Create an error tree for the errors.""" 

42 return ErrorTree(errors=errors) 

43 

44 

45class FastJsonSchemaValidator(JsonSchemaValidator): 

46 """A schema validator using fastjsonschema.""" 

47 

48 name = "fastjsonschema" 

49 

50 def __init__(self, schema): 

51 """Initialize the validator.""" 

52 super().__init__(schema) 

53 self._validator = fastjsonschema.compile(schema) 

54 

55 def validate(self, data): 

56 """Validate incoming data.""" 

57 try: 

58 self._validator(data) 

59 except _JsonSchemaException as error: 

60 raise ValidationError(str(error), schema_path=error.path) from error 

61 

62 def iter_errors(self, data, schema=None): 

63 """Iterate over errors in incoming data.""" 

64 if schema is not None: 

65 return super().iter_errors(data, schema) 

66 

67 errors = [] 

68 validate_func = self._validator 

69 try: 

70 validate_func(data) 

71 except _JsonSchemaException as error: 

72 errors = [ValidationError(str(error), schema_path=error.path)] 

73 

74 return errors 

75 

76 def error_tree(self, errors): 

77 """Create an error tree for the errors.""" 

78 # fastjsonschema's exceptions don't contain the same information that the jsonschema ValidationErrors 

79 # do. This method is primarily used for introspecting metadata schema failures so that we can strip 

80 # them if asked to do so in `nbformat.validate`. 

81 # Another way forward for compatibility: we could distill both validator errors into a custom collection 

82 # for this data. Since implementation details of ValidationError is used elsewhere, we would probably 

83 # just use this data for schema introspection. 

84 msg = "JSON schema error introspection not enabled for fastjsonschema" 

85 raise NotImplementedError(msg) 

86 

87 

88_VALIDATOR_MAP = [ 

89 ("fastjsonschema", fastjsonschema, FastJsonSchemaValidator), 

90 ("jsonschema", jsonschema, JsonSchemaValidator), 

91] 

92VALIDATORS = [item[0] for item in _VALIDATOR_MAP] 

93 

94 

95def _validator_for_name(validator_name): 

96 if validator_name not in VALIDATORS: 

97 msg = f"Invalid validator '{validator_name}' value!\nValid values are: {VALIDATORS}" 

98 raise ValueError(msg) 

99 

100 for name, module, validator_cls in _VALIDATOR_MAP: 

101 if module and validator_name == name: 

102 return validator_cls 

103 # we always return something. 

104 msg = f"Missing validator for {repr(validator_name)}" 

105 raise ValueError(msg) 

106 

107 

108def get_current_validator(): 

109 """ 

110 Return the default validator based on the value of an environment variable. 

111 """ 

112 validator_name = os.environ.get("NBFORMAT_VALIDATOR", "fastjsonschema") 

113 return _validator_for_name(validator_name)