コード例 #1
0
    def test_setitem(self):
        q = IndexedList(['a', 'b'], {'a': 123}, 'a', 123, ['a', 'b', 'c'],
                        ['b', 123], ['a'], {'b': 321})
        q[0] = 2
        self.assertEqual(
            q._locator, {
                'b': SortedList([5, 7]),
                'a': SortedList([1, 4, 6]),
                str: SortedList([0, 2, 3])
            })

        self.assertTrue(q.is_consistent())

        q[2] = ['b', 'c', 'd']
        self.assertEqual(
            q._locator, {
                'b': SortedList([2, 5, 7]),
                'a': SortedList([1, 4, 6]),
                str: SortedList([0, 3])
            })
        self.assertTrue(q.is_consistent())

        q[1] = ['cd', 'efg', 12]
        self.assertEqual(
            q._locator, {
                'a': SortedList([4, 6]),
                'b': SortedList([2, 5, 7]),
                'cd': SortedList([1]),
                str: SortedList([0, 3])
            })
        self.assertTrue(q.is_consistent())
コード例 #2
0
ファイル: test_indexedlist.py プロジェクト: ischurov/qqmbr
 def test_creating_indexedlist2(self):
     q = IndexedList(["a", "b"], {"a": 123}, "a", 123, ["a", "b", "c"], ["b", 123], ["a"], {"b": 321})
     self.assertEqual(
         repr(q), "IndexedList([['a', 'b'], {'a': 123}, 'a', 123, ['a', 'b', 'c'], ['b', 123], ['a'], {'b': 321}])"
     )
     self.assertEqual(eval(repr(q)), q)
     self.assertEqual(q._locator, {"b": SortedList([5, 7]), "a": SortedList([0, 1, 4, 6]), str: SortedList([2, 3])})
     self.assertTrue(q.is_consistent())
コード例 #3
0
ファイル: test_indexedlist.py プロジェクト: ischurov/qqmbr
    def test_delitem(self):
        q = IndexedList(["a", "b"], {"a": 123}, "a", 123, ["a", "b", "c"], ["b", 123], ["a"], {"b": 321})

        del q[0]
        self.assertEqual(q._locator, {"b": SortedList([4, 6]), "a": SortedList([0, 3, 5]), str: SortedList([1, 2])})
        self.assertTrue(q.is_consistent())

        del q[2]
        self.assertEqual(q._locator, {"b": SortedList([3, 5]), "a": SortedList([0, 2, 4]), str: SortedList([1])})
        self.assertTrue(q.is_consistent())

        del q[3]
        self.assertEqual(q._locator, {"b": SortedList([4]), "a": SortedList([0, 2, 3]), str: SortedList([1])})

        self.assertTrue(q.is_consistent())

        del q[0]
        self.assertTrue(q.is_consistent())

        del q[3]
        self.assertTrue(q.is_consistent())

        del q[0]
        self.assertTrue(q.is_consistent())

        del q[1]
        self.assertTrue(q.is_consistent())

        del q[0]
        self.assertTrue(q.is_consistent())
        self.assertEqual(q, [])
コード例 #4
0
 def test_creating_indexedlist2(self):
     q = IndexedList(['a', 'b'], {'a': 123}, 'a', 123, ['a', 'b', 'c'],
                     ['b', 123], ['a'], {'b': 321})
     self.assertEqual(
         repr(q),
         "IndexedList([['a', 'b'], {'a': 123}, 'a', 123, ['a', 'b', 'c'], ['b', 123], ['a'], {'b': 321}])"
     )
     self.assertEqual(eval(repr(q)), q)
     self.assertEqual(
         q._locator, {
             'b': SortedList([5, 7]),
             'a': SortedList([0, 1, 4, 6]),
             str: SortedList([2, 3])
         })
     self.assertTrue(q.is_consistent())
