Whole file
martinblech/xmltodict
The author described this change as “fix(streaming): avoid parent accumulation at item_depth; add regression tests”. It counts as a record because the check below fails on the code as it stood at 8a2c93e35 and passes on 220240c5e, with nothing else changed between the two runs.
Projectmartinblech/xmltodict
Fix saved2025-09-12
Sharing licenceMIT · LICENSE
Change size+13 −1
What the code was meant to do, written into the code itself as a save note
fix(streaming): avoid parent accumulation at item_depth; add regression tests
The change
| 111 | 111 | ||
| 112 | 112 | def endElement(self, full_name): | |
| 113 | 113 | name = self._build_name(full_name) | |
| 114 | + | # If we just closed an item at the streaming depth, emit it and drop it | |
| 115 | + | # without attaching it back to its parent. This avoids accumulating all | |
| 116 | + | # streamed items in memory when using item_depth > 0. | |
| 114 | 117 | if len(self.path) == self.item_depth: | |
| 115 | 118 | item = self.item | |
| 116 | 119 | if item is None: | |
| ⋯ | |||
| 120 | 123 | should_continue = self.item_callback(self.path, item) | |
| 121 | 124 | if not should_continue: | |
| 122 | 125 | raise ParsingInterrupted | |
| 126 | + | # Reset state for the parent context without keeping a reference to | |
| 127 | + | # the emitted item. | |
| 128 | + | if self.stack: | |
| 129 | + | self.item, self.data = self.stack.pop() | |
| 130 | + | else: | |
| 131 | + | self.item = None | |
| 132 | + | self.data = [] | |
| 133 | + | self.path.pop() | |
| 134 | + | return | |
| 123 | 135 | if self.stack: | |
| 124 | 136 | data = (None if not self.data | |
| 125 | 137 | else self.cdata_separator.join(self.data)) | |
| ⋯ | |||
| 549 | 561 | ||
| 550 | 562 | ||
| 551 | 563 | if __name__ == '__main__': # pragma: no cover | |
| 552 | - | import sys | |
| 553 | 564 | import marshal | |
| 565 | + | import sys | |
| 554 | 566 | try: | |
| 555 | 567 | stdin = sys.stdin.buffer | |
| 556 | 568 | stdout = sys.stdout.buffer | |
The check that tells the two apart
fail→pass·tests/test_xmltodict.py::XMLToDictTestCase::test_streaming_memory_usage
Check file tests/test_xmltodict.py, taken without changes from the fix and copied onto the older code, so the exact same check runs against both versions.
Origin and history
The code before it8a2c93e350b44c98b41f1b5ffc4d0838812b0838
Broken version dated2025-09-12
Modulexmltodict
Units changed_DictSAXHandler
Fingerprint33d4ace280ceefe3
Checked2026-08-18 by goldset/0.1
Every field above is generated by our program. None of it is written by hand.
Other bugs found in martinblech/xmltodict
- 2026-02-15fix(unparse): serialize None text/attrs as empty values (fixes #401)
- 2025-09-17fix: allow DOCTYPE with disable_entities=True (default)
- 2025-09-16fix: fail closed when entities disabled
- 2025-09-16fix: validate XML comments
- 2025-09-12fix(unparse): handle non-string `#text` with attributes; unify value conversion
- 2025-09-12fix(unparse): skip empty lists to keep pretty/compact outputs consistent