From 0094e4b44658d9ce6ca07ca1542de7b3b0b92473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=8F=99=EC=A3=BC?= Date: Wed, 2 Jun 2021 14:18:40 +0900 Subject: [PATCH 1/5] Create NodeList.py --- w3/python/core/fundamental_interface/NodeList.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 w3/python/core/fundamental_interface/NodeList.py diff --git a/w3/python/core/fundamental_interface/NodeList.py b/w3/python/core/fundamental_interface/NodeList.py new file mode 100644 index 0000000..e69de29 From f4ee67c48190ce9107d4ae1dbd36fa4e557126ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=8F=99=EC=A3=BC?= Date: Wed, 2 Jun 2021 14:58:19 +0900 Subject: [PATCH 2/5] Implement `NodeList` based on `list` type --- .../core/fundamental_interface/NodeList.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/w3/python/core/fundamental_interface/NodeList.py b/w3/python/core/fundamental_interface/NodeList.py index e69de29..4df6941 100644 --- a/w3/python/core/fundamental_interface/NodeList.py +++ b/w3/python/core/fundamental_interface/NodeList.py @@ -0,0 +1,36 @@ +from typing import Optional + +from w3.python.core.fundamental_interface.Node import Node + + +_AnyNode = Node + +class NodeList(list): + """Interface NodeList + + The `NodeList` interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. + The items in the `NodeList` are accessible via an integral index, starting from 0. + """ + + @property + def length(self) -> int: + """The number of nodes in the list. The range of valid child node indices is 0 to `length`-1 inclusive. + """ + return len(self) + + + def item(self, index: int) -> Optional[_AnyNode]: + """Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null. + + Args: + index: Index into the collection. + + Returns: + The node at the `index`th position in the `NodeList`, or `None` if that is not a valid index. + + This method raises no exceptions. + """ + if isinstance(index, int): + if 0 <= index < self.length: + return self[index] + return None From 48ab5055c76e03435d7e915fd7d2ae7009f521ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=8F=99=EC=A3=BC?= Date: Wed, 2 Jun 2021 15:00:59 +0900 Subject: [PATCH 3/5] Create unittest for `NodeList` --- .../fundamental_interface/NodeList_test.py | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 w3/python/core/fundamental_interface/NodeList_test.py diff --git a/w3/python/core/fundamental_interface/NodeList_test.py b/w3/python/core/fundamental_interface/NodeList_test.py new file mode 100644 index 0000000..d19801e --- /dev/null +++ b/w3/python/core/fundamental_interface/NodeList_test.py @@ -0,0 +1,69 @@ +from typing import Iterator +import unittest + +from w3.python.core.fundamental_interface.DOMException import DOMException +from w3.python.core.fundamental_interface.Node import Node +from w3.python.core.fundamental_interface.Node import NodeType +from w3.python.core.fundamental_interface.NodeList import NodeList + + +def _make_nodes(n: int) -> Iterator[Node]: + """Accessor to create `n` random nodes immediatly. + + Args: + n: number of nodes to generate. + + Yields: + A randomly generated node. + """ + for _ in range(n): + yield Node(NodeType.TEXT_NODE, '#text') + + +class Test_NodeList(unittest.TestCase): + def testInit(self): + NodeList() + # Initiate with a node + node = next(_make_nodes(1)) + NodeList([node]) + # Initiate with multiple nodes. + NodeList(_make_nodes(4)) + + def testIter(self): + nodes = [*_make_nodes(4)] + node_list = NodeList(nodes) + # Create an iterator for checking + node_iter = iter(nodes) + for list_elem in node_list: + self.assertEqual(list_elem, next(node_iter)) + + def testItem_inSize(self): + nodes = [*_make_nodes(5)] + node_list = NodeList(nodes) + for i in range(5): + self.assertEqual(node_list.item(i), nodes[i]) + + def testItem_greaterOrEqualThanSize(self): + node_list = NodeList(_make_nodes(5)) + for i in range(5, 8): + self.assertIsNone(node_list.item(i)) + + def testItem_notValid(self): + node_list = NodeList(_make_nodes(5)) + for idx in [-1, -9999, 'hi', '1', None, Node, NodeList, b'0']: + self.assertIsNone(node_list.item(idx)) + + def testLength(self): + # Empty NodeList + node_list = NodeList() + self.assertEqual(node_list.length, 0) + # NodeList with a node. + node_list = NodeList(_make_nodes(1)) + self.assertEqual(node_list.length, 1) + # NodeList with some items. + node_list = NodeList(_make_nodes(5)) + self.assertEqual(node_list.length, 5) + + +if __name__ == '__main__': + unittest.main() From 56ab2a8d85d28a77b726daabe6a4ff3b3a269168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=8F=99=EC=A3=BC?= Date: Wed, 2 Jun 2021 15:59:57 +0900 Subject: [PATCH 4/5] Unimport unused interface `DOMException` --- w3/python/core/fundamental_interface/NodeList_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/w3/python/core/fundamental_interface/NodeList_test.py b/w3/python/core/fundamental_interface/NodeList_test.py index d19801e..4b63fa2 100644 --- a/w3/python/core/fundamental_interface/NodeList_test.py +++ b/w3/python/core/fundamental_interface/NodeList_test.py @@ -1,7 +1,6 @@ from typing import Iterator import unittest -from w3.python.core.fundamental_interface.DOMException import DOMException from w3.python.core.fundamental_interface.Node import Node from w3.python.core.fundamental_interface.Node import NodeType from w3.python.core.fundamental_interface.NodeList import NodeList From fc1811b3710be241ace8c1a3bf0f3a9d02b5d189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=8F=99=EC=A3=BC?= Date: Wed, 2 Jun 2021 16:02:05 +0900 Subject: [PATCH 5/5] Fix circular import issue by unimporting `Node` and replacing `_AnyNode = Node` with `_AnyNode = Any` --- w3/python/core/fundamental_interface/NodeList.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/w3/python/core/fundamental_interface/NodeList.py b/w3/python/core/fundamental_interface/NodeList.py index 4df6941..6af09ab 100644 --- a/w3/python/core/fundamental_interface/NodeList.py +++ b/w3/python/core/fundamental_interface/NodeList.py @@ -1,9 +1,7 @@ -from typing import Optional +from typing import Any, Optional -from w3.python.core.fundamental_interface.Node import Node - -_AnyNode = Node +_AnyNode = Any class NodeList(list): """Interface NodeList