コード例 #5
0
    def test_delitem(self):
        q = IndexedList(['a', 'b'], {'a': 123}, 'a', 123, ['a', 'b', 'c'],
                        ['b', 123], ['a'], {'b': 321})

        del q[0]
        self.assertEqual(
            q._locator, {
                'b': SortedList([4, 6]),
                'a': SortedList([0, 3, 5]),
                str: SortedList([1, 2])
            })
        self.assertTrue(q.is_consistent())

        del q[2]
        self.assertEqual(
            q._locator, {
                'b': SortedList([3, 5]),
                'a': SortedList([0, 2, 4]),
                str: SortedList([1])
            })
        self.assertTrue(q.is_consistent())

        del q[3]
        self.assertEqual(q._locator, {
            'b': SortedList([4]),
            'a': SortedList([0, 2, 3]),
            str: SortedList([1])
        })

        self.assertTrue(q.is_consistent())

        del q[0]
        self.assertTrue(q.is_consistent())

        del q[3]
        self.assertTrue(q.is_consistent())

        del q[0]
        self.assertTrue(q.is_consistent())

        del q[1]
        self.assertTrue(q.is_consistent())

        del q[0]
        self.assertTrue(q.is_consistent())
        self.assertEqual(q, [])
コード例 #6
0
ファイル: test_indexedlist.py プロジェクト: ischurov/qqmbr
    def test_setitem(self):
        q = IndexedList(["a", "b"], {"a": 123}, "a", 123, ["a", "b", "c"], ["b", 123], ["a"], {"b": 321})
        q[0] = 2
        self.assertEqual(q._locator, {"b": SortedList([5, 7]), "a": SortedList([1, 4, 6]), str: SortedList([0, 2, 3])})

        self.assertTrue(q.is_consistent())

        q[2] = ["b", "c", "d"]
        self.assertEqual(q._locator, {"b": SortedList([2, 5, 7]), "a": SortedList([1, 4, 6]), str: SortedList([0, 3])})
        self.assertTrue(q.is_consistent())

        q[1] = ["cd", "efg", 12]
        self.assertEqual(
            q._locator,
            {"a": SortedList([4, 6]), "b": SortedList([2, 5, 7]), "cd": SortedList([1]), str: SortedList([0, 3])},
        )
        self.assertTrue(q.is_consistent())
コード例 #7
0
ファイル: ml.py プロジェクト: ischurov/qqmbr
    def __init__(self, name, children=None, parent=None, my_index=None):
        if isinstance(name, dict) and len(name) == 1:
            self.__init__(*list(name.items())[0], parent=parent)
            return

        self.name = name
        self.parent = parent
        self.my_index = my_index

        if children is None:
            self._children = IndexedList()
        elif isinstance(children, str) or isinstance(children, int) or isinstance(children, float):
            self._children = IndexedList([children])
        elif isinstance(children, Sequence):
            self._children = IndexedList(children)
        else:
            raise QqError("I don't know what to do with children " + str(children))

        for i, child in enumerate(self):
            if isinstance(child, QqTag):
                child.parent = self
                child.my_index = i
コード例 #8
0
ファイル: test_indexedlist.py プロジェクト: ischurov/qqmbr
    def test_insert(self):
        q = IndexedList(["a", "b"], {"a": 123}, "a", 123, ["a", "b", "c"], ["b", 123], ["a"], {"b": 321})
        q.insert(2, "b")
        self.assertEqual(
            q._locator, {"a": SortedList([0, 1, 5, 7]), "b": SortedList([6, 8]), str: SortedList([2, 3, 4])}
        )
        self.assertTrue(q.is_consistent())

        q.insert(0, ["b", 123])
        self.assertEqual(
            q._locator, {"a": SortedList([1, 2, 6, 8]), "b": SortedList([0, 7, 9]), str: SortedList([3, 4, 5])}
        )
        self.assertTrue(q.is_consistent())
コード例 #9
0
    def test_insert(self):
        q = IndexedList(['a', 'b'], {'a': 123}, 'a', 123, ['a', 'b', 'c'],
                        ['b', 123], ['a'], {'b': 321})
        q.insert(2, 'b')
        self.assertEqual(
            q._locator, {
                'a': SortedList([0, 1, 5, 7]),
                'b': SortedList([6, 8]),
                str: SortedList([2, 3, 4])
            })
        self.assertTrue(q.is_consistent())

        q.insert(0, ['b', 123])
        self.assertEqual(
            q._locator, {
                'a': SortedList([1, 2, 6, 8]),
                'b': SortedList([0, 7, 9]),
                str: SortedList([3, 4, 5])
            })
        self.assertTrue(q.is_consistent())
