Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 038098c

Browse files
authored
Merge pull request #45: Partially implement interface Node
close #37 fix #38
2 parents a6e3e28 + 16a64ae commit 038098c

File tree

1 file changed

+337
-18
lines changed

1 file changed

+337
-18
lines changed

‎w3/python/core/interface.py

Lines changed: 337 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from __future__ import annotations
22

33
from ctypes import c_ushort, c_ulong
4-
from typing import Callable
4+
from typing import Callable, Optional
55

6+
from w3.python.core.exception import DOMException
67
from w3.python.core.type import DOMString
78

89

@@ -73,23 +74,341 @@ class Node:
7374
DOCUMENT_FRAGMENT_NODE: c_ushort = c_ushort(11)
7475
NOTATION_NODE: c_ushort = c_ushort(12)
7576

76-
nodeName: DOMString
77-
nodeValue: DOMString
78-
nodeType: c_ushort
79-
parentNode: Node
80-
childNodes: NodeList
81-
firstChild: Node
82-
lastChild: Node
83-
previousSibling: Node
84-
nextSibling: Node
85-
attributes: NamedNodeMap
86-
ownerDocument: Document
87-
insertBefore: Callable[[Node, Node], Node]
88-
replaceChild: Callable[[Node, Node], Node]
89-
removeChild: Callable[[Node], Node]
90-
appendChild: Callable[[Node], Node]
91-
hasChildNodes: Callable[[], bool]
92-
cloneNodes: Callable[[bool], Node]
77+
def __init__(self) -> None:
78+
# Accessor about this node's modification
79+
self._read_only: bool
80+
# Accessors about this node's properties
81+
self._node_type: c_ushort
82+
self._node_name: DOMString
83+
self._node_value: DOMString
84+
self._attributes: NamedNodeMap
85+
# Accessors about DOM Tree
86+
self._owner_document: Optional[Document]
87+
self._parent_node: Optional[Node]
88+
self._next_sibling_node: Optional[Node]
89+
self._prev_sibling_node: Optional[Node]
90+
self._child_nodes: NodeList
91+
# Methods typing hints
92+
self.insertBefore: Callable[[Node, Node], Node]
93+
self.replaceChild: Callable[[Node, Node], Node]
94+
self.removeChild: Callable[[Node], Node]
95+
self.appendChild: Callable[[Node], Node]
96+
self.hasChildNodes: Callable[[], bool]
97+
self.cloneNodes: Callable[[bool], Node]
98+
99+
def _get_nodeName(self) -> DOMString:
100+
"""Indirect accessor to get the `nodeName` property."""
101+
return self._node_name
102+
103+
def _set_nodeName(self, name: DOMString) -> None:
104+
"""Indirect accessor to set the `nodeName` property."""
105+
self._node_name = DOMString(name)
106+
107+
def _get_nodeValue(self) -> DOMString:
108+
"""Indirect accessor to get the `nodeValue` property.
109+
110+
Raises:
111+
DOMException:
112+
- DOMSTRING_SIZE_ERR: Raised when it would return more characters than fit in a `DOMString` variable on the implementation platform.
113+
"""
114+
# XXX: DOMException.DOMSTRING_SIZE_ERR was not taken into account.
115+
return self._node_value
116+
117+
def _set_nodeValue(self, value: DOMString) -> None:
118+
"""Indirect accessor to set the `nodeValue` property."""
119+
self._node_value = DOMString(value)
120+
121+
def _get_nodeType(self) -> c_ushort:
122+
"""Indirect accessor to get the `nodeType` property."""
123+
return self._node_type
124+
125+
def _set_nodeType(self, type: c_ushort) -> None:
126+
"""Indirect accessor to set the `nodeType` property."""
127+
self._node_type = c_ushort(type)
128+
129+
def _get_parentNode(self) -> Node:
130+
"""Indirect accessor to get the `parentNode` property."""
131+
return self._parent_node
132+
133+
def _set_parentNode(self, node: Optional[Node] = None) -> None:
134+
"""Indirect accessor to set the `parentNode` property."""
135+
self._parent_node = node
136+
137+
def _get_childNodes(self) -> NodeList:
138+
"""Indirect accessor to get the `childNodes` property."""
139+
return self._child_nodes
140+
141+
def _get_child_node(self, index: c_ulong) -> Optional[Node]:
142+
"""Accessor to get the `childNodes`property."""
143+
if self.parentNode is None:
144+
return None
145+
if not self.parentNode.hasChildNodes():
146+
return None
147+
return self.parentNode.childNodes.item(index)
148+
149+
def _insert_child_node(self, index: c_ulong, new_child: Node) -> Node:
150+
raise NotImplementedError()
151+
152+
def _get_index_of_child_node(self, child: Node) -> c_ulong:
153+
raise NotImplementedError()
154+
155+
def _get_firstChild(self) -> Optional[Node]:
156+
"""Indirect accessor to get the `firstChild` property."""
157+
return self._get_child_node(0)
158+
159+
def _get_lastChild(self) -> Node:
160+
"""Indirect accessor to get the `lastChild` property."""
161+
return self._get_child_node(self.childNodes.length-1)
162+
163+
def _get_previousSibling(self) -> Node:
164+
"""Indirect accessor to get the `previousSibling` property."""
165+
return self._prev_sibling_node
166+
167+
def _get_nextSibling(self) -> Node:
168+
"""Indirect accessor to get the `nextSibling` property."""
169+
return self._next_sibling_node
170+
171+
def _get_attributes(self) -> NamedNodeMap:
172+
"""Indirect accessor to get the `attributes` property."""
173+
return self._attributes
174+
175+
def _get_ownerDocument(self) -> Document:
176+
"""Indirect accessor to get the `ownerDocument` property."""
177+
return self._owner_document
178+
179+
def _set_ownerDocument(self, owner_document: Document) -> None:
180+
"""Indirect accessor to set the `ownerDocument` property."""
181+
self._owner_document = owner_document
182+
183+
def _appendChild(self, new_child: Node) -> Node:
184+
if new_child.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
185+
for grand_child_node in new_child.childNodes:
186+
self._appendChild(grand_child_node)
187+
else:
188+
self._check_NO_MODIFICATION_ALLOWED_ERR()
189+
self._check_WRONG_DOCUMENT_ERR(new_child)
190+
self._check_HIERARCHY_REQUEST_ERR(new_child)
191+
# XXX
192+
raise NotImplementedError()
193+
return new_child
194+
195+
def _hasChildNodes(self) -> bool:
196+
return self.childNodes.length > 0
197+
198+
def _check_HIERARCHY_REQUEST_ERR(self, node: Node) -> None:
199+
# Should be checked on subclasses.
200+
raise NotImplementedError()
201+
202+
def _check_WRONG_DOCUMENT_ERR(self, node: Node) -> None:
203+
if node.ownerDocument is not self.ownerDocument:
204+
raise DOMException(DOMException.WRONG_DOCUMENT_ERR)
205+
206+
def _check_NO_MODIFICATION_ALLOWED_ERR(self) -> None:
207+
if self._read_only:
208+
raise DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR)
209+
210+
def _check_NOT_FOUND_ERR(self, node: Node) -> None:
211+
if node not in self.childNodes:
212+
raise DOMException(DOMException.NOT_FOUND_ERR)
213+
214+
@property
215+
def nodeName(self) -> DOMString:
216+
"""The name of this node, depending on its type."""
217+
return self._get_nodeName()
218+
219+
@property
220+
def nodeValue(self) -> DOMString:
221+
"""The value of this node, depending on its type.
222+
223+
Raises:
224+
Exceptions on setting
225+
DOMException:
226+
NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
227+
228+
Exceptions on retrieval
229+
DOMException:
230+
DOMSTRING_SIZE_ERR: Raised when it would return more characters than fit in a `DOMString` variable on the implementation platform.
231+
"""
232+
return self._get_nodeValue()
233+
234+
@nodeValue.setter
235+
def nodeValue(self, value: DOMString) -> None:
236+
self._set_nodeValue(value)
237+
238+
@property
239+
def nodeType(self) -> c_ushort:
240+
"""A code representing the type of the underlying object."""
241+
return self._get_nodeType()
242+
243+
@property
244+
def parentNode(self) -> Optional[Node]:
245+
"""The parent of this node.
246+
247+
All nodes, except `Document`, `DocumentFragment`, and `Attr` may have a parent.
248+
However, if a node has just been created and not yet added to the tree, or if it has been removed from the tree, this is `None`.
249+
"""
250+
return self._get_parentNode()
251+
252+
@property
253+
def childNodes(self) -> NodeList:
254+
"""A `NodeList` that contains all children of this node.
255+
256+
If there are no children, this is a `NodeList` containing no nodes.
257+
The content of the returned `NodeList` is "live" in the sense that, for instance, changes to the children of the node object that it was created from are immediately reflected in the nodes returned by the `NodeList` accessors; it is not a static snapshot of the content of the node.
258+
This is true for every `NodeList`, including the ones returned by the `getElementsByTagName` method.
259+
"""
260+
return self._get_childNodes()
261+
262+
@property
263+
def firstChild(self) -> Node:
264+
"""The first child of this node.
265+
266+
If there is no such node, this returns `null`."""
267+
return self._get_firstChild()
268+
269+
@property
270+
def lastChild(self) -> Node:
271+
"""The last child of this node.
272+
273+
If there is no such node, this returns `null`."""
274+
return self._get_lastChild()
275+
276+
@property
277+
def previousSibling(self) -> Node:
278+
"""The node immediately preceding this node.
279+
280+
If there is no such node, this returns `null`."""
281+
return self._get_previousSibling()
282+
283+
@property
284+
def nextSibling(self) -> Node:
285+
"""The node immediately following this node.
286+
287+
If there is no such node, this returns `None`.
288+
"""
289+
return self._get_nextSibling()
290+
291+
@property
292+
def attributes(self) -> NamedNodeMap:
293+
"""A `NamedNodeMap` containing the attributes of this node (if it is an `Element`) or `None` otherwise.
294+
"""
295+
return self._get_attributes()
296+
297+
@property
298+
def ownerDocument(self) -> Document:
299+
"""The `Document` object associated with this node.
300+
301+
This is also the `Document` object used to create new nodes.
302+
When this node is a `Document` this is `None`.
303+
"""
304+
return self._get_ownerDocument()
305+
306+
def insertBefore(self, newChild: Node, refChild: Node) -> Node:
307+
"""Inserts the node `newChild` before the existing child node `refChild`.
308+
309+
If `refChild` is `None`, insert `newChild` at the end of the list of children.
310+
If `newChild` is a `DocumentFragment` object, all of its children are inserted, in the same order, before `refChild`.
311+
If the `newChild` is already in the tree, it is first removed.
312+
313+
Args:
314+
newChild: The node to insert.
315+
refChild: The reference node, i.e., the node before which the new node must be inserted.
316+
317+
Returns:
318+
The node being inserted.
319+
320+
Raises:
321+
DOMException:
322+
- HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the `newChild` node, or if the node to insert is one of this node's ancestors.
323+
- WRONG_DOCUMENT_ERR: Raised if `newChild` was created from a different document than the one that created this node.
324+
- NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
325+
- NOT_FOUND_ERR: Raised if `refChild` is not a child of this node.
326+
"""
327+
raise NotImplementedError()
328+
329+
def replaceChild(self, newChild: Node, oldChild: Node) -> Node:
330+
"""Replaces the child node `oldChild` with `newChild` in the list of children, and returns the `oldChild` node.
331+
332+
If the `newChild` is already in the tree, it is first removed.
333+
334+
Args:
335+
newChild: The new node to put in the child list.
336+
oldChild: The node being replaced in the list.
337+
338+
Returns:
339+
The node replaced.
340+
341+
Raises:
342+
DOMException:
343+
- HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the `newChild` node, or it the node to put in is one of this node's ancestors.
344+
- WRONG_DOCUMENT_ERR: Raised if `newChild` was created from a different document than the one that created this node.
345+
- NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
346+
- NOT_FOUND_ERR: Raised if `oldChild` is not a child of this node.
347+
"""
348+
raise NotImplementedError()
349+
350+
def removeChild(self, oldChild: Node) -> Node:
351+
"""Removes the child node indicated by `oldChild` from the list of children, and returns it.
352+
353+
Args:
354+
oldChild: The node being removed.
355+
356+
Returns:
357+
The node removed.
358+
359+
Raises:
360+
DOMException:
361+
- NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
362+
- NOT_FOUND_ERR: Raised if `oldChild` is not a child of this node.
363+
"""
364+
raise NotImplementedError()
365+
366+
def appendChild(self, newChild: Node) -> Node:
367+
"""Adds the node `newChild` to the end of the list of children of this node.
368+
369+
If the `newChild` is already in the tree, it is first removed.
370+
371+
Args:
372+
newChild: The node to add. If it is a `DocumentFragment` object, the entire contents of the document fragment are moved into the child list of this node
373+
374+
Returns:
375+
The node added.
376+
377+
Raises:
378+
DOMException:
379+
- HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the `newChild` node, or if the node to append is one of this node's ancestors.
380+
- WRONG_DOCUMENT_ERR: Raised if `newChild` was created from a different document than the one that created this node.
381+
- NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
382+
"""
383+
return self._appendChild(newChild)
384+
385+
def hasChildNodes(self) -> bool:
386+
"""This is a convenience method to allow easy determination of whether a node has any children.
387+
388+
Returns:
389+
`True` if the node has any children, `False` if the node has no children.
390+
391+
This method has no parameters.
392+
This method raises no exceptions.
393+
"""
394+
return self._hasChildNodes()
395+
396+
def cloneNode(self) -> Node:
397+
"""Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes.
398+
399+
The duplicate node has no parent (`parentNode` returns `None`.).
400+
Cloning an `Element` copies all attributes and their values, including those generated by the XML processor to represent defaulted attributes, but this method does not copy any text it contains unless it is a deep clone, since the text is contained in a child `Text` node.
401+
Cloning any other type of node simply returns a copy of this node.
402+
403+
Args:
404+
deep: If `True`, recursively clone the subtree under the specified node; if `False`, clone only the node itself (and its attributes, if it is an `Element`).
405+
406+
Returns:
407+
The duplicate node.
408+
409+
This method raises no exceptions.
410+
"""
411+
raise NotImplementedError()
93412

94413

95414
class DocumentFragment(Node):

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /