diff options
author | Shubham Saini <shubham6405@gmail.com> | 2019-08-05 08:32:33 +0000 |
---|---|---|
committer | Shubham Saini <shubham6405@gmail.com> | 2019-08-05 08:32:33 +0000 |
commit | 227b2d30a8675b44918f9d9ca89b24144a938215 (patch) | |
tree | 9f8e6a28724514b6fdf463a9ab2067a7ef309b72 /venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders | |
parent | 842a8cfbbbdb1f92889d892e4859dbd5d40c5be8 (diff) |
removing venv files
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders')
5 files changed, 0 insertions, 1447 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/__init__.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/__init__.py deleted file mode 100644 index 2ce5c87..0000000 --- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/__init__.py +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | """A collection of modules for building different kinds of trees from HTML | ||
2 | documents. | ||
3 | |||
4 | To create a treebuilder for a new type of tree, you need to do | ||
5 | implement several things: | ||
6 | |||
7 | 1. A set of classes for various types of elements: Document, Doctype, Comment, | ||
8 | Element. These must implement the interface of ``base.treebuilders.Node`` | ||
9 | (although comment nodes have a different signature for their constructor, | ||
10 | see ``treebuilders.etree.Comment``) Textual content may also be implemented | ||
11 | as another node type, or not, as your tree implementation requires. | ||
12 | |||
13 | 2. A treebuilder object (called ``TreeBuilder`` by convention) that inherits | ||
14 | from ``treebuilders.base.TreeBuilder``. This has 4 required attributes: | ||
15 | |||
16 | * ``documentClass`` - the class to use for the bottommost node of a document | ||
17 | * ``elementClass`` - the class to use for HTML Elements | ||
18 | * ``commentClass`` - the class to use for comments | ||
19 | * ``doctypeClass`` - the class to use for doctypes | ||
20 | |||
21 | It also has one required method: | ||
22 | |||
23 | * ``getDocument`` - Returns the root node of the complete document tree | ||
24 | |||
25 | 3. If you wish to run the unit tests, you must also create a ``testSerializer`` | ||
26 | method on your treebuilder which accepts a node and returns a string | ||
27 | containing Node and its children serialized according to the format used in | ||
28 | the unittests | ||
29 | |||
30 | """ | ||
31 | |||
32 | from __future__ import absolute_import, division, unicode_literals | ||
33 | |||
34 | from .._utils import default_etree | ||
35 | |||
36 | treeBuilderCache = {} | ||
37 | |||
38 | |||
39 | def getTreeBuilder(treeType, implementation=None, **kwargs): | ||
40 | """Get a TreeBuilder class for various types of trees with built-in support | ||
41 | |||
42 | :arg treeType: the name of the tree type required (case-insensitive). Supported | ||
43 | values are: | ||
44 | |||
45 | * "dom" - A generic builder for DOM implementations, defaulting to a | ||
46 | xml.dom.minidom based implementation. | ||
47 | * "etree" - A generic builder for tree implementations exposing an | ||
48 | ElementTree-like interface, defaulting to xml.etree.cElementTree if | ||
49 | available and xml.etree.ElementTree if not. | ||
50 | * "lxml" - A etree-based builder for lxml.etree, handling limitations | ||
51 | of lxml's implementation. | ||
52 | |||
53 | :arg implementation: (Currently applies to the "etree" and "dom" tree | ||
54 | types). A module implementing the tree type e.g. xml.etree.ElementTree | ||
55 | or xml.etree.cElementTree. | ||
56 | |||
57 | :arg kwargs: Any additional options to pass to the TreeBuilder when | ||
58 | creating it. | ||
59 | |||
60 | Example: | ||
61 | |||
62 | >>> from html5lib.treebuilders import getTreeBuilder | ||
63 | >>> builder = getTreeBuilder('etree') | ||
64 | |||
65 | """ | ||
66 | |||
67 | treeType = treeType.lower() | ||
68 | if treeType not in treeBuilderCache: | ||
69 | if treeType == "dom": | ||
70 | from . import dom | ||
71 | # Come up with a sane default (pref. from the stdlib) | ||
72 | if implementation is None: | ||
73 | from xml.dom import minidom | ||
74 | implementation = minidom | ||
75 | # NEVER cache here, caching is done in the dom submodule | ||
76 | return dom.getDomModule(implementation, **kwargs).TreeBuilder | ||
77 | elif treeType == "lxml": | ||
78 | from . import etree_lxml | ||
79 | treeBuilderCache[treeType] = etree_lxml.TreeBuilder | ||
80 | elif treeType == "etree": | ||
81 | from . import etree | ||
82 | if implementation is None: | ||
83 | implementation = default_etree | ||
84 | # NEVER cache here, caching is done in the etree submodule | ||
85 | return etree.getETreeModule(implementation, **kwargs).TreeBuilder | ||
86 | else: | ||
87 | raise ValueError("""Unrecognised treebuilder "%s" """ % treeType) | ||
88 | return treeBuilderCache.get(treeType) | ||
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/base.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/base.py deleted file mode 100644 index ed32fcb..0000000 --- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/base.py +++ /dev/null | |||
@@ -1,417 +0,0 @@ | |||
1 | from __future__ import absolute_import, division, unicode_literals | ||
2 | from pip._vendor.six import text_type | ||
3 | |||
4 | from ..constants import scopingElements, tableInsertModeElements, namespaces | ||
5 | |||
6 | # The scope markers are inserted when entering object elements, | ||
7 | # marquees, table cells, and table captions, and are used to prevent formatting | ||
8 | # from "leaking" into tables, object elements, and marquees. | ||
9 | Marker = None | ||
10 | |||
11 | listElementsMap = { | ||
12 | None: (frozenset(scopingElements), False), | ||
13 | "button": (frozenset(scopingElements | set([(namespaces["html"], "button")])), False), | ||
14 | "list": (frozenset(scopingElements | set([(namespaces["html"], "ol"), | ||
15 | (namespaces["html"], "ul")])), False), | ||
16 | "table": (frozenset([(namespaces["html"], "html"), | ||
17 | (namespaces["html"], "table")]), False), | ||
18 | "select": (frozenset([(namespaces["html"], "optgroup"), | ||
19 | (namespaces["html"], "option")]), True) | ||
20 | } | ||
21 | |||
22 | |||
23 | class Node(object): | ||
24 | """Represents an item in the tree""" | ||
25 | def __init__(self, name): | ||
26 | """Creates a Node | ||
27 | |||
28 | :arg name: The tag name associated with the node | ||
29 | |||
30 | """ | ||
31 | # The tag name assocaited with the node | ||
32 | self.name = name | ||
33 | # The parent of the current node (or None for the document node) | ||
34 | self.parent = None | ||
35 | # The value of the current node (applies to text nodes and comments) | ||
36 | self.value = None | ||
37 | # A dict holding name -> value pairs for attributes of the node | ||
38 | self.attributes = {} | ||
39 | # A list of child nodes of the current node. This must include all | ||
40 | # elements but not necessarily other node types. | ||
41 | self.childNodes = [] | ||
42 | # A list of miscellaneous flags that can be set on the node. | ||
43 | self._flags = [] | ||
44 | |||
45 | def __str__(self): | ||
46 | attributesStr = " ".join(["%s=\"%s\"" % (name, value) | ||
47 | for name, value in | ||
48 | self.attributes.items()]) | ||
49 | if attributesStr: | ||
50 | return "<%s %s>" % (self.name, attributesStr) | ||
51 | else: | ||
52 | return "<%s>" % (self.name) | ||
53 | |||
54 | def __repr__(self): | ||
55 | return "<%s>" % (self.name) | ||
56 | |||
57 | def appendChild(self, node): | ||
58 | """Insert node as a child of the current node | ||
59 | |||
60 | :arg node: the node to insert | ||
61 | |||
62 | """ | ||
63 | raise NotImplementedError | ||
64 | |||
65 | def insertText(self, data, insertBefore=None): | ||
66 | """Insert data as text in the current node, positioned before the | ||
67 | start of node insertBefore or to the end of the node's text. | ||
68 | |||
69 | :arg data: the data to insert | ||
70 | |||
71 | :arg insertBefore: True if you want to insert the text before the node | ||
72 | and False if you want to insert it after the node | ||
73 | |||
74 | """ | ||
75 | raise NotImplementedError | ||
76 | |||
77 | def insertBefore(self, node, refNode): | ||
78 | """Insert node as a child of the current node, before refNode in the | ||
79 | list of child nodes. Raises ValueError if refNode is not a child of | ||
80 | the current node | ||
81 | |||
82 | :arg node: the node to insert | ||
83 | |||
84 | :arg refNode: the child node to insert the node before | ||
85 | |||
86 | """ | ||
87 | raise NotImplementedError | ||
88 | |||
89 | def removeChild(self, node): | ||
90 | """Remove node from the children of the current node | ||
91 | |||
92 | :arg node: the child node to remove | ||
93 | |||
94 | """ | ||
95 | raise NotImplementedError | ||
96 | |||
97 | def reparentChildren(self, newParent): | ||
98 | """Move all the children of the current node to newParent. | ||
99 | This is needed so that trees that don't store text as nodes move the | ||
100 | text in the correct way | ||
101 | |||
102 | :arg newParent: the node to move all this node's children to | ||
103 | |||
104 | """ | ||
105 | # XXX - should this method be made more general? | ||
106 | for child in self.childNodes: | ||
107 | newParent.appendChild(child) | ||
108 | self.childNodes = [] | ||
109 | |||
110 | def cloneNode(self): | ||
111 | """Return a shallow copy of the current node i.e. a node with the same | ||
112 | name and attributes but with no parent or child nodes | ||
113 | """ | ||
114 | raise NotImplementedError | ||
115 | |||
116 | def hasContent(self): | ||
117 | """Return true if the node has children or text, false otherwise | ||
118 | """ | ||
119 | raise NotImplementedError | ||
120 | |||
121 | |||
122 | class ActiveFormattingElements(list): | ||
123 | def append(self, node): | ||
124 | equalCount = 0 | ||
125 | if node != Marker: | ||
126 | for element in self[::-1]: | ||
127 | if element == Marker: | ||
128 | break | ||
129 | if self.nodesEqual(element, node): | ||
130 | equalCount += 1 | ||
131 | if equalCount == 3: | ||
132 | self.remove(element) | ||
133 | break | ||
134 | list.append(self, node) | ||
135 | |||
136 | def nodesEqual(self, node1, node2): | ||
137 | if not node1.nameTuple == node2.nameTuple: | ||
138 | return False | ||
139 | |||
140 | if not node1.attributes == node2.attributes: | ||
141 | return False | ||
142 | |||
143 | return True | ||
144 | |||
145 | |||
146 | class TreeBuilder(object): | ||
147 | """Base treebuilder implementation | ||
148 | |||
149 | * documentClass - the class to use for the bottommost node of a document | ||
150 | * elementClass - the class to use for HTML Elements | ||
151 | * commentClass - the class to use for comments | ||
152 | * doctypeClass - the class to use for doctypes | ||
153 | |||
154 | """ | ||
155 | # pylint:disable=not-callable | ||
156 | |||
157 | # Document class | ||
158 | documentClass = None | ||
159 | |||
160 | # The class to use for creating a node | ||
161 | elementClass = None | ||
162 | |||
163 | # The class to use for creating comments | ||
164 | commentClass = None | ||
165 | |||
166 | # The class to use for creating doctypes | ||
167 | doctypeClass = None | ||
168 | |||
169 | # Fragment class | ||
170 | fragmentClass = None | ||
171 | |||
172 | def __init__(self, namespaceHTMLElements): | ||
173 | """Create a TreeBuilder | ||
174 | |||
175 | :arg namespaceHTMLElements: whether or not to namespace HTML elements | ||
176 | |||
177 | """ | ||
178 | if namespaceHTMLElements: | ||
179 | self.defaultNamespace = "http://www.w3.org/1999/xhtml" | ||
180 | else: | ||
181 | self.defaultNamespace = None | ||
182 | self.reset() | ||
183 | |||
184 | def reset(self): | ||
185 | self.openElements = [] | ||
186 | self.activeFormattingElements = ActiveFormattingElements() | ||
187 | |||
188 | # XXX - rename these to headElement, formElement | ||
189 | self.headPointer = None | ||
190 | self.formPointer = None | ||
191 | |||
192 | self.insertFromTable = False | ||
193 | |||
194 | self.document = self.documentClass() | ||
195 | |||
196 | def elementInScope(self, target, variant=None): | ||
197 | |||
198 | # If we pass a node in we match that. if we pass a string | ||
199 | # match any node with that name | ||
200 | exactNode = hasattr(target, "nameTuple") | ||
201 | if not exactNode: | ||
202 | if isinstance(target, text_type): | ||
203 | target = (namespaces["html"], target) | ||
204 | assert isinstance(target, tuple) | ||
205 | |||
206 | listElements, invert = listElementsMap[variant] | ||
207 | |||
208 | for node in reversed(self.openElements): | ||
209 | if exactNode and node == target: | ||
210 | return True | ||
211 | elif not exactNode and node.nameTuple == target: | ||
212 | return True | ||
213 | elif (invert ^ (node.nameTuple in listElements)): | ||
214 | return False | ||
215 | |||
216 | assert False # We should never reach this point | ||
217 | |||
218 | def reconstructActiveFormattingElements(self): | ||
219 | # Within this algorithm the order of steps described in the | ||
220 | # specification is not quite the same as the order of steps in the | ||
221 | # code. It should still do the same though. | ||
222 | |||
223 | # Step 1: stop the algorithm when there's nothing to do. | ||
224 | if not self.activeFormattingElements: | ||
225 | return | ||
226 | |||
227 | # Step 2 and step 3: we start with the last element. So i is -1. | ||
228 | i = len(self.activeFormattingElements) - 1 | ||
229 | entry = self.activeFormattingElements[i] | ||
230 | if entry == Marker or entry in self.openElements: | ||
231 | return | ||
232 | |||
233 | # Step 6 | ||
234 | while entry != Marker and entry not in self.openElements: | ||
235 | if i == 0: | ||
236 | # This will be reset to 0 below | ||
237 | i = -1 | ||
238 | break | ||
239 | i -= 1 | ||
240 | # Step 5: let entry be one earlier in the list. | ||
241 | entry = self.activeFormattingElements[i] | ||
242 | |||
243 | while True: | ||
244 | # Step 7 | ||
245 | i += 1 | ||
246 | |||
247 | # Step 8 | ||
248 | entry = self.activeFormattingElements[i] | ||
249 | clone = entry.cloneNode() # Mainly to get a new copy of the attributes | ||
250 | |||
251 | # Step 9 | ||
252 | element = self.insertElement({"type": "StartTag", | ||
253 | "name": clone.name, | ||
254 | "namespace": clone.namespace, | ||
255 | "data": clone.attributes}) | ||
256 | |||
257 | # Step 10 | ||
258 | self.activeFormattingElements[i] = element | ||
259 | |||
260 | # Step 11 | ||
261 | if element == self.activeFormattingElements[-1]: | ||
262 | break | ||
263 | |||
264 | def clearActiveFormattingElements(self): | ||
265 | entry = self.activeFormattingElements.pop() | ||
266 | while self.activeFormattingElements and entry != Marker: | ||
267 | entry = self.activeFormattingElements.pop() | ||
268 | |||
269 | def elementInActiveFormattingElements(self, name): | ||
270 | """Check if an element exists between the end of the active | ||
271 | formatting elements and the last marker. If it does, return it, else | ||
272 | return false""" | ||
273 | |||
274 | for item in self.activeFormattingElements[::-1]: | ||
275 | # Check for Marker first because if it's a Marker it doesn't have a | ||
276 | # name attribute. | ||
277 | if item == Marker: | ||
278 | break | ||
279 | elif item.name == name: | ||
280 | return item | ||
281 | return False | ||
282 | |||
283 | def insertRoot(self, token): | ||
284 | element = self.createElement(token) | ||
285 | self.openElements.append(element) | ||
286 | self.document.appendChild(element) | ||
287 | |||
288 | def insertDoctype(self, token): | ||
289 | name = token["name"] | ||
290 | publicId = token["publicId"] | ||
291 | systemId = token["systemId"] | ||
292 | |||
293 | doctype = self.doctypeClass(name, publicId, systemId) | ||
294 | self.document.appendChild(doctype) | ||
295 | |||
296 | def insertComment(self, token, parent=None): | ||
297 | if parent is None: | ||
298 | parent = self.openElements[-1] | ||
299 | parent.appendChild(self.commentClass(token["data"])) | ||
300 | |||
301 | def createElement(self, token): | ||
302 | """Create an element but don't insert it anywhere""" | ||
303 | name = token["name"] | ||
304 | namespace = token.get("namespace", self.defaultNamespace) | ||
305 | element = self.elementClass(name, namespace) | ||
306 | element.attributes = token["data"] | ||
307 | return element | ||
308 | |||
309 | def _getInsertFromTable(self): | ||
310 | return self._insertFromTable | ||
311 | |||
312 | def _setInsertFromTable(self, value): | ||
313 | """Switch the function used to insert an element from the | ||
314 | normal one to the misnested table one and back again""" | ||
315 | self._insertFromTable = value | ||
316 | if value: | ||
317 | self.insertElement = self.insertElementTable | ||
318 | else: | ||
319 | self.insertElement = self.insertElementNormal | ||
320 | |||
321 | insertFromTable = property(_getInsertFromTable, _setInsertFromTable) | ||
322 | |||
323 | def insertElementNormal(self, token): | ||
324 | name = token["name"] | ||
325 | assert isinstance(name, text_type), "Element %s not unicode" % name | ||
326 | namespace = token.get("namespace", self.defaultNamespace) | ||
327 | element = self.elementClass(name, namespace) | ||
328 | element.attributes = token["data"] | ||
329 | self.openElements[-1].appendChild(element) | ||
330 | self.openElements.append(element) | ||
331 | return element | ||
332 | |||
333 | def insertElementTable(self, token): | ||
334 | """Create an element and insert it into the tree""" | ||
335 | element = self.createElement(token) | ||
336 | if self.openElements[-1].name not in tableInsertModeElements: | ||
337 | return self.insertElementNormal(token) | ||
338 | else: | ||
339 | # We should be in the InTable mode. This means we want to do | ||
340 | # special magic element rearranging | ||
341 | parent, insertBefore = self.getTableMisnestedNodePosition() | ||
342 | if insertBefore is None: | ||
343 | parent.appendChild(element) | ||
344 | else: | ||
345 | parent.insertBefore(element, insertBefore) | ||
346 | self.openElements.append(element) | ||
347 | return element | ||
348 | |||
349 | def insertText(self, data, parent=None): | ||
350 | """Insert text data.""" | ||
351 | if parent is None: | ||
352 | parent = self.openElements[-1] | ||
353 | |||
354 | if (not self.insertFromTable or (self.insertFromTable and | ||
355 | self.openElements[-1].name | ||
356 | not in tableInsertModeElements)): | ||
357 | parent.insertText(data) | ||
358 | else: | ||
359 | # We should be in the InTable mode. This means we want to do | ||
360 | # special magic element rearranging | ||
361 | parent, insertBefore = self.getTableMisnestedNodePosition() | ||
362 | parent.insertText(data, insertBefore) | ||
363 | |||
364 | def getTableMisnestedNodePosition(self): | ||
365 | """Get the foster parent element, and sibling to insert before | ||
366 | (or None) when inserting a misnested table node""" | ||
367 | # The foster parent element is the one which comes before the most | ||
368 | # recently opened table element | ||
369 | # XXX - this is really inelegant | ||
370 | lastTable = None | ||
371 | fosterParent = None | ||
372 | insertBefore = None | ||
373 | for elm in self.openElements[::-1]: | ||
374 | if elm.name == "table": | ||
375 | lastTable = elm | ||
376 | break | ||
377 | if lastTable: | ||
378 | # XXX - we should really check that this parent is actually a | ||
379 | # node here | ||
380 | if lastTable.parent: | ||
381 | fosterParent = lastTable.parent | ||
382 | insertBefore = lastTable | ||
383 | else: | ||
384 | fosterParent = self.openElements[ | ||
385 | self.openElements.index(lastTable) - 1] | ||
386 | else: | ||
387 | fosterParent = self.openElements[0] | ||
388 | return fosterParent, insertBefore | ||
389 | |||
390 | def generateImpliedEndTags(self, exclude=None): | ||
391 | name = self.openElements[-1].name | ||
392 | # XXX td, th and tr are not actually needed | ||
393 | if (name in frozenset(("dd", "dt", "li", "option", "optgroup", "p", "rp", "rt")) and | ||
394 | name != exclude): | ||
395 | self.openElements.pop() | ||
396 | # XXX This is not entirely what the specification says. We should | ||
397 | # investigate it more closely. | ||
398 | self.generateImpliedEndTags(exclude) | ||
399 | |||
400 | def getDocument(self): | ||
401 | """Return the final tree""" | ||
402 | return self.document | ||
403 | |||
404 | def getFragment(self): | ||
405 | """Return the final fragment""" | ||
406 | # assert self.innerHTML | ||
407 | fragment = self.fragmentClass() | ||
408 | self.openElements[0].reparentChildren(fragment) | ||
409 | return fragment | ||
410 | |||
411 | def testSerializer(self, node): | ||
412 | """Serialize the subtree of node in the format required by unit tests | ||
413 | |||
414 | :arg node: the node from which to start serializing | ||
415 | |||
416 | """ | ||
417 | raise NotImplementedError | ||
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/dom.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/dom.py deleted file mode 100644 index 8117b2d..0000000 --- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/dom.py +++ /dev/null | |||
@@ -1,236 +0,0 @@ | |||
1 | from __future__ import absolute_import, division, unicode_literals | ||
2 | |||
3 | |||
4 | from collections import MutableMapping | ||
5 | from xml.dom import minidom, Node | ||
6 | import weakref | ||
7 | |||
8 | from . import base | ||
9 | from .. import constants | ||
10 | from ..constants import namespaces | ||
11 | from .._utils import moduleFactoryFactory | ||
12 | |||
13 | |||
14 | def getDomBuilder(DomImplementation): | ||
15 | Dom = DomImplementation | ||
16 | |||
17 | class AttrList(MutableMapping): | ||
18 | def __init__(self, element): | ||
19 | self.element = element | ||
20 | |||
21 | def __iter__(self): | ||
22 | return iter(self.element.attributes.keys()) | ||
23 | |||
24 | def __setitem__(self, name, value): | ||
25 | if isinstance(name, tuple): | ||
26 | raise NotImplementedError | ||
27 | else: | ||
28 | attr = self.element.ownerDocument.createAttribute(name) | ||
29 | attr.value = value | ||
30 | self.element.attributes[name] = attr | ||
31 | |||
32 | def __len__(self): | ||
33 | return len(self.element.attributes) | ||
34 | |||
35 | def items(self): | ||
36 | return list(self.element.attributes.items()) | ||
37 | |||
38 | def values(self): | ||
39 | return list(self.element.attributes.values()) | ||
40 | |||
41 | def __getitem__(self, name): | ||
42 | if isinstance(name, tuple): | ||
43 | raise NotImplementedError | ||
44 | else: | ||
45 | return self.element.attributes[name].value | ||
46 | |||
47 | def __delitem__(self, name): | ||
48 | if isinstance(name, tuple): | ||
49 | raise NotImplementedError | ||
50 | else: | ||
51 | del self.element.attributes[name] | ||
52 | |||
53 | class NodeBuilder(base.Node): | ||
54 | def __init__(self, element): | ||
55 | base.Node.__init__(self, element.nodeName) | ||
56 | self.element = element | ||
57 | |||
58 | namespace = property(lambda self: hasattr(self.element, "namespaceURI") and | ||
59 | self.element.namespaceURI or None) | ||
60 | |||
61 | def appendChild(self, node): | ||
62 | node.parent = self | ||
63 | self.element.appendChild(node.element) | ||
64 | |||
65 | def insertText(self, data, insertBefore=None): | ||
66 | text = self.element.ownerDocument.createTextNode(data) | ||
67 | if insertBefore: | ||
68 | self.element.insertBefore(text, insertBefore.element) | ||
69 | else: | ||
70 | self.element.appendChild(text) | ||
71 | |||
72 | def insertBefore(self, node, refNode): | ||
73 | self.element.insertBefore(node.element, refNode.element) | ||
74 | node.parent = self | ||
75 | |||
76 | def removeChild(self, node): | ||
77 | if node.element.parentNode == self.element: | ||
78 | self.element.removeChild(node.element) | ||
79 | node.parent = None | ||
80 | |||
81 | def reparentChildren(self, newParent): | ||
82 | while self.element.hasChildNodes(): | ||
83 | child = self.element.firstChild | ||
84 | self.element.removeChild(child) | ||
85 | newParent.element.appendChild(child) | ||
86 | self.childNodes = [] | ||
87 | |||
88 | def getAttributes(self): | ||
89 | return AttrList(self.element) | ||
90 | |||
91 | def setAttributes(self, attributes): | ||
92 | if attributes: | ||
93 | for name, value in list(attributes.items()): | ||
94 | if isinstance(name, tuple): | ||
95 | if name[0] is not None: | ||
96 | qualifiedName = (name[0] + ":" + name[1]) | ||
97 | else: | ||
98 | qualifiedName = name[1] | ||
99 | self.element.setAttributeNS(name[2], qualifiedName, | ||
100 | value) | ||
101 | else: | ||
102 | self.element.setAttribute( | ||
103 | name, value) | ||
104 | attributes = property(getAttributes, setAttributes) | ||
105 | |||
106 | def cloneNode(self): | ||
107 | return NodeBuilder(self.element.cloneNode(False)) | ||
108 | |||
109 | def hasContent(self): | ||
110 | return self.element.hasChildNodes() | ||
111 | |||
112 | def getNameTuple(self): | ||
113 | if self.namespace is None: | ||
114 | return namespaces["html"], self.name | ||
115 | else: | ||
116 | return self.namespace, self.name | ||
117 | |||
118 | nameTuple = property(getNameTuple) | ||
119 | |||
120 | class TreeBuilder(base.TreeBuilder): # pylint:disable=unused-variable | ||
121 | def documentClass(self): | ||
122 | self.dom = Dom.getDOMImplementation().createDocument(None, None, None) | ||
123 | return weakref.proxy(self) | ||
124 | |||
125 | def insertDoctype(self, token): | ||
126 | name = token["name"] | ||
127 | publicId = token["publicId"] | ||
128 | systemId = token["systemId"] | ||
129 | |||
130 | domimpl = Dom.getDOMImplementation() | ||
131 | doctype = domimpl.createDocumentType(name, publicId, systemId) | ||
132 | self.document.appendChild(NodeBuilder(doctype)) | ||
133 | if Dom == minidom: | ||
134 | doctype.ownerDocument = self.dom | ||
135 | |||
136 | def elementClass(self, name, namespace=None): | ||
137 | if namespace is None and self.defaultNamespace is None: | ||
138 | node = self.dom.createElement(name) | ||
139 | else: | ||
140 | node = self.dom.createElementNS(namespace, name) | ||
141 | |||
142 | return NodeBuilder(node) | ||
143 | |||
144 | def commentClass(self, data): | ||
145 | return NodeBuilder(self.dom.createComment(data)) | ||
146 | |||
147 | def fragmentClass(self): | ||
148 | return NodeBuilder(self.dom.createDocumentFragment()) | ||
149 | |||
150 | def appendChild(self, node): | ||
151 | self.dom.appendChild(node.element) | ||
152 | |||
153 | def testSerializer(self, element): | ||
154 | return testSerializer(element) | ||
155 | |||
156 | def getDocument(self): | ||
157 | return self.dom | ||
158 | |||
159 | def getFragment(self): | ||
160 | return base.TreeBuilder.getFragment(self).element | ||
161 | |||
162 | def insertText(self, data, parent=None): | ||
163 | data = data | ||
164 | if parent != self: | ||
165 | base.TreeBuilder.insertText(self, data, parent) | ||
166 | else: | ||
167 | # HACK: allow text nodes as children of the document node | ||
168 | if hasattr(self.dom, '_child_node_types'): | ||
169 | # pylint:disable=protected-access | ||
170 | if Node.TEXT_NODE not in self.dom._child_node_types: | ||
171 | self.dom._child_node_types = list(self.dom._child_node_types) | ||
172 | self.dom._child_node_types.append(Node.TEXT_NODE) | ||
173 | self.dom.appendChild(self.dom.createTextNode(data)) | ||
174 | |||
175 | implementation = DomImplementation | ||
176 | name = None | ||
177 | |||
178 | def testSerializer(element): | ||
179 | element.normalize() | ||
180 | rv = [] | ||
181 | |||
182 | def serializeElement(element, indent=0): | ||
183 | if element.nodeType == Node.DOCUMENT_TYPE_NODE: | ||
184 | if element.name: | ||
185 | if element.publicId or element.systemId: | ||
186 | publicId = element.publicId or "" | ||
187 | systemId = element.systemId or "" | ||
188 | rv.append("""|%s<!DOCTYPE %s "%s" "%s">""" % | ||
189 | (' ' * indent, element.name, publicId, systemId)) | ||
190 | else: | ||
191 | rv.append("|%s<!DOCTYPE %s>" % (' ' * indent, element.name)) | ||
192 | else: | ||
193 | rv.append("|%s<!DOCTYPE >" % (' ' * indent,)) | ||
194 | elif element.nodeType == Node.DOCUMENT_NODE: | ||
195 | rv.append("#document") | ||
196 | elif element.nodeType == Node.DOCUMENT_FRAGMENT_NODE: | ||
197 | rv.append("#document-fragment") | ||
198 | elif element.nodeType == Node.COMMENT_NODE: | ||
199 | rv.append("|%s<!-- %s -->" % (' ' * indent, element.nodeValue)) | ||
200 | elif element.nodeType == Node.TEXT_NODE: | ||
201 | rv.append("|%s\"%s\"" % (' ' * indent, element.nodeValue)) | ||
202 | else: | ||
203 | if (hasattr(element, "namespaceURI") and | ||
204 | element.namespaceURI is not None): | ||
205 | name = "%s %s" % (constants.prefixes[element.namespaceURI], | ||
206 | element.nodeName) | ||
207 | else: | ||
208 | name = element.nodeName | ||
209 | rv.append("|%s<%s>" % (' ' * indent, name)) | ||
210 | if element.hasAttributes(): | ||
211 | attributes = [] | ||
212 | for i in range(len(element.attributes)): | ||
213 | attr = element.attributes.item(i) | ||
214 | name = attr.nodeName | ||
215 | value = attr.value | ||
216 | ns = attr.namespaceURI | ||
217 | if ns: | ||
218 | name = "%s %s" % (constants.prefixes[ns], attr.localName) | ||
219 | else: | ||
220 | name = attr.nodeName | ||
221 | attributes.append((name, value)) | ||
222 | |||
223 | for name, value in sorted(attributes): | ||
224 | rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) | ||
225 | indent += 2 | ||
226 | for child in element.childNodes: | ||
227 | serializeElement(child, indent) | ||
228 | serializeElement(element, 0) | ||
229 | |||
230 | return "\n".join(rv) | ||
231 | |||
232 | return locals() | ||
233 | |||
234 | |||
235 | # The actual means to get a module! | ||
236 | getDomModule = moduleFactoryFactory(getDomBuilder) | ||
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree.py deleted file mode 100644 index 9a4aa95..0000000 --- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree.py +++ /dev/null | |||
@@ -1,340 +0,0 @@ | |||
1 | from __future__ import absolute_import, division, unicode_literals | ||
2 | # pylint:disable=protected-access | ||
3 | |||
4 | from pip._vendor.six import text_type | ||
5 | |||
6 | import re | ||
7 | |||
8 | from . import base | ||
9 | from .. import _ihatexml | ||
10 | from .. import constants | ||
11 | from ..constants import namespaces | ||
12 | from .._utils import moduleFactoryFactory | ||
13 | |||
14 | tag_regexp = re.compile("{([^}]*)}(.*)") | ||
15 | |||
16 | |||
17 | def getETreeBuilder(ElementTreeImplementation, fullTree=False): | ||
18 | ElementTree = ElementTreeImplementation | ||
19 | ElementTreeCommentType = ElementTree.Comment("asd").tag | ||
20 | |||
21 | class Element(base.Node): | ||
22 | def __init__(self, name, namespace=None): | ||
23 | self._name = name | ||
24 | self._namespace = namespace | ||
25 | self._element = ElementTree.Element(self._getETreeTag(name, | ||
26 | namespace)) | ||
27 | if namespace is None: | ||
28 | self.nameTuple = namespaces["html"], self._name | ||
29 | else: | ||
30 | self.nameTuple = self._namespace, self._name | ||
31 | self.parent = None | ||
32 | self._childNodes = [] | ||
33 | self._flags = [] | ||
34 | |||
35 | def _getETreeTag(self, name, namespace): | ||
36 | if namespace is None: | ||
37 | etree_tag = name | ||
38 | else: | ||
39 | etree_tag = "{%s}%s" % (namespace, name) | ||
40 | return etree_tag | ||
41 | |||
42 | def _setName(self, name): | ||
43 | self._name = name | ||
44 | self._element.tag = self._getETreeTag(self._name, self._namespace) | ||
45 | |||
46 | def _getName(self): | ||
47 | return self._name | ||
48 | |||
49 | name = property(_getName, _setName) | ||
50 | |||
51 | def _setNamespace(self, namespace): | ||
52 | self._namespace = namespace | ||
53 | self._element.tag = self._getETreeTag(self._name, self._namespace) | ||
54 | |||
55 | def _getNamespace(self): | ||
56 | return self._namespace | ||
57 | |||
58 | namespace = property(_getNamespace, _setNamespace) | ||
59 | |||
60 | def _getAttributes(self): | ||
61 | return self._element.attrib | ||
62 | |||
63 | def _setAttributes(self, attributes): | ||
64 | # Delete existing attributes first | ||
65 | # XXX - there may be a better way to do this... | ||
66 | for key in list(self._element.attrib.keys()): | ||
67 | del self._element.attrib[key] | ||
68 | for key, value in attributes.items(): | ||
69 | if isinstance(key, tuple): | ||
70 | name = "{%s}%s" % (key[2], key[1]) | ||
71 | else: | ||
72 | name = key | ||
73 | self._element.set(name, value) | ||
74 | |||
75 | attributes = property(_getAttributes, _setAttributes) | ||
76 | |||
77 | def _getChildNodes(self): | ||
78 | return self._childNodes | ||
79 | |||
80 | def _setChildNodes(self, value): | ||
81 | del self._element[:] | ||
82 | self._childNodes = [] | ||
83 | for element in value: | ||
84 | self.insertChild(element) | ||
85 | |||
86 | childNodes = property(_getChildNodes, _setChildNodes) | ||
87 | |||
88 | def hasContent(self): | ||
89 | """Return true if the node has children or text""" | ||
90 | return bool(self._element.text or len(self._element)) | ||
91 | |||
92 | def appendChild(self, node): | ||
93 | self._childNodes.append(node) | ||
94 | self._element.append(node._element) | ||
95 | node.parent = self | ||
96 | |||
97 | def insertBefore(self, node, refNode): | ||
98 | index = list(self._element).index(refNode._element) | ||
99 | self._element.insert(index, node._element) | ||
100 | node.parent = self | ||
101 | |||
102 | def removeChild(self, node): | ||
103 | self._childNodes.remove(node) | ||
104 | self._element.remove(node._element) | ||
105 | node.parent = None | ||
106 | |||
107 | def insertText(self, data, insertBefore=None): | ||
108 | if not(len(self._element)): | ||
109 | if not self._element.text: | ||
110 | self._element.text = "" | ||
111 | self._element.text += data | ||
112 | elif insertBefore is None: | ||
113 | # Insert the text as the tail of the last child element | ||
114 | if not self._element[-1].tail: | ||
115 | self._element[-1].tail = "" | ||
116 | self._element[-1].tail += data | ||
117 | else: | ||
118 | # Insert the text before the specified node | ||
119 | children = list(self._element) | ||
120 | index = children.index(insertBefore._element) | ||
121 | if index > 0: | ||
122 | if not self._element[index - 1].tail: | ||
123 | self._element[index - 1].tail = "" | ||
124 | self._element[index - 1].tail += data | ||
125 | else: | ||
126 | if not self._element.text: | ||
127 | self._element.text = "" | ||
128 | self._element.text += data | ||
129 | |||
130 | def cloneNode(self): | ||
131 | element = type(self)(self.name, self.namespace) | ||
132 | for name, value in self.attributes.items(): | ||
133 | element.attributes[name] = value | ||
134 | return element | ||
135 | |||
136 | def reparentChildren(self, newParent): | ||
137 | if newParent.childNodes: | ||
138 | newParent.childNodes[-1]._element.tail += self._element.text | ||
139 | else: | ||
140 | if not newParent._element.text: | ||
141 | newParent._element.text = "" | ||
142 | if self._element.text is not None: | ||
143 | newParent._element.text += self._element.text | ||
144 | self._element.text = "" | ||
145 | base.Node.reparentChildren(self, newParent) | ||
146 | |||
147 | class Comment(Element): | ||
148 | def __init__(self, data): | ||
149 | # Use the superclass constructor to set all properties on the | ||
150 | # wrapper element | ||
151 | self._element = ElementTree.Comment(data) | ||
152 | self.parent = None | ||
153 | self._childNodes = [] | ||
154 | self._flags = [] | ||
155 | |||
156 | def _getData(self): | ||
157 | return self._element.text | ||
158 | |||
159 | def _setData(self, value): | ||
160 | self._element.text = value | ||
161 | |||
162 | data = property(_getData, _setData) | ||
163 | |||
164 | class DocumentType(Element): | ||
165 | def __init__(self, name, publicId, systemId): | ||
166 | Element.__init__(self, "<!DOCTYPE>") | ||
167 | self._element.text = name | ||
168 | self.publicId = publicId | ||
169 | self.systemId = systemId | ||
170 | |||
171 | def _getPublicId(self): | ||
172 | return self._element.get("publicId", "") | ||
173 | |||
174 | def _setPublicId(self, value): | ||
175 | if value is not None: | ||
176 | self._element.set("publicId", value) | ||
177 | |||
178 | publicId = property(_getPublicId, _setPublicId) | ||
179 | |||
180 | def _getSystemId(self): | ||
181 | return self._element.get("systemId", "") | ||
182 | |||
183 | def _setSystemId(self, value): | ||
184 | if value is not None: | ||
185 | self._element.set("systemId", value) | ||
186 | |||
187 | systemId = property(_getSystemId, _setSystemId) | ||
188 | |||
189 | class Document(Element): | ||
190 | def __init__(self): | ||
191 | Element.__init__(self, "DOCUMENT_ROOT") | ||
192 | |||
193 | class DocumentFragment(Element): | ||
194 | def __init__(self): | ||
195 | Element.__init__(self, "DOCUMENT_FRAGMENT") | ||
196 | |||
197 | def testSerializer(element): | ||
198 | rv = [] | ||
199 | |||
200 | def serializeElement(element, indent=0): | ||
201 | if not(hasattr(element, "tag")): | ||
202 | element = element.getroot() | ||
203 | if element.tag == "<!DOCTYPE>": | ||
204 | if element.get("publicId") or element.get("systemId"): | ||
205 | publicId = element.get("publicId") or "" | ||
206 | systemId = element.get("systemId") or "" | ||
207 | rv.append("""<!DOCTYPE %s "%s" "%s">""" % | ||
208 | (element.text, publicId, systemId)) | ||
209 | else: | ||
210 | rv.append("<!DOCTYPE %s>" % (element.text,)) | ||
211 | elif element.tag == "DOCUMENT_ROOT": | ||
212 | rv.append("#document") | ||
213 | if element.text is not None: | ||
214 | rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) | ||
215 | if element.tail is not None: | ||
216 | raise TypeError("Document node cannot have tail") | ||
217 | if hasattr(element, "attrib") and len(element.attrib): | ||
218 | raise TypeError("Document node cannot have attributes") | ||
219 | elif element.tag == ElementTreeCommentType: | ||
220 | rv.append("|%s<!-- %s -->" % (' ' * indent, element.text)) | ||
221 | else: | ||
222 | assert isinstance(element.tag, text_type), \ | ||
223 | "Expected unicode, got %s, %s" % (type(element.tag), element.tag) | ||
224 | nsmatch = tag_regexp.match(element.tag) | ||
225 | |||
226 | if nsmatch is None: | ||
227 | name = element.tag | ||
228 | else: | ||
229 | ns, name = nsmatch.groups() | ||
230 | prefix = constants.prefixes[ns] | ||
231 | name = "%s %s" % (prefix, name) | ||
232 | rv.append("|%s<%s>" % (' ' * indent, name)) | ||
233 | |||
234 | if hasattr(element, "attrib"): | ||
235 | attributes = [] | ||
236 | for name, value in element.attrib.items(): | ||
237 | nsmatch = tag_regexp.match(name) | ||
238 | if nsmatch is not None: | ||
239 | ns, name = nsmatch.groups() | ||
240 | prefix = constants.prefixes[ns] | ||
241 | attr_string = "%s %s" % (prefix, name) | ||
242 | else: | ||
243 | attr_string = name | ||
244 | attributes.append((attr_string, value)) | ||
245 | |||
246 | for name, value in sorted(attributes): | ||
247 | rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) | ||
248 | if element.text: | ||
249 | rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) | ||
250 | indent += 2 | ||
251 | for child in element: | ||
252 | serializeElement(child, indent) | ||
253 | if element.tail: | ||
254 | rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) | ||
255 | serializeElement(element, 0) | ||
256 | |||
257 | return "\n".join(rv) | ||
258 | |||
259 | def tostring(element): # pylint:disable=unused-variable | ||
260 | """Serialize an element and its child nodes to a string""" | ||
261 | rv = [] | ||
262 | filter = _ihatexml.InfosetFilter() | ||
263 | |||
264 | def serializeElement(element): | ||
265 | if isinstance(element, ElementTree.ElementTree): | ||
266 | element = element.getroot() | ||
267 | |||
268 | if element.tag == "<!DOCTYPE>": | ||
269 | if element.get("publicId") or element.get("systemId"): | ||
270 | publicId = element.get("publicId") or "" | ||
271 | systemId = element.get("systemId") or "" | ||
272 | rv.append("""<!DOCTYPE %s PUBLIC "%s" "%s">""" % | ||
273 | (element.text, publicId, systemId)) | ||
274 | else: | ||
275 | rv.append("<!DOCTYPE %s>" % (element.text,)) | ||
276 | elif element.tag == "DOCUMENT_ROOT": | ||
277 | if element.text is not None: | ||
278 | rv.append(element.text) | ||
279 | if element.tail is not None: | ||
280 | raise TypeError("Document node cannot have tail") | ||
281 | if hasattr(element, "attrib") and len(element.attrib): | ||
282 | raise TypeError("Document node cannot have attributes") | ||
283 | |||
284 | for child in element: | ||
285 | serializeElement(child) | ||
286 | |||
287 | elif element.tag == ElementTreeCommentType: | ||
288 | rv.append("<!--%s-->" % (element.text,)) | ||
289 | else: | ||
290 | # This is assumed to be an ordinary element | ||
291 | if not element.attrib: | ||
292 | rv.append("<%s>" % (filter.fromXmlName(element.tag),)) | ||
293 | else: | ||
294 | attr = " ".join(["%s=\"%s\"" % ( | ||
295 | filter.fromXmlName(name), value) | ||
296 | for name, value in element.attrib.items()]) | ||
297 | rv.append("<%s %s>" % (element.tag, attr)) | ||
298 | if element.text: | ||
299 | rv.append(element.text) | ||
300 | |||
301 | for child in element: | ||
302 | serializeElement(child) | ||
303 | |||
304 | rv.append("</%s>" % (element.tag,)) | ||
305 | |||
306 | if element.tail: | ||
307 | rv.append(element.tail) | ||
308 | |||
309 | serializeElement(element) | ||
310 | |||
311 | return "".join(rv) | ||
312 | |||
313 | class TreeBuilder(base.TreeBuilder): # pylint:disable=unused-variable | ||
314 | documentClass = Document | ||
315 | doctypeClass = DocumentType | ||
316 | elementClass = Element | ||
317 | commentClass = Comment | ||
318 | fragmentClass = DocumentFragment | ||
319 | implementation = ElementTreeImplementation | ||
320 | |||
321 | def testSerializer(self, element): | ||
322 | return testSerializer(element) | ||
323 | |||
324 | def getDocument(self): | ||
325 | if fullTree: | ||
326 | return self.document._element | ||
327 | else: | ||
328 | if self.defaultNamespace is not None: | ||
329 | return self.document._element.find( | ||
330 | "{%s}html" % self.defaultNamespace) | ||
331 | else: | ||
332 | return self.document._element.find("html") | ||
333 | |||
334 | def getFragment(self): | ||
335 | return base.TreeBuilder.getFragment(self)._element | ||
336 | |||
337 | return locals() | ||
338 | |||
339 | |||
340 | getETreeModule = moduleFactoryFactory(getETreeBuilder) | ||
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree_lxml.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree_lxml.py deleted file mode 100644 index 66a9ba3..0000000 --- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree_lxml.py +++ /dev/null | |||
@@ -1,366 +0,0 @@ | |||
1 | """Module for supporting the lxml.etree library. The idea here is to use as much | ||
2 | of the native library as possible, without using fragile hacks like custom element | ||
3 | names that break between releases. The downside of this is that we cannot represent | ||
4 | all possible trees; specifically the following are known to cause problems: | ||
5 | |||
6 | Text or comments as siblings of the root element | ||
7 | Docypes with no name | ||
8 | |||
9 | When any of these things occur, we emit a DataLossWarning | ||
10 | """ | ||
11 | |||
12 | from __future__ import absolute_import, division, unicode_literals | ||
13 | # pylint:disable=protected-access | ||
14 | |||
15 | import warnings | ||
16 | import re | ||
17 | import sys | ||
18 | |||
19 | from . import base | ||
20 | from ..constants import DataLossWarning | ||
21 | from .. import constants | ||
22 | from . import etree as etree_builders | ||
23 | from .. import _ihatexml | ||
24 | |||
25 | import lxml.etree as etree | ||
26 | |||
27 | |||
28 | fullTree = True | ||
29 | tag_regexp = re.compile("{([^}]*)}(.*)") | ||
30 | |||
31 | comment_type = etree.Comment("asd").tag | ||
32 | |||
33 | |||
34 | class DocumentType(object): | ||
35 | def __init__(self, name, publicId, systemId): | ||
36 | self.name = name | ||
37 | self.publicId = publicId | ||
38 | self.systemId = systemId | ||
39 | |||
40 | |||
41 | class Document(object): | ||
42 | def __init__(self): | ||
43 | self._elementTree = None | ||
44 | self._childNodes = [] | ||
45 | |||
46 | def appendChild(self, element): | ||
47 | self._elementTree.getroot().addnext(element._element) | ||
48 | |||
49 | def _getChildNodes(self): | ||
50 | return self._childNodes | ||
51 | |||
52 | childNodes = property(_getChildNodes) | ||
53 | |||
54 | |||
55 | def testSerializer(element): | ||
56 | rv = [] | ||
57 | infosetFilter = _ihatexml.InfosetFilter(preventDoubleDashComments=True) | ||
58 | |||
59 | def serializeElement(element, indent=0): | ||
60 | if not hasattr(element, "tag"): | ||
61 | if hasattr(element, "getroot"): | ||
62 | # Full tree case | ||
63 | rv.append("#document") | ||
64 | if element.docinfo.internalDTD: | ||
65 | if not (element.docinfo.public_id or | ||
66 | element.docinfo.system_url): | ||
67 | dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name | ||
68 | else: | ||
69 | dtd_str = """<!DOCTYPE %s "%s" "%s">""" % ( | ||
70 | element.docinfo.root_name, | ||
71 | element.docinfo.public_id, | ||
72 | element.docinfo.system_url) | ||
73 | rv.append("|%s%s" % (' ' * (indent + 2), dtd_str)) | ||
74 | next_element = element.getroot() | ||
75 | while next_element.getprevious() is not None: | ||
76 | next_element = next_element.getprevious() | ||
77 | while next_element is not None: | ||
78 | serializeElement(next_element, indent + 2) | ||
79 | next_element = next_element.getnext() | ||
80 | elif isinstance(element, str) or isinstance(element, bytes): | ||
81 | # Text in a fragment | ||
82 | assert isinstance(element, str) or sys.version_info[0] == 2 | ||
83 | rv.append("|%s\"%s\"" % (' ' * indent, element)) | ||
84 | else: | ||
85 | # Fragment case | ||
86 | rv.append("#document-fragment") | ||
87 | for next_element in element: | ||
88 | serializeElement(next_element, indent + 2) | ||
89 | elif element.tag == comment_type: | ||
90 | rv.append("|%s<!-- %s -->" % (' ' * indent, element.text)) | ||
91 | if hasattr(element, "tail") and element.tail: | ||
92 | rv.append("|%s\"%s\"" % (' ' * indent, element.tail)) | ||
93 | else: | ||
94 | assert isinstance(element, etree._Element) | ||
95 | nsmatch = etree_builders.tag_regexp.match(element.tag) | ||
96 | if nsmatch is not None: | ||
97 | ns = nsmatch.group(1) | ||
98 | tag = nsmatch.group(2) | ||
99 | prefix = constants.prefixes[ns] | ||
100 | rv.append("|%s<%s %s>" % (' ' * indent, prefix, | ||
101 | infosetFilter.fromXmlName(tag))) | ||
102 | else: | ||
103 | rv.append("|%s<%s>" % (' ' * indent, | ||
104 | infosetFilter.fromXmlName(element.tag))) | ||
105 | |||
106 | if hasattr(element, "attrib"): | ||
107 | attributes = [] | ||
108 | for name, value in element.attrib.items(): | ||
109 | nsmatch = tag_regexp.match(name) | ||
110 | if nsmatch is not None: | ||
111 | ns, name = nsmatch.groups() | ||
112 | name = infosetFilter.fromXmlName(name) | ||
113 | prefix = constants.prefixes[ns] | ||
114 | attr_string = "%s %s" % (prefix, name) | ||
115 | else: | ||
116 | attr_string = infosetFilter.fromXmlName(name) | ||
117 | attributes.append((attr_string, value)) | ||
118 | |||
119 | for name, value in sorted(attributes): | ||
120 | rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) | ||
121 | |||
122 | if element.text: | ||
123 | rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) | ||
124 | indent += 2 | ||
125 | for child in element: | ||
126 | serializeElement(child, indent) | ||
127 | if hasattr(element, "tail") and element.tail: | ||
128 | rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) | ||
129 | serializeElement(element, 0) | ||
130 | |||
131 | return "\n".join(rv) | ||
132 | |||
133 | |||
134 | def tostring(element): | ||
135 | """Serialize an element and its child nodes to a string""" | ||
136 | rv = [] | ||
137 | |||
138 | def serializeElement(element): | ||
139 | if not hasattr(element, "tag"): | ||
140 | if element.docinfo.internalDTD: | ||
141 | if element.docinfo.doctype: | ||
142 | dtd_str = element.docinfo.doctype | ||
143 | else: | ||
144 | dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name | ||
145 | rv.append(dtd_str) | ||
146 | serializeElement(element.getroot()) | ||
147 | |||
148 | elif element.tag == comment_type: | ||
149 | rv.append("<!--%s-->" % (element.text,)) | ||
150 | |||
151 | else: | ||
152 | # This is assumed to be an ordinary element | ||
153 | if not element.attrib: | ||
154 | rv.append("<%s>" % (element.tag,)) | ||
155 | else: | ||
156 | attr = " ".join(["%s=\"%s\"" % (name, value) | ||
157 | for name, value in element.attrib.items()]) | ||
158 | rv.append("<%s %s>" % (element.tag, attr)) | ||
159 | if element.text: | ||
160 | rv.append(element.text) | ||
161 | |||
162 | for child in element: | ||
163 | serializeElement(child) | ||
164 | |||
165 | rv.append("</%s>" % (element.tag,)) | ||
166 | |||
167 | if hasattr(element, "tail") and element.tail: | ||
168 | rv.append(element.tail) | ||
169 | |||
170 | serializeElement(element) | ||
171 | |||
172 | return "".join(rv) | ||
173 | |||
174 | |||
175 | class TreeBuilder(base.TreeBuilder): | ||
176 | documentClass = Document | ||
177 | doctypeClass = DocumentType | ||
178 | elementClass = None | ||
179 | commentClass = None | ||
180 | fragmentClass = Document | ||
181 | implementation = etree | ||
182 | |||
183 | def __init__(self, namespaceHTMLElements, fullTree=False): | ||
184 | builder = etree_builders.getETreeModule(etree, fullTree=fullTree) | ||
185 | infosetFilter = self.infosetFilter = _ihatexml.InfosetFilter(preventDoubleDashComments=True) | ||
186 | self.namespaceHTMLElements = namespaceHTMLElements | ||
187 | |||
188 | class Attributes(dict): | ||
189 | def __init__(self, element, value=None): | ||
190 | if value is None: | ||
191 | value = {} | ||
192 | self._element = element | ||
193 | dict.__init__(self, value) # pylint:disable=non-parent-init-called | ||
194 | for key, value in self.items(): | ||
195 | if isinstance(key, tuple): | ||
196 | name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) | ||
197 | else: | ||
198 | name = infosetFilter.coerceAttribute(key) | ||
199 | self._element._element.attrib[name] = value | ||
200 | |||
201 | def __setitem__(self, key, value): | ||
202 | dict.__setitem__(self, key, value) | ||
203 | if isinstance(key, tuple): | ||
204 | name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) | ||
205 | else: | ||
206 | name = infosetFilter.coerceAttribute(key) | ||
207 | self._element._element.attrib[name] = value | ||
208 | |||
209 | class Element(builder.Element): | ||
210 | def __init__(self, name, namespace): | ||
211 | name = infosetFilter.coerceElement(name) | ||
212 | builder.Element.__init__(self, name, namespace=namespace) | ||
213 | self._attributes = Attributes(self) | ||
214 | |||
215 | def _setName(self, name): | ||
216 | self._name = infosetFilter.coerceElement(name) | ||
217 | self._element.tag = self._getETreeTag( | ||
218 | self._name, self._namespace) | ||
219 | |||
220 | def _getName(self): | ||
221 | return infosetFilter.fromXmlName(self._name) | ||
222 | |||
223 | name = property(_getName, _setName) | ||
224 | |||
225 | def _getAttributes(self): | ||
226 | return self._attributes | ||
227 | |||
228 | def _setAttributes(self, attributes): | ||
229 | self._attributes = Attributes(self, attributes) | ||
230 | |||
231 | attributes = property(_getAttributes, _setAttributes) | ||
232 | |||
233 | def insertText(self, data, insertBefore=None): | ||
234 | data = infosetFilter.coerceCharacters(data) | ||
235 | builder.Element.insertText(self, data, insertBefore) | ||
236 | |||
237 | def appendChild(self, child): | ||
238 | builder.Element.appendChild(self, child) | ||
239 | |||
240 | class Comment(builder.Comment): | ||
241 | def __init__(self, data): | ||
242 | data = infosetFilter.coerceComment(data) | ||
243 | builder.Comment.__init__(self, data) | ||
244 | |||
245 | def _setData(self, data): | ||
246 | data = infosetFilter.coerceComment(data) | ||
247 | self._element.text = data | ||
248 | |||
249 | def _getData(self): | ||
250 | return self._element.text | ||
251 | |||
252 | data = property(_getData, _setData) | ||
253 | |||
254 | self.elementClass = Element | ||
255 | self.commentClass = Comment | ||
256 | # self.fragmentClass = builder.DocumentFragment | ||
257 | base.TreeBuilder.__init__(self, namespaceHTMLElements) | ||
258 | |||
259 | def reset(self): | ||
260 | base.TreeBuilder.reset(self) | ||
261 | self.insertComment = self.insertCommentInitial | ||
262 | self.initial_comments = [] | ||
263 | self.doctype = None | ||
264 | |||
265 | def testSerializer(self, element): | ||
266 | return testSerializer(element) | ||
267 | |||
268 | def getDocument(self): | ||
269 | if fullTree: | ||
270 | return self.document._elementTree | ||
271 | else: | ||
272 | return self.document._elementTree.getroot() | ||
273 | |||
274 | def getFragment(self): | ||
275 | fragment = [] | ||
276 | element = self.openElements[0]._element | ||
277 | if element.text: | ||
278 | fragment.append(element.text) | ||
279 | fragment.extend(list(element)) | ||
280 | if element.tail: | ||
281 | fragment.append(element.tail) | ||
282 | return fragment | ||
283 | |||
284 | def insertDoctype(self, token): | ||
285 | name = token["name"] | ||
286 | publicId = token["publicId"] | ||
287 | systemId = token["systemId"] | ||
288 | |||
289 | if not name: | ||
290 | warnings.warn("lxml cannot represent empty doctype", DataLossWarning) | ||
291 | self.doctype = None | ||
292 | else: | ||
293 | coercedName = self.infosetFilter.coerceElement(name) | ||
294 | if coercedName != name: | ||
295 | warnings.warn("lxml cannot represent non-xml doctype", DataLossWarning) | ||
296 | |||
297 | doctype = self.doctypeClass(coercedName, publicId, systemId) | ||
298 | self.doctype = doctype | ||
299 | |||
300 | def insertCommentInitial(self, data, parent=None): | ||
301 | assert parent is None or parent is self.document | ||
302 | assert self.document._elementTree is None | ||
303 | self.initial_comments.append(data) | ||
304 | |||
305 | def insertCommentMain(self, data, parent=None): | ||
306 | if (parent == self.document and | ||
307 | self.document._elementTree.getroot()[-1].tag == comment_type): | ||
308 | warnings.warn("lxml cannot represent adjacent comments beyond the root elements", DataLossWarning) | ||
309 | super(TreeBuilder, self).insertComment(data, parent) | ||
310 | |||
311 | def insertRoot(self, token): | ||
312 | # Because of the way libxml2 works, it doesn't seem to be possible to | ||
313 | # alter information like the doctype after the tree has been parsed. | ||
314 | # Therefore we need to use the built-in parser to create our initial | ||
315 | # tree, after which we can add elements like normal | ||
316 | docStr = "" | ||
317 | if self.doctype: | ||
318 | assert self.doctype.name | ||
319 | docStr += "<!DOCTYPE %s" % self.doctype.name | ||
320 | if (self.doctype.publicId is not None or | ||
321 | self.doctype.systemId is not None): | ||
322 | docStr += (' PUBLIC "%s" ' % | ||
323 | (self.infosetFilter.coercePubid(self.doctype.publicId or ""))) | ||
324 | if self.doctype.systemId: | ||
325 | sysid = self.doctype.systemId | ||
326 | if sysid.find("'") >= 0 and sysid.find('"') >= 0: | ||
327 | warnings.warn("DOCTYPE system cannot contain single and double quotes", DataLossWarning) | ||
328 | sysid = sysid.replace("'", 'U00027') | ||
329 | if sysid.find("'") >= 0: | ||
330 | docStr += '"%s"' % sysid | ||
331 | else: | ||
332 | docStr += "'%s'" % sysid | ||
333 | else: | ||
334 | docStr += "''" | ||
335 | docStr += ">" | ||
336 | if self.doctype.name != token["name"]: | ||
337 | warnings.warn("lxml cannot represent doctype with a different name to the root element", DataLossWarning) | ||
338 | docStr += "<THIS_SHOULD_NEVER_APPEAR_PUBLICLY/>" | ||
339 | root = etree.fromstring(docStr) | ||
340 | |||
341 | # Append the initial comments: | ||
342 | for comment_token in self.initial_comments: | ||
343 | comment = self.commentClass(comment_token["data"]) | ||
344 | root.addprevious(comment._element) | ||
345 | |||
346 | # Create the root document and add the ElementTree to it | ||
347 | self.document = self.documentClass() | ||
348 | self.document._elementTree = root.getroottree() | ||
349 | |||
350 | # Give the root element the right name | ||
351 | name = token["name"] | ||
352 | namespace = token.get("namespace", self.defaultNamespace) | ||
353 | if namespace is None: | ||
354 | etree_tag = name | ||
355 | else: | ||
356 | etree_tag = "{%s}%s" % (namespace, name) | ||
357 | root.tag = etree_tag | ||
358 | |||
359 | # Add the root element to the internal child/open data structures | ||
360 | root_element = self.elementClass(name, namespace) | ||
361 | root_element._element = root | ||
362 | self.document._childNodes.append(root_element) | ||
363 | self.openElements.append(root_element) | ||
364 | |||
365 | # Reset to the default insert comment function | ||
366 | self.insertComment = self.insertCommentMain | ||