Skip to content

Conversation

@Guiforge
Copy link

Fix Markdown export under Python optimized mode (-O)

Context

Issue: docling-project/docling-core#460

Markdown export could crash when running Python with optimizations enabled (e.g. python -O or PYTHONOPTIMIZE=1).

Symptom

UnboundLocalError: cannot access local variable 'list_group' where it is not associated with a value

This surfaced during Markdown serialization of list items.

Root cause

In docling_core/transforms/serializer/markdown.py (Markdown list item serialization), list_group was assigned via the walrus operator inside an assert:

  • assert item.parent and isinstance((list_group := item.parent.resolve(doc)), ListGroup)

Under -O, Python strips assert statements entirely, so the assignment never executes. Since Python still treats list_group as a local variable in the function, later references to list_group raise UnboundLocalError.

(Conceptually the same as Ruff rule RUF018: assignment in assert.)

Fix

  • Remove the assignment from the assert.
  • Resolve list_group explicitly (outside of assert) and guard access with an is not None check.
  • If the parent is unexpectedly missing or not a ListGroup, fall back to the safe Markdown marker - rather than crashing.

This preserves existing behavior for valid documents and prevents optimized-mode crashes.

Tests

  • Added test/test_markdown_optimized_mode.py which spawns a subprocess with sys.executable -O and calls DoclingDocument.export_to_markdown() on a minimal document that triggers list marker normalization.

Notes

  • No public APIs changed.
  • Behavior is strictly more robust: malformed list structures no longer crash serialization in optimized mode.

Avoid assignment-in-assert during list marker normalization (issue docling-project#460).
@github-actions
Copy link
Contributor

github-actions bot commented Dec 31, 2025

DCO Check Passed

Thanks @Guiforge, all your commits are properly signed off. 🎉

@dosubot
Copy link

dosubot bot commented Dec 31, 2025

Related Documentation

Checked 10 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

@mergify
Copy link

mergify bot commented Dec 31, 2025

Merge Protections

Your pull request matches the following merge protections and will not be merged until they are valid.

🟢 Enforce conventional commit

Wonderful, this rule succeeded.

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\(.+\))?(!)?:

@cau-git
Copy link
Member

cau-git commented Jan 13, 2026

@Guiforge thanks for this fix! The change looks good to me, but I would suggest to remove the test unit you provide, it should not require a test at this level.

Also, please follow the steps to remediate the DCO as posted by the github-bot here.

@codecov
Copy link

codecov bot commented Jan 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Delete test/test_markdown_optimized_mode.py. The test targeted markdown
serialization under Python -O and has been removed as obsolete.
…ail.com>

I, Guillaume Pouyat <[email protected]>, hereby add my Signed-off-by to this commit: a9ce24f
I, Guillaume Pouyat <[email protected]>, hereby add my Signed-off-by to this commit: 88b8996

Signed-off-by: Guillaume Pouyat <[email protected]>
…ail.com>

I, Guillaume Pouyat <[email protected]>, hereby add my Signed-off-by to this commit: a9ce24f
I, Guillaume Pouyat <[email protected]>, hereby add my Signed-off-by to this commit: 88b8996

Signed-off-by: Guillaume Pouyat <[email protected]>
@Guiforge Guiforge closed this Jan 21, 2026
@Guiforge
Copy link
Author

Guiforge commented Jan 21, 2026

I closed; it seems solved. 👍 (#456)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants