4
4
import sys
5
5
import urlparse
6
6
import re
7
+ import logging
8
+
7
9
from typing import Any , Union
8
10
from .sourceline import SourceLine , lineno_re , bullets , indent
9
11
12
+ _logger = logging .getLogger ("salad" )
10
13
11
14
class ValidationException (Exception ):
12
15
pass
@@ -54,12 +57,14 @@ def vpformat(datum): # type: (Any) -> str
54
57
return a
55
58
56
59
57
- def validate_ex (expected_schema , # type: Schema
58
- datum , # type: Any
59
- identifiers = None , # type: Set[unicode]
60
- strict = False , # type: bool
61
- foreign_properties = None , # type: Set[unicode]
62
- raise_ex = True # type: bool
60
+ def validate_ex (expected_schema , # type: Schema
61
+ datum , # type: Any
62
+ identifiers = None , # type: Set[unicode]
63
+ strict = False , # type: bool
64
+ foreign_properties = None , # type: Set[unicode]
65
+ raise_ex = True , # type: bool
66
+ strict_foreign_properties = False , # type: bool
67
+ logger = _logger # type: logging.Logger
63
68
):
64
69
# type: (...) -> bool
65
70
"""Determine if a python datum is an instance of a schema."""
@@ -167,9 +172,11 @@ def validate_ex(expected_schema, # type: Schema
167
172
for i , d in enumerate (datum ):
168
173
try :
169
174
sl = SourceLine (datum , i , ValidationException )
170
- if not validate_ex (expected_schema .items , d , identifiers , strict = strict ,
175
+ if not validate_ex (expected_schema .items , d , identifiers ,
176
+ strict = strict ,
171
177
foreign_properties = foreign_properties ,
172
- raise_ex = raise_ex ):
178
+ raise_ex = raise_ex ,
179
+ strict_foreign_properties = strict_foreign_properties ):
173
180
return False
174
181
except ValidationException as v :
175
182
if raise_ex :
@@ -186,7 +193,8 @@ def validate_ex(expected_schema, # type: Schema
186
193
return False
187
194
elif isinstance (expected_schema , avro .schema .UnionSchema ):
188
195
for s in expected_schema .schemas :
189
- if validate_ex (s , datum , identifiers , strict = strict , raise_ex = False ):
196
+ if validate_ex (s , datum , identifiers , strict = strict , raise_ex = False ,
197
+ strict_foreign_properties = strict_foreign_properties ):
190
198
return True
191
199
192
200
if not raise_ex :
@@ -207,7 +215,9 @@ def validate_ex(expected_schema, # type: Schema
207
215
checked .append (s )
208
216
try :
209
217
validate_ex (s , datum , identifiers , strict = strict ,
210
- foreign_properties = foreign_properties , raise_ex = True )
218
+ foreign_properties = foreign_properties ,
219
+ raise_ex = True ,
220
+ strict_foreign_properties = strict_foreign_properties )
211
221
except ClassValidationException as e :
212
222
raise
213
223
except ValidationException as e :
@@ -256,8 +266,10 @@ def validate_ex(expected_schema, # type: Schema
256
266
257
267
try :
258
268
sl = SourceLine (datum , f .name , unicode )
259
- if not validate_ex (f .type , fieldval , identifiers , strict = strict , foreign_properties = foreign_properties ,
260
- raise_ex = raise_ex ):
269
+ if not validate_ex (f .type , fieldval , identifiers , strict = strict ,
270
+ foreign_properties = foreign_properties ,
271
+ raise_ex = raise_ex ,
272
+ strict_foreign_properties = strict_foreign_properties ):
261
273
return False
262
274
except ValidationException as v :
263
275
if f .name not in datum :
@@ -266,24 +278,34 @@ def validate_ex(expected_schema, # type: Schema
266
278
errors .append (sl .makeError (u"the `%s` field is not valid because\n %s" % (
267
279
f .name , indent (str (v )))))
268
280
269
- if strict :
270
- for d in datum :
271
- found = False
272
- for f in expected_schema .fields :
273
- if d == f .name :
274
- found = True
275
- if not found :
276
- sl = SourceLine (datum , d , unicode )
277
- if d not in identifiers and d not in foreign_properties and d [0 ] not in ("@" , "$" ):
278
- if not raise_ex :
279
- return False
280
- split = urlparse .urlsplit (d )
281
- if split .scheme :
282
- errors .append (sl .makeError (
283
- u"unrecognized extension field `%s` and strict is True. Did you include a $schemas section?" % (d )))
281
+ for d in datum :
282
+ found = False
283
+ for f in expected_schema .fields :
284
+ if d == f .name :
285
+ found = True
286
+ if not found :
287
+ sl = SourceLine (datum , d , unicode )
288
+ if d not in identifiers and d not in foreign_properties and d [0 ] not in ("@" , "$" ):
289
+ if (d not in identifiers and strict ) and (
290
+ d not in foreign_properties and strict_foreign_properties ) and not raise_ex :
291
+ return False
292
+ split = urlparse .urlsplit (d )
293
+ if split .scheme :
294
+ err = sl .makeError (u"unrecognized extension field `%s`%s."
295
+ " Did you include "
296
+ "a $schemas section?" % (
297
+ d , " and strict_foreign_properties is True" if strict_foreign_properties else "" ))
298
+ if strict_foreign_properties :
299
+ errors .append (err )
300
+ else :
301
+ logger .warn (err )
302
+ else :
303
+ err = sl .makeError (u"invalid field `%s`, expected one of: %s" % (
304
+ d , ", " .join ("'%s'" % fn .name for fn in expected_schema .fields )))
305
+ if strict :
306
+ errors .append (err )
284
307
else :
285
- errors .append (sl .makeError (u"invalid field `%s`, expected one of: %s" % (
286
- d , ", " .join ("'%s'" % fn .name for fn in expected_schema .fields ))))
308
+ logger .warn (err )
287
309
288
310
if errors :
289
311
if raise_ex :
0 commit comments