コード例 #10
0
    def __init__(self, name, children=None, parent=None, my_index=None):
        if isinstance(name, dict) and len(name) == 1:
            self.__init__(*list(name.items())[0], parent=parent)
            return

        self.name = name
        self.parent = parent
        self.my_index = my_index

        if children is None:
            self._children = IndexedList()
        elif isinstance(children, str) or isinstance(
                children, int) or isinstance(children, float):
            self._children = IndexedList([children])
        elif isinstance(children, Sequence):
            self._children = IndexedList(children)
        else:
            raise QqError("I don't know what to do with children " +
                          str(children))

        for i, child in enumerate(self):
            if isinstance(child, QqTag):
                child.parent = self
                child.my_index = i
コード例 #11
0
 def test_creating_indexedlist1(self):
     q = IndexedList([['a', 'b'], ['a', 'd']])
     self.assertEqual(list(q._locator['a']), [0, 1])
     self.assertTrue(q.is_consistent())
コード例 #12
0
ファイル: test_indexedlist.py プロジェクト: ischurov/qqmbr
 def test_creating_indexedlist1(self):
     q = IndexedList([["a", "b"], ["a", "d"]])
     self.assertEqual(list(q._locator["a"]), [0, 1])
     self.assertTrue(q.is_consistent())
コード例 #13
0
ファイル: ml.py プロジェクト: ischurov/qqmbr
class QqTag(MutableSequence):
    """
    QqTag is essentially an IndexedList with name attached. It behaves mostly like eTree Element.

    It provides eTree and BeautifulSoup-style navigation over its child:
    - ``tag.find('subtag')`` returns first occurrence of a child with name ``subtag``. (Note that
    in contrast with BeautifulSoup, this is not recursive: it searches only through tag's direct childrens.)
    - ``tag._subtag`` is a shortcut for ``tag.find('subtag')`` (works if ``subtag`` is valid identifier)
    - ``tag.find_all('subtag')`` returns all occurrences of tag with name 'subtag'
    - ``tag('subtag')`` is shortcut for ``tag.find_all('subtag')``

    If QqTag has only one child, it is called *simple*. Then its `.value` is defined. (Useful for access
    to property-like subtags.)
    """
    def __init__(self, name, children=None, parent=None, my_index=None):
        if isinstance(name, dict) and len(name) == 1:
            self.__init__(*list(name.items())[0], parent=parent)
            return

        self.name = name
        self.parent = parent
        self.my_index = my_index

        if children is None:
            self._children = IndexedList()
        elif isinstance(children, str) or isinstance(children, int) or isinstance(children, float):
            self._children = IndexedList([children])
        elif isinstance(children, Sequence):
            self._children = IndexedList(children)
        else:
            raise QqError("I don't know what to do with children " + str(children))

        for i, child in enumerate(self):
            if isinstance(child, QqTag):
                child.parent = self
                child.my_index = i

    def __repr__(self):
        if self.parent is None:
            return "QqTag(%s, %s)" % (repr(self.name), repr(self._children))
        else:
            return "QqTag(%s, %s, parent = %s)" % (repr(self.name), repr(self._children), repr(self.parent.name))

    def __str__(self):
        return "{%s : %s}" % (self.name, self._children)

    def __eq__(self, other):
        if other is None or not isinstance(other, QqTag):
            return False
        return self.as_list() == other.as_list()

    @property
    def is_simple(self):
        """
        Simple tags are those containing only one child
        :return:
        """
        return len(self) == 1

    @property
    def value(self):
        if self.is_simple:
            return self[0].strip()
        raise QqError("More than one child, value is not defined, QqTag: %s" % str(self))

    @value.setter
    def value(self, value):
        if self.is_simple:
            self[0] = value
        else:
            raise QqError("More than one child, cannot set value")

    def __qqkey__(self):
        return self.name

    def __getattr__(self, attr):
        if attr[0] == "_":
            return self.find(attr[1:])
        raise AttributeError("Attribute " + attr + " not found")

    def find(self, key):
        """
        Returns direct children with the given key if it exists, otherwise returns None
        :param key: key
        :return: QqTag
        """
        if key in self._children._locator:
            return self._children.find(key)

    def find_all(self, key):
        if key in self._children._locator:
            return self._children.find_all(key)

    def __call__(self, key):
        return self.find_all(key)

    def as_list(self):
        ret = [self.name]
        for child in self:
            if isinstance(child, QqTag):
                ret.append(child.as_list())
            else:
                ret.append(child)
        return ret

    def insert(self, index: int, child) -> None:
        self._children.insert(index, child)
        child.parent = self
        child.my_index = index
        for i in range(index+1, len(self)):
            self._children[i].my_index += 1

    def __delitem__(self, index: int):
        del self._children[index]
        for i in range(index, len(self)):
            self._children[i].my_index -= 1

    def append_child(self, child):
        self.insert(len(self), child)

    def _is_consistent(self):
        for i, child in enumerate(self):
            if child.parent != self or child.my_index != i:
                return False
        return True

    def append_line(self, line):
        if line:
            self._children.append(line)

    def __getitem__(self, item):
        return self._children[item]

    def __setitem__(self, index, child):
        self._children[index] = child
        child.parent = self
        child.my_index = index

    def __iter__(self):
        return iter(self._children)

    def __len__(self):
        return len(self._children)

    @property
    def text_content(self):
        chunk = []
        for child in self:
            if isinstance(child, str):
                chunk.append(child)
        return "".join(chunk)

    def exists(self, key):
        """
        Returns True if a child with given key exists
        :param key:
        :return:
        """
        return key in self._children._locator

    def get(self, key, default_value=None):
        """
        Returns a value of a direct child with a given key.
        If it is does not exists or is not simple, returns default value (default: None)
        :param key: key
        :param default_value: what to return if there is no such key or the corresponding child is ot simple
        :return: the value of a child
        """
        tag = self.find(key)
        if tag and tag.is_simple:
            return tag.value
        else:
            return default_value

    def ancestor_path(self):
        """
        Returns list of ancestors for self.

        Example:

            \tag
                \othertag
                    \thirdtag

        thirdtag.ancestor_path == [thirdtag, othertag, tag, _root]

        :return:
        """
        tag = self
        path = [tag]
        while tag.parent:
            tag = tag.parent
            path.append(tag)
        return path

    def get_granny(self):
        """
        Returns ancestor which is direct child of root

        :return:
        """
        return self.ancestor_path()[-2]

    def next(self):
        if not self.parent or self.my_index is None or self.my_index == len(self.parent) - 1:
            return None
        return self.parent[self.my_index + 1]

    def prev(self):
        if not self.parent or self.my_index is None or self.my_index == 0:
            return None
        return self.parent[self.my_index - 1]

    def split_by_sep(self, separator='separator'):
        chunks = []
        chunk = []
        sep = QqTag(separator)
        for child in self:
            if child == sep:
                chunks.append(chunk)
                chunk = []
            else:
                chunk.append(child)
        chunks.append(chunk)
        return chunks
