Package suds :: Package xsd :: Module doctor
[hide private]
[frames] | no frames]

Source Code for Module suds.xsd.doctor

  1  # This program is free software; you can redistribute it and/or modify 
  2  # it under the terms of the (LGPL) GNU Lesser General Public License as 
  3  # published by the Free Software Foundation; either version 3 of the  
  4  # License, or (at your option) any later version. 
  5  # 
  6  # This program is distributed in the hope that it will be useful, 
  7  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  8  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  9  # GNU Library Lesser General Public License for more details at 
 10  # ( http://www.gnu.org/licenses/lgpl.html ). 
 11  # 
 12  # You should have received a copy of the GNU Lesser General Public License 
 13  # along with this program; if not, write to the Free Software 
 14  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 15  # written by: Jeff Ortel ( jortel@redhat.com ) 
 16   
 17  """ 
 18  The I{doctor} module provides classes for fixing broken (sick) 
 19  schema(s). 
 20  """ 
 21   
 22  from logging import getLogger 
 23  from suds.sax import splitPrefix, Namespace 
 24  from suds.sax.element import Element 
 25  from suds.plugin import DocumentPlugin, DocumentContext 
 26   
 27  log = getLogger(__name__) 
 28   
 29   
30 -class Doctor:
31 """ 32 Schema Doctor. 33 """
34 - def examine(self, root):
35 """ 36 Examine and repair the schema (if necessary). 37 @param root: A schema root element. 38 @type root: L{Element} 39 """ 40 pass
41 42
43 -class Practice(Doctor):
44 """ 45 A collection of doctors. 46 @ivar doctors: A list of doctors. 47 @type doctors: list 48 """ 49
50 - def __init__(self):
51 self.doctors = []
52
53 - def add(self, doctor):
54 """ 55 Add a doctor to the practice 56 @param doctor: A doctor to add. 57 @type doctor: L{Doctor} 58 """ 59 self.doctors.append(doctor)
60
61 - def examine(self, root):
62 for d in self.doctors: 63 d.examine(root) 64 return root
65 66
67 -class TnsFilter:
68 """ 69 Target Namespace filter. 70 @ivar tns: A list of target namespaces. 71 @type tns: [str,...] 72 """ 73
74 - def __init__(self, *tns):
75 """ 76 @param tns: A list of target namespaces. 77 @type tns: [str,...] 78 """ 79 self.tns = [] 80 self.add(*tns)
81
82 - def add(self, *tns):
83 """ 84 Add I{targetNamesapces} to be added. 85 @param tns: A list of target namespaces. 86 @type tns: [str,...] 87 """ 88 self.tns += tns
89
90 - def match(self, root, ns):
91 """ 92 Match by I{targetNamespace} excluding those that 93 are equal to the specified namespace to prevent 94 adding an import to itself. 95 @param root: A schema root. 96 @type root: L{Element} 97 """ 98 tns = root.get('targetNamespace') 99 if len(self.tns): 100 matched = ( tns in self.tns ) 101 else: 102 matched = 1 103 itself = ( ns == tns ) 104 return ( matched and not itself )
105 106
107 -class Import:
108 """ 109 An <xs:import/> to be applied. 110 @cvar xsdns: The XSD namespace. 111 @type xsdns: (p,u) 112 @ivar ns: An import namespace. 113 @type ns: str 114 @ivar location: An optional I{schemaLocation}. 115 @type location: str 116 @ivar filter: A filter used to restrict application to 117 a particular schema. 118 @type filter: L{TnsFilter} 119 """ 120 121 xsdns = Namespace.xsdns 122
123 - def __init__(self, ns, location=None):
124 """ 125 @param ns: An import namespace. 126 @type ns: str 127 @param location: An optional I{schemaLocation}. 128 @type location: str 129 """ 130 self.ns = ns 131 self.location = location 132 self.filter = TnsFilter()
133
134 - def setfilter(self, filter):
135 """ 136 Set the filter. 137 @param filter: A filter to set. 138 @type filter: L{TnsFilter} 139 """ 140 self.filter = filter
141
142 - def apply(self, root):
143 """ 144 Apply the import (rule) to the specified schema. 145 If the schema does not already contain an import for the 146 I{namespace} specified here, it is added. 147 @param root: A schema root. 148 @type root: L{Element} 149 """ 150 if not self.filter.match(root, self.ns): 151 return 152 if self.exists(root): 153 return 154 node = Element('import', ns=self.xsdns) 155 node.set('namespace', self.ns) 156 if self.location is not None: 157 node.set('schemaLocation', self.location) 158 log.debug('inserting: %s', node) 159 root.insert(node)
160
161 - def add(self, root):
162 """ 163 Add an <xs:import/> to the specified schema root. 164 @param root: A schema root. 165 @type root: L{Element} 166 """ 167 node = Element('import', ns=self.xsdns) 168 node.set('namespace', self.ns) 169 if self.location is not None: 170 node.set('schemaLocation', self.location) 171 log.debug('%s inserted', node) 172 root.insert(node)
173
174 - def exists(self, root):
175 """ 176 Check to see if the <xs:import/> already exists 177 in the specified schema root by matching I{namesapce}. 178 @param root: A schema root. 179 @type root: L{Element} 180 """ 181 for node in root.children: 182 if node.name != 'import': 183 continue 184 ns = node.get('namespace') 185 if self.ns == ns: 186 return 1 187 return 0
188 189
190 -class ImportDoctor(Doctor, DocumentPlugin):
191 """ 192 Doctor used to fix missing imports. 193 @ivar imports: A list of imports to apply. 194 @type imports: [L{Import},...] 195 """ 196
197 - def __init__(self, *imports):
198 """ 199 """ 200 self.imports = [] 201 self.add(*imports)
202
203 - def add(self, *imports):
204 """ 205 Add a namesapce to be checked. 206 @param imports: A list of L{Import} objects. 207 @type imports: [L{Import},..] 208 """ 209 self.imports += imports
210
211 - def examine(self, node):
212 for imp in self.imports: 213 imp.apply(node)
214
215 - def parsed(self, context):
216 node = context.document 217 # xsd root 218 if node.name == 'schema' and Namespace.xsd(node.namespace()): 219 self.examine(node) 220 return 221 # look deeper 222 context = DocumentContext() 223 for child in node: 224 context.document = child 225 self.parsed(context)
226