5j9/wikitextparser

The object has died (overwritten or deleted) and cannot be mutated

MrIbrahem opened this issue · 3 comments

I'm encountering a DeadIndexError when attempting to access the name property of a template after parsing and editting Wikitext containing nested templates. Here's a minimal example to reproduce the issue:

import wikitextparser as wtp
text = "{{Ficha de medicamento| Drugs.com = {{drugs.com|monograph|alitretinoin}}}}"
parsed = wtp.parse(text)
n = 0
for template in parsed.templates:
    n += 1
    print(f'template {n}:')
    print(template)
    na = template.name
    normal = template.normal_name()
    print(f'normal: {normal}')
    for arg in template.arguments:
        arg.value = arg.value.rstrip() + '\n'

error:


Traceback (most recent call last):
  File "I:\mdwiki\pybot\md_core\tests7.py", line 10, in <module>
    na = template.name
         ^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\site-packages\wikitextparser\_parser_function.py", line 95, in name
    return self(2, -2)
           ^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\site-packages\wikitextparser\_wikitext.py", line 317, in __call__
    else (s + start if start >= 0 else e + start) : e
          ~~^~~~~~~
  File "C:\Program Files\Python311\Lib\site-packages\wikitextparser\_wikitext.py", line 173, in __add__
    raise DeadIndexError(
wikitextparser._wikitext.DeadIndexError: this usually means that the object has died (overwritten or deleted) and cannot be mutated

@coderabbitai found a solution to this problem

When the code runs in the first template no error occurs, but I changed the value of the argument which is the second template in parsed.templates, and when the code starts running in the second template the error occurs.

5j9 commented

When the value of the last argument in the first template is modified, all objects that are entirely contained within that specific portion of the wikitext—meaning those that both start and end within that area, as opposed to parent objects whose start and end tokens extend beyond it—are invalidated or overwritten. This includes the second template, as it falls within the affected segment.

This behavior is expected. While tracking all changes within a text segment might be possible (and some early wikitextparser versions attempted this), the process is computationally too expensive and can be unintuitive. Therefore, it's not currently implemented.

Fortunately, a simple workaround exists: iterate over templates in reverse order:

-for template in parsed.templates:
+for template in reversed(parsed.templates):

This works because WikiText.templates are returned in the order they appear in the text. Modifying a later template never invalidates its preceding parent.