コード例 #14
0
class QqTag(MutableSequence):
    """
    QqTag is essentially an IndexedList with name attached. It behaves mostly like eTree Element.

    It provides eTree and BeautifulSoup-style navigation over its child:
    - ``tag.find('subtag')`` returns first occurrence of a child with name ``subtag``. (Note that
    in contrast with BeautifulSoup, this is not recursive: it searches only through tag's direct childrens.)
    - ``tag._subtag`` is a shortcut for ``tag.find('subtag')`` (works if ``subtag`` is valid identifier)
    - ``tag.find_all('subtag')`` returns all occurrences of tag with name 'subtag'
    - ``tag('subtag')`` is shortcut for ``tag.find_all('subtag')``

    If QqTag has only one child, it is called *simple*. Then its `.value` is defined. (Useful for access
    to property-like subtags.)
    """
    def __init__(self, name, children=None, parent=None, my_index=None):
        if isinstance(name, dict) and len(name) == 1:
            self.__init__(*list(name.items())[0], parent=parent)
            return

        self.name = name
        self.parent = parent
        self.my_index = my_index

        if children is None:
            self._children = IndexedList()
        elif isinstance(children, str) or isinstance(
                children, int) or isinstance(children, float):
            self._children = IndexedList([children])
        elif isinstance(children, Sequence):
            self._children = IndexedList(children)
        else:
            raise QqError("I don't know what to do with children " +
                          str(children))

        for i, child in enumerate(self):
            if isinstance(child, QqTag):
                child.parent = self
                child.my_index = i

    def __repr__(self):
        if self.parent is None:
            return "QqTag(%s, %s)" % (repr(self.name), repr(self._children))
        else:
            return "QqTag(%s, %s, parent = %s)" % (repr(
                self.name), repr(self._children), repr(self.parent.name))

    def __str__(self):
        return "{%s : %s}" % (self.name, self._children)

    def __eq__(self, other):
        if other is None or not isinstance(other, QqTag):
            return False
        return self.as_list() == other.as_list()

    @property
    def is_simple(self):
        """
        Simple tags are those containing only one child
        :return:
        """
        return len(self) == 1

    @property
    def value(self):
        if self.is_simple:
            return self[0].strip()
        raise QqError("More than one child, value is not defined, QqTag: %s" %
                      str(self))

    @value.setter
    def value(self, value):
        if self.is_simple:
            self[0] = value
        else:
            raise QqError("More than one child, cannot set value")

    def __qqkey__(self):
        return self.name

    def __getattr__(self, attr):
        if attr[0] == "_":
            return self.find(attr[1:])
        raise AttributeError("Attribute " + attr + " not found")

    def find(self, key):
        """
        Returns direct children with the given key if it exists, otherwise returns None
        :param key: key
        :return: QqTag
        """
        if key in self._children._locator:
            return self._children.find(key)

    def find_all(self, key):
        if key in self._children._locator:
            return self._children.find_all(key)

    def __call__(self, key):
        return self.find_all(key)

    def as_list(self):
        ret = [self.name]
        for child in self:
            if isinstance(child, QqTag):
                ret.append(child.as_list())
            else:
                ret.append(child)
        return ret

    def insert(self, index: int, child) -> None:
        self._children.insert(index, child)
        child.parent = self
        child.my_index = index
        for i in range(index + 1, len(self)):
            self._children[i].my_index += 1

    def __delitem__(self, index: int):
        del self._children[index]
        for i in range(index, len(self)):
            self._children[i].my_index -= 1

    def append_child(self, child):
        self.insert(len(self), child)

    def _is_consistent(self):
        for i, child in enumerate(self):
            if child.parent != self or child.my_index != i:
                return False
        return True

    def append_line(self, line):
        if line:
            self._children.append(line)

    def __getitem__(self, item):
        return self._children[item]

    def __setitem__(self, index, child):
        self._children[index] = child
        child.parent = self
        child.my_index = index

    def __iter__(self):
        return iter(self._children)

    def __len__(self):
        return len(self._children)

    @property
    def text_content(self):
        chunk = []
        for child in self:
            if isinstance(child, str):
                chunk.append(child)
        return "".join(chunk)

    def exists(self, key):
        """
        Returns True if a child with given key exists
        :param key:
        :return:
        """
        return key in self._children._locator

    def get(self, key, default_value=None):
        """
        Returns a value of a direct child with a given key.
        If it is does not exists or is not simple, returns default value (default: None)
        :param key: key
        :param default_value: what to return if there is no such key or the corresponding child is ot simple
        :return: the value of a child
        """
        tag = self.find(key)
        if tag and tag.is_simple:
            return tag.value
        else:
            return default_value

    def ancestor_path(self):
        """
        Returns list of ancestors for self.

        Example:

            \tag
                \othertag
                    \thirdtag

        thirdtag.ancestor_path == [thirdtag, othertag, tag, _root]

        :return:
        """
        tag = self
        path = [tag]
        while tag.parent:
            tag = tag.parent
            path.append(tag)
        return path

    def get_granny(self):
        """
        Returns ancestor which is direct child of root

        :return:
        """
        return self.ancestor_path()[-2]

    def next(self):
        if not self.parent or self.my_index is None or self.my_index == len(
                self.parent) - 1:
            return None
        return self.parent[self.my_index + 1]

    def prev(self):
        if not self.parent or self.my_index is None or self.my_index == 0:
            return None
        return self.parent[self.my_index - 1]

    def split_by_sep(self, separator='separator'):
        chunks = []
        chunk = []
        sep = QqTag(separator)
        for child in self:
            if child == sep:
                chunks.append(chunk)
                chunk = []
            else:
                chunk.append(child)
        chunks.append(chunk)
        return chunks