Package xmlschema_acue ::
Package validators ::
Module globals_
1
2
3
4
5
6
7
8
9
10
11 """
12 This module contains functions and classes for managing namespaces's
13 XSD declarations/definitions.
14 """
15 from __future__ import unicode_literals
16 import re
17 import warnings
18 from collections import Counter
19
20 from xmlschema_acue.exceptions import XMLSchemaKeyError, XMLSchemaTypeError, XMLSchemaValueError, XMLSchemaWarning
21 from xmlschema_acue.namespaces import XSD_NAMESPACE
22 from xmlschema_acue.qnames import XSD_INCLUDE, XSD_IMPORT, XSD_REDEFINE, XSD_OVERRIDE, XSD_NOTATION, XSD_ANY_TYPE, \
23 XSD_SIMPLE_TYPE, XSD_COMPLEX_TYPE, XSD_GROUP, XSD_ATTRIBUTE, XSD_ATTRIBUTE_GROUP, XSD_ELEMENT
24 from xmlschema_acue.helpers import get_qname, local_name
25 from xmlschema_acue.namespaces import NamespaceResourcesMap
26
27 from xmlschema_acue.validators.assertions import XsdAssert
28 from xmlschema_acue.validators.attributes import XsdAttribute, XsdAttributeGroup
29 from xmlschema_acue.validators.complex_types import XsdComplexType
30 from xmlschema_acue.validators.elements import XsdElement
31 from xmlschema_acue.validators.exceptions import XMLSchemaNotBuiltError, XMLSchemaModelError, XMLSchemaModelDepthError
32 from xmlschema_acue.validators.groups import XsdGroup
33 from xmlschema_acue.validators.identities import XsdKeyref
34 from xmlschema_acue.validators.notations import XsdNotation
35 from xmlschema_acue.validators.simple_types import XsdSimpleType
36 from xmlschema_acue.validators.xsdbase import XsdValidator, XsdComponent
37
38
39 from xmlschema_acue.validators.builtins import xsd_builtin_types_factory
43 """
44 Split words of a camel case string
45 """
46 return re.findall(r'[A-Z]?[a-z]+|[A-Z]+(?=[A-Z]|$)', s)
47
50 """
51 Defines a generator that produce all child elements that have a specific tag.
52 """
53 def iterfind_function(elem):
54 for e in elem:
55 if e.tag == tag:
56 yield e
57 iterfind_function.__name__ = str('iterfind_xsd_%ss' % '_'.join(camel_case_split(local_name(tag))).lower())
58 return iterfind_function
59
60
61 iterchildren_xsd_import = iterchildren_by_tag(XSD_IMPORT)
62 iterchildren_xsd_include = iterchildren_by_tag(XSD_INCLUDE)
63 iterchildren_xsd_redefine = iterchildren_by_tag(XSD_REDEFINE)
64 iterchildren_xsd_override = iterchildren_by_tag(XSD_OVERRIDE)
70
71 def load_xsd_globals(xsd_globals, schemas):
72 redefinitions = []
73 for schema in schemas:
74 target_namespace = schema.target_namespace
75 for elem in iterchildren_xsd_redefine(schema.root):
76 location = elem.get('schemaLocation')
77 if location is None:
78 continue
79 for child in filter_function(elem):
80 qname = get_qname(target_namespace, child.attrib['name'])
81 redefinitions.append((qname, child, schema, schema.includes[location]))
82
83 for elem in filter_function(schema.root):
84 qname = get_qname(target_namespace, elem.attrib['name'])
85 try:
86 xsd_globals[qname].append((elem, schema))
87 except KeyError:
88 xsd_globals[qname] = (elem, schema)
89 except AttributeError:
90 xsd_globals[qname] = [xsd_globals[qname], (elem, schema)]
91
92 tags = Counter([x[0] for x in redefinitions])
93 for qname, elem, schema, redefined_schema in redefinitions:
94
95
96 if tags[qname] > 1:
97 tags[qname] = 1
98
99 redefined_schemas = [x[3] for x in redefinitions if x[0] == qname]
100 if any(redefined_schemas.count(x) > 1 for x in redefined_schemas):
101 schema.parse_error(
102 "multiple redefinition for {} {!r}".format(local_name(elem.tag), qname), elem
103 )
104 else:
105 redefined_schemas = {x[3]: x[2] for x in redefinitions if x[0] == qname}
106 for rs, s in redefined_schemas.items():
107 while True:
108 try:
109 s = redefined_schemas[s]
110 except KeyError:
111 break
112
113 if s is rs:
114 schema.parse_error(
115 "circular redefinition for {} {!r}".format(local_name(elem.tag), qname), elem
116 )
117 break
118
119
120 try:
121 xsd_globals[qname].append((elem, schema))
122 except KeyError:
123 schema.parse_error("not a redefinition!", elem)
124
125 except AttributeError:
126 xsd_globals[qname] = [xsd_globals[qname], (elem, schema)]
127
128 return load_xsd_globals
129
130
131 load_xsd_simple_types = create_load_function(iterchildren_by_tag(XSD_SIMPLE_TYPE))
132 load_xsd_attributes = create_load_function(iterchildren_by_tag(XSD_ATTRIBUTE))
133 load_xsd_attribute_groups = create_load_function(iterchildren_by_tag(XSD_ATTRIBUTE_GROUP))
134 load_xsd_complex_types = create_load_function(iterchildren_by_tag(XSD_COMPLEX_TYPE))
135 load_xsd_elements = create_load_function(iterchildren_by_tag(XSD_ELEMENT))
136 load_xsd_groups = create_load_function(iterchildren_by_tag(XSD_GROUP))
137 load_xsd_notations = create_load_function(iterchildren_by_tag(XSD_NOTATION))
141 if isinstance(xsd_classes, tuple):
142 types_desc = ' or '.join([c.__name__ for c in xsd_classes])
143 else:
144 types_desc = xsd_classes.__name__
145
146 def lookup(global_map, qname, tag_map):
147 try:
148 obj = global_map[qname]
149 except KeyError:
150 if '{' in qname:
151 raise XMLSchemaKeyError("missing a %s component for %r!" % (types_desc, qname))
152 raise XMLSchemaKeyError("missing a %s component for %r! As the name has no namespace "
153 "maybe a missing default namespace declaration." % (types_desc, qname))
154 else:
155 if isinstance(obj, xsd_classes):
156 return obj
157
158 elif isinstance(obj, tuple):
159
160 try:
161 elem, schema = obj
162 except ValueError:
163 return obj[0]
164
165 try:
166 factory_or_class = tag_map[elem.tag]
167 except KeyError:
168 raise XMLSchemaKeyError("wrong element %r for map %r." % (elem, global_map))
169
170 global_map[qname] = obj,
171 global_map[qname] = factory_or_class(elem, schema, parent=None)
172 return global_map[qname]
173
174 elif isinstance(obj, list):
175
176 try:
177 elem, schema = obj[0]
178 except ValueError:
179 return obj[0][0]
180
181 try:
182 factory_or_class = tag_map[elem.tag]
183 except KeyError:
184 raise XMLSchemaKeyError("wrong element %r for map %r." % (elem, global_map))
185
186 global_map[qname] = obj[0],
187 global_map[qname] = component = factory_or_class(elem, schema, parent=None)
188
189
190 for elem, schema in obj[1:]:
191 component.redefine = component.copy()
192 component.schema = schema
193 component.elem = elem
194
195 return global_map[qname]
196
197 else:
198 raise XMLSchemaTypeError(
199 "wrong instance %s for XSD global %r, a %s required." % (obj, qname, types_desc)
200 )
201
202 return lookup
203
204
205 lookup_notation = create_lookup_function(XsdNotation)
206 lookup_type = create_lookup_function((XsdSimpleType, XsdComplexType))
207 lookup_attribute = create_lookup_function(XsdAttribute)
208 lookup_attribute_group = create_lookup_function(XsdAttributeGroup)
209 lookup_group = create_lookup_function(XsdGroup)
210 lookup_element = create_lookup_function(XsdElement)
214 """
215 Mediator class for related XML schema instances. It stores the global
216 declarations defined in the registered schemas. Register a schema to
217 add it's declarations to the global maps.
218
219 :param validator: the origin schema class/instance used for creating the global maps.
220 :param validation: the XSD validation mode to use, can be 'strict', 'lax' or 'skip'.
221 """
222 - def __init__(self, validator, validation='strict'):
241
243 return '%s(validator=%r, validation=%r)' % (self.__class__.__name__, self.validator, self.validation)
244
245 - def copy(self, validator=None, validation=None):
258
259 __copy__ = copy
260
263
266
269
272
275
278
279 - def lookup(self, tag, qname):
294
295 @property
301
302 @property
310
311 @property
321
322 @property
325
326 @property
332
334 if xsd_classes is None or isinstance(self, xsd_classes):
335 yield self
336 for xsd_global in self.iter_globals():
337 for obj in xsd_global.iter_components(xsd_classes):
338 yield obj
339
341 """Creates an iterator for the schemas registered in the instance."""
342 for ns_schemas in self.namespaces.values():
343 for schema in ns_schemas:
344 yield schema
345
347 """
348 Creates an iterator for XSD global definitions/declarations.
349 """
350 for global_map in self.global_maps:
351 for obj in global_map.values():
352 yield obj
353
367
368 - def clear(self, remove_schemas=False, only_unbuilt=False):
369 """
370 Clears the instance maps and schemas.
371
372 :param remove_schemas: removes also the schema instances.
373 :param only_unbuilt: removes only not built objects/schemas.
374 """
375 if only_unbuilt:
376 not_built_schemas = {schema for schema in self.iter_schemas() if not schema.built}
377 if not not_built_schemas:
378 return
379
380 for global_map in self.global_maps:
381 for k in list(global_map.keys()):
382 obj = global_map[k]
383 if not isinstance(obj, XsdComponent) or obj.schema in not_built_schemas:
384 del global_map[k]
385 if k in self.substitution_groups:
386 del self.substitution_groups[k]
387 if k in self.constraints:
388 del self.constraints[k]
389
390 if remove_schemas:
391 namespaces = NamespaceResourcesMap()
392 for uri, value in self.namespaces.items():
393 for schema in value:
394 if schema not in not_built_schemas:
395 namespaces[uri] = schema
396 self.namespaces = namespaces
397
398 else:
399 for global_map in self.global_maps:
400 global_map.clear()
401 self.substitution_groups.clear()
402 self.constraints.clear()
403
404 if remove_schemas:
405 self.namespaces.clear()
406
408 """
409 Build the maps of XSD global definitions/declarations. The global maps are
410 updated adding and building the globals of not built registered schemas.
411 """
412 try:
413 meta_schema = self.namespaces[XSD_NAMESPACE][0]
414 except KeyError:
415
416
417 meta_schema = self.validator.meta_schema
418 if meta_schema is None:
419 raise XMLSchemaValueError("{!r} has not a meta-schema".format(self.validator))
420
421 if any(ns in self.namespaces for ns in meta_schema.BASE_SCHEMAS):
422 base_schemas = {k: v for k, v in meta_schema.BASE_SCHEMAS.items() if k not in self.namespaces}
423 meta_schema = self.validator.create_meta_schema(meta_schema.url, base_schemas, self)
424 for schema in self.iter_schemas():
425 if schema.meta_schema is not None:
426 schema.meta_schema = meta_schema
427 else:
428 for schema in meta_schema.maps.iter_schemas():
429 self.register(schema)
430
431 self.types.update(meta_schema.maps.types)
432 self.attributes.update(meta_schema.maps.attributes)
433 self.attribute_groups.update(meta_schema.maps.attribute_groups)
434 self.groups.update(meta_schema.maps.groups)
435 self.notations.update(meta_schema.maps.notations)
436 self.elements.update(meta_schema.maps.elements)
437 self.substitution_groups.update(meta_schema.maps.substitution_groups)
438 self.constraints.update(meta_schema.maps.constraints)
439
440 not_built_schemas = [schema for schema in self.iter_schemas() if not schema.built]
441 for schema in not_built_schemas:
442 schema._root_elements = None
443
444
445 load_xsd_notations(self.notations, not_built_schemas)
446 load_xsd_simple_types(self.types, not_built_schemas)
447 load_xsd_attributes(self.attributes, not_built_schemas)
448 load_xsd_attribute_groups(self.attribute_groups, not_built_schemas)
449 load_xsd_complex_types(self.types, not_built_schemas)
450 load_xsd_elements(self.elements, not_built_schemas)
451 load_xsd_groups(self.groups, not_built_schemas)
452
453 if not meta_schema.built:
454 xsd_builtin_types_factory(meta_schema, self.types)
455
456 for qname in self.notations:
457 self.lookup_notation(qname)
458 for qname in self.attributes:
459 self.lookup_attribute(qname)
460 for qname in self.attribute_groups:
461 self.lookup_attribute_group(qname)
462 for qname in self.types:
463 self.lookup_type(qname)
464 for qname in self.elements:
465 self.lookup_element(qname)
466 for qname in self.groups:
467 self.lookup_group(qname)
468
469
470 for schema in not_built_schemas:
471 for group in schema.iter_components(XsdGroup):
472 group.build()
473
474 for schema in filter(lambda x: x.meta_schema is not None, not_built_schemas):
475
476 for constraint in schema.iter_components(XsdKeyref):
477 constraint.parse_refer()
478 for assertion in schema.iter_components(XsdAssert):
479 assertion.parse()
480 self._check_schema(schema)
481
482 if self.validation == 'strict' and not self.built:
483 raise XMLSchemaNotBuiltError(self, "global map %r not built!" % self)
484
529