@@ -28,7 +28,7 @@ def __init__(self, node=None, transport=None, location=None, strict=True):
2828
2929 self ._transport = transport
3030
31- self ._documents = OrderedDict ()
31+ self .documents = _SchemaContainer ()
3232 self ._prefix_map_auto = {}
3333 self ._prefix_map_custom = {}
3434
@@ -40,11 +40,12 @@ def __init__(self, node=None, transport=None, location=None, strict=True):
4040 nodes = node
4141 self .add_documents (nodes , location )
4242
43- @property
44- def documents (self ):
45- for documents in self ._documents .values ():
46- for document in documents :
47- yield document
43+ def __repr__ (self ):
44+ main_doc = self .root_document
45+ if main_doc :
46+ return '<Schema(location=%r, tns=%r)>' % (
47+ main_doc ._location , main_doc ._target_namespace )
48+ return '<Schema()>'
4849
4950 @property
5051 def prefix_map (self ):
@@ -69,7 +70,7 @@ def is_empty(self):
6970
7071 @property
7172 def namespaces (self ):
72- return set ( self ._documents . keys () )
73+ return self .documents . get_all_namespaces ( )
7374
7475 @property
7576 def elements (self ):
@@ -99,20 +100,13 @@ def types(self):
99100 yield type_
100101 seen .add (type_ .qname )
101102
102- def __repr__ (self ):
103- main_doc = self .root_document
104- if main_doc :
105- return '<Schema(location=%r, tns=%r)>' % (
106- main_doc ._location , main_doc ._target_namespace )
107- return '<Schema()>'
108-
109103 def add_documents (self , schema_nodes , location ):
110- documents = []
104+ resolve_queue = []
111105 for node in schema_nodes :
112106 document = self .create_new_document (node , location )
113- documents .append (document )
107+ resolve_queue .append (document )
114108
115- for document in documents :
109+ for document in resolve_queue :
116110 document .resolve ()
117111
118112 self ._prefix_map_auto = self ._create_prefix_map ()
@@ -199,19 +193,24 @@ def get_shorthand_for_ns(self, namespace):
199193 return namespace
200194
201195 def create_new_document (self , node , url , base_url = None ):
196+ """
197+
198+ :rtype: zeep.xsd.schema.SchemaDocument
199+
200+ """
202201 namespace = node .get ('targetNamespace' ) if node is not None else None
203202 if base_url is None :
204203 base_url = url
205204
206205 schema = SchemaDocument (namespace , url , base_url )
207- self ._add_schema_document (schema )
206+ self .documents . add (schema )
208207 schema .load (self , node )
209208 return schema
210209
211210 def merge (self , schema ):
212211 """Merge an other XSD schema in this one"""
213212 for document in schema .documents :
214- self ._add_schema_document (document )
213+ self .documents . add (document )
215214 self ._prefix_map_auto = self ._create_prefix_map ()
216215
217216 def _load_default_documents (self ):
@@ -226,7 +225,7 @@ def _load_default_documents(self):
226225 schema .register_element (cls .qname , instance )
227226
228227 schema ._is_internal = True
229- self ._add_schema_document (schema )
228+ self .documents . add (schema )
230229 return schema
231230
232231 def _get_instance (self , qname , method_name , name ):
@@ -277,64 +276,96 @@ def _create_prefix_map(self):
277276 'xsd' : 'http://www.w3.org/2001/XMLSchema' ,
278277 }
279278 i = 0
280- for namespace in self ._documents . keys ():
279+ for namespace in self .documents . get_all_namespaces ():
281280 if namespace is None or namespace in prefix_map .values ():
282281 continue
283282
284283 prefix_map ['ns%d' % i ] = namespace
285284 i += 1
286285 return prefix_map
287286
288- def _has_schema_document (self , namespace ):
289- """Return a boolean if there is a SchemaDocumnet for the namespace.
287+ def _get_schema_documents (self , namespace , fail_silently = False ):
288+ """Return a list of SchemaDocument's for the given namespace.
290289
291- :rtype: boolean
290+ :rtype: list of SchemaDocument
292291
293292 """
294- return namespace in self ._documents
293+ if (
294+ not self .documents .has_schema_document_for_ns (namespace )
295+ and namespace in const .AUTO_IMPORT_NAMESPACES
296+ ):
297+ logger .debug ("Auto importing missing known schema: %s" , namespace )
298+ self .add_document_by_url (namespace )
299+
300+ return self .documents .get_by_namespace (namespace , fail_silently )
301+
295302
296- def _add_schema_document (self , document ):
303+ class _SchemaContainer (object ):
304+ """Container instances to store multiple SchemaDocument objects per
305+ namespace.
306+
307+ """
308+
309+ def __init__ (self ):
310+ self ._instances = OrderedDict ()
311+
312+ def __iter__ (self ):
313+ for document in self .values ():
314+ yield document
315+
316+ def add (self , document ):
317+ """Append a schema document
318+
319+ :param document: zeep.xsd.schema.SchemaDocument
320+
321+ """
297322 logger .debug ("Add document with tns %s to schema %s" , document .namespace , id (self ))
298- documents = self ._documents .setdefault (document .namespace , [])
323+ documents = self ._instances .setdefault (document .namespace , [])
299324 documents .append (document )
300325
301- def _get_schema_document (self , namespace , location ):
302- """Return a list of SchemaDocument's for the given namespace AND
326+ def get_all_namespaces (self ):
327+ return self ._instances .keys ()
328+
329+ def get_by_namespace (self , namespace , fail_silently ):
330+ if namespace not in self ._instances :
331+ if fail_silently :
332+ return []
333+ raise exceptions .NamespaceError (
334+ "No schema available for the namespace %r" % namespace )
335+ return self ._instances [namespace ]
336+
337+ def get_by_namespace_and_location (self , namespace , location ):
338+ """Return list of SchemaDocument's for the given namespace AND
303339 location.
304340
305- :rtype: SchemaDocument
341+ :rtype: zeep.xsd.schema. SchemaDocument
306342
307343 """
308- for document in self ._documents .get (namespace , []):
344+ documents = self .get_by_namespace (namespace , fail_silently = True )
345+ for document in documents :
309346 if document ._location == location :
310347 return document
311348
312- def _get_schema_documents (self , namespace , fail_silently = False ):
313- """Return a list of SchemaDocument's for the given namespace.
349+ def has_schema_document_for_ns (self , namespace ):
350+ """Return a boolean if there is a SchemaDocument for the namespace.
314351
315- :rtype: list of SchemaDocument
352+ :rtype: boolean
316353
317354 """
318- if (
319- namespace not in self ._documents
320- and namespace in const .AUTO_IMPORT_NAMESPACES
321- ):
322- logger .debug ("Auto importing missing known schema: %s" , namespace )
323- self .add_document_by_url (namespace )
355+ return namespace in self ._instances
324356
325- if namespace not in self ._documents :
326- if fail_silently :
327- return []
328- raise exceptions .NamespaceError (
329- "No schema available for the namespace %r" % namespace )
330- return self ._documents [namespace ]
357+ def values (self ):
358+ for documents in self ._instances .values ():
359+ for document in documents :
360+ yield document
331361
332362
333363class SchemaDocument (object ):
334- """A Schema Document consists of a set of schema components for a specific
335- target namespace.
364+ """A Schema Document consists of a set of schema components for a
365+ specific target namespace.
336366
337367 """
368+
338369 def __init__ (self , namespace , location , base_url ):
339370 logger .debug ("Init schema document for %r" , location )
340371
@@ -379,7 +410,7 @@ def load(self, schema, node):
379410 if node is None :
380411 return
381412
382- if not schema ._has_schema_document (self ._target_namespace ):
413+ if not schema .documents . has_schema_document_for_ns (self ._target_namespace ):
383414 raise RuntimeError (
384415 "The document needs to be registered in the schema before " +
385416 "it can be loaded" )
0 commit comments