Mercurial > cpython-lru_cache-weakref
annotate Lib/xml/dom/xmlbuilder.py @ 58765:2ba7677bfa95 legacy-trunk
testCopysign was defined twice in test_math; combine the definitions
| author | Mark Dickinson <dickinsm@gmail.com> |
|---|---|
| date | Sat, 06 Feb 2010 23:11:25 +0000 |
| parents | 684960fb1cbf |
| children | 5a416a6417d3 |
| rev | line source |
|---|---|
| 39275 | 1 """Implementation of the DOM Level 3 'LS-Load' feature.""" |
| 2 | |
| 3 import copy | |
| 4 import xml.dom | |
| 5 | |
| 6 from xml.dom.NodeFilter import NodeFilter | |
| 7 | |
| 8 | |
| 9 __all__ = ["DOMBuilder", "DOMEntityResolver", "DOMInputSource"] | |
| 10 | |
| 11 | |
| 12 class Options: | |
| 13 """Features object that has variables set for each DOMBuilder feature. | |
| 14 | |
| 15 The DOMBuilder class uses an instance of this class to pass settings to | |
| 16 the ExpatBuilder class. | |
| 17 """ | |
| 18 | |
| 19 # Note that the DOMBuilder class in LoadSave constrains which of these | |
| 20 # values can be set using the DOM Level 3 LoadSave feature. | |
| 21 | |
| 22 namespaces = 1 | |
| 23 namespace_declarations = True | |
| 24 validation = False | |
| 25 external_parameter_entities = True | |
| 26 external_general_entities = True | |
| 27 external_dtd_subset = True | |
| 28 validate_if_schema = False | |
| 29 validate = False | |
| 30 datatype_normalization = False | |
| 31 create_entity_ref_nodes = True | |
| 32 entities = True | |
| 33 whitespace_in_element_content = True | |
| 34 cdata_sections = True | |
| 35 comments = True | |
| 36 charset_overrides_xml_encoding = True | |
| 37 infoset = False | |
| 38 supported_mediatypes_only = False | |
| 39 | |
| 40 errorHandler = None | |
| 41 filter = None | |
| 42 | |
| 43 | |
| 44 class DOMBuilder: | |
| 45 entityResolver = None | |
| 46 errorHandler = None | |
| 47 filter = None | |
| 48 | |
| 49 ACTION_REPLACE = 1 | |
| 50 ACTION_APPEND_AS_CHILDREN = 2 | |
| 51 ACTION_INSERT_AFTER = 3 | |
| 52 ACTION_INSERT_BEFORE = 4 | |
| 53 | |
| 54 _legal_actions = (ACTION_REPLACE, ACTION_APPEND_AS_CHILDREN, | |
| 55 ACTION_INSERT_AFTER, ACTION_INSERT_BEFORE) | |
| 56 | |
| 57 def __init__(self): | |
| 58 self._options = Options() | |
| 59 | |
| 60 def _get_entityResolver(self): | |
| 61 return self.entityResolver | |
| 62 def _set_entityResolver(self, entityResolver): | |
| 63 self.entityResolver = entityResolver | |
| 64 | |
| 65 def _get_errorHandler(self): | |
| 66 return self.errorHandler | |
| 67 def _set_errorHandler(self, errorHandler): | |
| 68 self.errorHandler = errorHandler | |
| 69 | |
| 70 def _get_filter(self): | |
| 71 return self.filter | |
| 72 def _set_filter(self, filter): | |
| 73 self.filter = filter | |
| 74 | |
| 75 def setFeature(self, name, state): | |
| 76 if self.supportsFeature(name): | |
| 77 state = state and 1 or 0 | |
| 78 try: | |
| 79 settings = self._settings[(_name_xform(name), state)] | |
| 80 except KeyError: | |
| 81 raise xml.dom.NotSupportedErr( | |
| 82 "unsupported feature: %r" % (name,)) | |
| 83 else: | |
| 84 for name, value in settings: | |
| 85 setattr(self._options, name, value) | |
| 86 else: | |
| 87 raise xml.dom.NotFoundErr("unknown feature: " + repr(name)) | |
| 88 | |
| 89 def supportsFeature(self, name): | |
| 90 return hasattr(self._options, _name_xform(name)) | |
| 91 | |
| 92 def canSetFeature(self, name, state): | |
| 93 key = (_name_xform(name), state and 1 or 0) | |
|
56436
684960fb1cbf
replace has_key with 'in' operator
Benjamin Peterson <benjamin@python.org>
parents:
39275
diff
changeset
|
94 return key in self._settings |
| 39275 | 95 |
| 96 # This dictionary maps from (feature,value) to a list of | |
| 97 # (option,value) pairs that should be set on the Options object. | |
| 98 # If a (feature,value) setting is not in this dictionary, it is | |
| 99 # not supported by the DOMBuilder. | |
| 100 # | |
| 101 _settings = { | |
| 102 ("namespace_declarations", 0): [ | |
| 103 ("namespace_declarations", 0)], | |
| 104 ("namespace_declarations", 1): [ | |
| 105 ("namespace_declarations", 1)], | |
| 106 ("validation", 0): [ | |
| 107 ("validation", 0)], | |
| 108 ("external_general_entities", 0): [ | |
| 109 ("external_general_entities", 0)], | |
| 110 ("external_general_entities", 1): [ | |
| 111 ("external_general_entities", 1)], | |
| 112 ("external_parameter_entities", 0): [ | |
| 113 ("external_parameter_entities", 0)], | |
| 114 ("external_parameter_entities", 1): [ | |
| 115 ("external_parameter_entities", 1)], | |
| 116 ("validate_if_schema", 0): [ | |
| 117 ("validate_if_schema", 0)], | |
| 118 ("create_entity_ref_nodes", 0): [ | |
| 119 ("create_entity_ref_nodes", 0)], | |
| 120 ("create_entity_ref_nodes", 1): [ | |
| 121 ("create_entity_ref_nodes", 1)], | |
| 122 ("entities", 0): [ | |
| 123 ("create_entity_ref_nodes", 0), | |
| 124 ("entities", 0)], | |
| 125 ("entities", 1): [ | |
| 126 ("entities", 1)], | |
| 127 ("whitespace_in_element_content", 0): [ | |
| 128 ("whitespace_in_element_content", 0)], | |
| 129 ("whitespace_in_element_content", 1): [ | |
| 130 ("whitespace_in_element_content", 1)], | |
| 131 ("cdata_sections", 0): [ | |
| 132 ("cdata_sections", 0)], | |
| 133 ("cdata_sections", 1): [ | |
| 134 ("cdata_sections", 1)], | |
| 135 ("comments", 0): [ | |
| 136 ("comments", 0)], | |
| 137 ("comments", 1): [ | |
| 138 ("comments", 1)], | |
| 139 ("charset_overrides_xml_encoding", 0): [ | |
| 140 ("charset_overrides_xml_encoding", 0)], | |
| 141 ("charset_overrides_xml_encoding", 1): [ | |
| 142 ("charset_overrides_xml_encoding", 1)], | |
| 143 ("infoset", 0): [], | |
| 144 ("infoset", 1): [ | |
| 145 ("namespace_declarations", 0), | |
| 146 ("validate_if_schema", 0), | |
| 147 ("create_entity_ref_nodes", 0), | |
| 148 ("entities", 0), | |
| 149 ("cdata_sections", 0), | |
| 150 ("datatype_normalization", 1), | |
| 151 ("whitespace_in_element_content", 1), | |
| 152 ("comments", 1), | |
| 153 ("charset_overrides_xml_encoding", 1)], | |
| 154 ("supported_mediatypes_only", 0): [ | |
| 155 ("supported_mediatypes_only", 0)], | |
| 156 ("namespaces", 0): [ | |
| 157 ("namespaces", 0)], | |
| 158 ("namespaces", 1): [ | |
| 159 ("namespaces", 1)], | |
| 160 } | |
| 161 | |
| 162 def getFeature(self, name): | |
| 163 xname = _name_xform(name) | |
| 164 try: | |
| 165 return getattr(self._options, xname) | |
| 166 except AttributeError: | |
| 167 if name == "infoset": | |
| 168 options = self._options | |
| 169 return (options.datatype_normalization | |
| 170 and options.whitespace_in_element_content | |
| 171 and options.comments | |
| 172 and options.charset_overrides_xml_encoding | |
| 173 and not (options.namespace_declarations | |
| 174 or options.validate_if_schema | |
| 175 or options.create_entity_ref_nodes | |
| 176 or options.entities | |
| 177 or options.cdata_sections)) | |
| 178 raise xml.dom.NotFoundErr("feature %s not known" % repr(name)) | |
| 179 | |
| 180 def parseURI(self, uri): | |
| 181 if self.entityResolver: | |
| 182 input = self.entityResolver.resolveEntity(None, uri) | |
| 183 else: | |
| 184 input = DOMEntityResolver().resolveEntity(None, uri) | |
| 185 return self.parse(input) | |
| 186 | |
| 187 def parse(self, input): | |
| 188 options = copy.copy(self._options) | |
| 189 options.filter = self.filter | |
| 190 options.errorHandler = self.errorHandler | |
| 191 fp = input.byteStream | |
| 192 if fp is None and options.systemId: | |
| 193 import urllib2 | |
| 194 fp = urllib2.urlopen(input.systemId) | |
| 195 return self._parse_bytestream(fp, options) | |
| 196 | |
| 197 def parseWithContext(self, input, cnode, action): | |
| 198 if action not in self._legal_actions: | |
| 199 raise ValueError("not a legal action") | |
| 200 raise NotImplementedError("Haven't written this yet...") | |
| 201 | |
| 202 def _parse_bytestream(self, stream, options): | |
| 203 import xml.dom.expatbuilder | |
| 204 builder = xml.dom.expatbuilder.makeBuilder(options) | |
| 205 return builder.parseFile(stream) | |
| 206 | |
| 207 | |
| 208 def _name_xform(name): | |
| 209 return name.lower().replace('-', '_') | |
| 210 | |
| 211 | |
| 212 class DOMEntityResolver(object): | |
| 213 __slots__ = '_opener', | |
| 214 | |
| 215 def resolveEntity(self, publicId, systemId): | |
| 216 assert systemId is not None | |
| 217 source = DOMInputSource() | |
| 218 source.publicId = publicId | |
| 219 source.systemId = systemId | |
| 220 source.byteStream = self._get_opener().open(systemId) | |
| 221 | |
| 222 # determine the encoding if the transport provided it | |
| 223 source.encoding = self._guess_media_encoding(source) | |
| 224 | |
| 225 # determine the base URI is we can | |
| 226 import posixpath, urlparse | |
| 227 parts = urlparse.urlparse(systemId) | |
| 228 scheme, netloc, path, params, query, fragment = parts | |
| 229 # XXX should we check the scheme here as well? | |
| 230 if path and not path.endswith("/"): | |
| 231 path = posixpath.dirname(path) + "/" | |
| 232 parts = scheme, netloc, path, params, query, fragment | |
| 233 source.baseURI = urlparse.urlunparse(parts) | |
| 234 | |
| 235 return source | |
| 236 | |
| 237 def _get_opener(self): | |
| 238 try: | |
| 239 return self._opener | |
| 240 except AttributeError: | |
| 241 self._opener = self._create_opener() | |
| 242 return self._opener | |
| 243 | |
| 244 def _create_opener(self): | |
| 245 import urllib2 | |
| 246 return urllib2.build_opener() | |
| 247 | |
| 248 def _guess_media_encoding(self, source): | |
| 249 info = source.byteStream.info() | |
|
56436
684960fb1cbf
replace has_key with 'in' operator
Benjamin Peterson <benjamin@python.org>
parents:
39275
diff
changeset
|
250 if "Content-Type" in info: |
| 39275 | 251 for param in info.getplist(): |
| 252 if param.startswith("charset="): | |
| 253 return param.split("=", 1)[1].lower() | |
| 254 | |
| 255 | |
| 256 class DOMInputSource(object): | |
| 257 __slots__ = ('byteStream', 'characterStream', 'stringData', | |
| 258 'encoding', 'publicId', 'systemId', 'baseURI') | |
| 259 | |
| 260 def __init__(self): | |
| 261 self.byteStream = None | |
| 262 self.characterStream = None | |
| 263 self.stringData = None | |
| 264 self.encoding = None | |
| 265 self.publicId = None | |
| 266 self.systemId = None | |
| 267 self.baseURI = None | |
| 268 | |
| 269 def _get_byteStream(self): | |
| 270 return self.byteStream | |
| 271 def _set_byteStream(self, byteStream): | |
| 272 self.byteStream = byteStream | |
| 273 | |
| 274 def _get_characterStream(self): | |
| 275 return self.characterStream | |
| 276 def _set_characterStream(self, characterStream): | |
| 277 self.characterStream = characterStream | |
| 278 | |
| 279 def _get_stringData(self): | |
| 280 return self.stringData | |
| 281 def _set_stringData(self, data): | |
| 282 self.stringData = data | |
| 283 | |
| 284 def _get_encoding(self): | |
| 285 return self.encoding | |
| 286 def _set_encoding(self, encoding): | |
| 287 self.encoding = encoding | |
| 288 | |
| 289 def _get_publicId(self): | |
| 290 return self.publicId | |
| 291 def _set_publicId(self, publicId): | |
| 292 self.publicId = publicId | |
| 293 | |
| 294 def _get_systemId(self): | |
| 295 return self.systemId | |
| 296 def _set_systemId(self, systemId): | |
| 297 self.systemId = systemId | |
| 298 | |
| 299 def _get_baseURI(self): | |
| 300 return self.baseURI | |
| 301 def _set_baseURI(self, uri): | |
| 302 self.baseURI = uri | |
| 303 | |
| 304 | |
| 305 class DOMBuilderFilter: | |
| 306 """Element filter which can be used to tailor construction of | |
| 307 a DOM instance. | |
| 308 """ | |
| 309 | |
| 310 # There's really no need for this class; concrete implementations | |
| 311 # should just implement the endElement() and startElement() | |
| 312 # methods as appropriate. Using this makes it easy to only | |
| 313 # implement one of them. | |
| 314 | |
| 315 FILTER_ACCEPT = 1 | |
| 316 FILTER_REJECT = 2 | |
| 317 FILTER_SKIP = 3 | |
| 318 FILTER_INTERRUPT = 4 | |
| 319 | |
| 320 whatToShow = NodeFilter.SHOW_ALL | |
| 321 | |
| 322 def _get_whatToShow(self): | |
| 323 return self.whatToShow | |
| 324 | |
| 325 def acceptNode(self, element): | |
| 326 return self.FILTER_ACCEPT | |
| 327 | |
| 328 def startContainer(self, element): | |
| 329 return self.FILTER_ACCEPT | |
| 330 | |
| 331 del NodeFilter | |
| 332 | |
| 333 | |
| 334 class DocumentLS: | |
| 335 """Mixin to create documents that conform to the load/save spec.""" | |
| 336 | |
| 337 async = False | |
| 338 | |
| 339 def _get_async(self): | |
| 340 return False | |
| 341 def _set_async(self, async): | |
| 342 if async: | |
| 343 raise xml.dom.NotSupportedErr( | |
| 344 "asynchronous document loading is not supported") | |
| 345 | |
| 346 def abort(self): | |
| 347 # What does it mean to "clear" a document? Does the | |
| 348 # documentElement disappear? | |
| 349 raise NotImplementedError( | |
| 350 "haven't figured out what this means yet") | |
| 351 | |
| 352 def load(self, uri): | |
| 353 raise NotImplementedError("haven't written this yet") | |
| 354 | |
| 355 def loadXML(self, source): | |
| 356 raise NotImplementedError("haven't written this yet") | |
| 357 | |
| 358 def saveXML(self, snode): | |
| 359 if snode is None: | |
| 360 snode = self | |
| 361 elif snode.ownerDocument is not self: | |
| 362 raise xml.dom.WrongDocumentErr() | |
| 363 return snode.toxml() | |
| 364 | |
| 365 | |
| 366 class DOMImplementationLS: | |
| 367 MODE_SYNCHRONOUS = 1 | |
| 368 MODE_ASYNCHRONOUS = 2 | |
| 369 | |
| 370 def createDOMBuilder(self, mode, schemaType): | |
| 371 if schemaType is not None: | |
| 372 raise xml.dom.NotSupportedErr( | |
| 373 "schemaType not yet supported") | |
| 374 if mode == self.MODE_SYNCHRONOUS: | |
| 375 return DOMBuilder() | |
| 376 if mode == self.MODE_ASYNCHRONOUS: | |
| 377 raise xml.dom.NotSupportedErr( | |
| 378 "asynchronous builders are not supported") | |
| 379 raise ValueError("unknown value for mode") | |
| 380 | |
| 381 def createDOMWriter(self): | |
| 382 raise NotImplementedError( | |
| 383 "the writer interface hasn't been written yet!") | |
| 384 | |
| 385 def createDOMInputSource(self): | |
| 386 return DOMInputSource() |
