From 7122c76d4273c22bdce4125aae8d03ce601f7302 Mon Sep 17 00:00:00 2001 From: hebl Date: Fri, 4 Nov 2022 21:30:05 +0100 Subject: [PATCH] Added fix for unstable element index (issue #223) --- panflute/base.py | 14 ++------------ panflute/containers.py | 8 +++++--- tests/test_regressions.py | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/panflute/base.py b/panflute/base.py index 134b7b0..d87cfe4 100644 --- a/panflute/base.py +++ b/panflute/base.py @@ -22,7 +22,7 @@ class Element(object): """ Base class of all Pandoc elements """ - __slots__ = ['parent', 'location'] + __slots__ = ['parent', 'location', 'index'] _children = [] def __new__(cls, *args, **kwargs): @@ -30,6 +30,7 @@ def __new__(cls, *args, **kwargs): element = object.__new__(cls) element.parent = None element.location = None + element.index = None return element @property @@ -134,17 +135,6 @@ def _set_content(self, value, oktypes): # Navigation # --------------------------- - @property - def index(self): - """ - Return position of element inside the parent. - - :rtype: ``int`` | ``None`` - """ - container = self.container - if container is not None: - return container.index(self) - @property def container(self): """ diff --git a/panflute/containers.py b/panflute/containers.py index 10ab229..1cae364 100644 --- a/panflute/containers.py +++ b/panflute/containers.py @@ -18,7 +18,8 @@ # These are list and dict containers that # (a) track the identity of their parents, and # (b) track the parent's property where they are stored -# They attach these two to the elements requested through __getattr__ +# (c) track the index in the parent in case of list +# They attach these three to the elements requested through __getattr__ class ListContainer(MutableSequence): """ @@ -55,7 +56,7 @@ def __len__(self): def __getitem__(self, i): if isinstance(i, int): - return attach(self.list[i], self.parent, self.location) + return attach(self.list[i], self.parent, self.location, i) else: newlist = self.list.__getitem__(i) obj = ListContainer(*newlist, @@ -168,10 +169,11 @@ def to_json(self): # Functions # --------------------------- -def attach(element, parent, location): +def attach(element, parent, location, index=None): if not isinstance(element, (int, str, bool)): element.parent = parent element.location = location + element.index = index else: debug(f'Warning: element "{type(element)}" has no parent') return element diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 155d4df..515867b 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -11,5 +11,20 @@ def test_quotes_129(): assert output == '"Some quoted text"' +def test_index_223(): + """Index values on duplicated elements are determined using list.index() + but this returns the index first found element. + This test checks whether the index on the element corresponds with the + actual index in the parent collection. + """ + # pf https://github.com/sergiocorreia/panflute/issues/223 + doc = pf.Doc(pf.Para(pf.Str("a")), pf.Para(pf.Str("b")), + pf.Para(pf.Str("a")), pf.Para(pf.Str("c"))) + + for (index, element) in enumerate(doc.content): + assert element.index == index + + if __name__ == "__main__": test_quotes_129() + test_index_223()