Skip to content

fix(robustness): improve Markdown link parsing, diagnostics, and thread safety - #66

Merged
lkdmc merged 1 commit into
mainfrom
fix/robustness
Mar 31, 2026
Merged

fix(robustness): improve Markdown link parsing, diagnostics, and thread safety#66
lkdmc merged 1 commit into
mainfrom
fix/robustness

Conversation

@lkdmc

@lkdmc lkdmc commented Mar 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

Three robustness improvements that prevent silent misbehaviour in edge cases.

1. Fragile Markdown link parsing in _build_attribution_display (__init__.py:951)

The source-value parser used split("](") to detect the [text](url) format. This breaks silently when the URL itself contains the two-character sequence ]( (e.g. some documentation links with anchor fragments). The check len(...split("](")) == 2 also passed spuriously for strings with a single ]( anywhere.

Fix: replace the split heuristic with re.fullmatch(r"\[([^\]]+)\]\(([^)]+)\)", ...) which correctly matches only well-formed Markdown inline links and is unambiguous regardless of URL content.


2. Misleading diagnostic messages for imageless figures (__init__.py:510)

When a figure has no image argument, the code appended "dummy.png" to self.arguments as a placeholder, and all subsequent warning and error messages used self.arguments[0]. Every diagnostic for such a figure therefore reported "dummy.png" instead of a meaningful identifier, making it impossible to locate the offending directive.

Fix: capture _figure_id = self.arguments[0] if self.arguments else "<no image>" before the placeholder is appended, and use _figure_id in all diagnostic messages (unrecognized BibTeX key, missing/invalid license, invalid date, missing source).


3. Thread-unsafe lazy initialisation of _untranslate_map_cache (__init__.py:1672)

parallel_read_safe = True allows Sphinx to fork worker processes that call untranslate_license() concurrently. The previous check-and-set pattern (if _untranslate_map_cache is None: _untranslate_map_cache = ...) is not atomic; two workers can both observe None and both call _load_untranslate_map() simultaneously.

Fix: protect the initialisation block with a threading.Lock using the double-checked locking pattern so that the JSON file is read at most once per process regardless of concurrency.

Test plan

  • Set :source: to a URL containing ]( (e.g. [docs](https://example.com/path#section)) and confirm the link renders correctly.
  • Create a figure with no image argument and an invalid license; confirm the warning names <no image> rather than dummy.png.
  • Run a parallel Sphinx build (sphinx-build -j auto) with a non-English locale and confirm no exception from concurrent untranslate_license() calls.

https://claude.ai/code/session_01ApsmWPWsKBesMV1rq2VenA

…read safety

1. Fragile Markdown link parsing: replace the split("](") heuristic in
   _build_attribution_display with a re.fullmatch() call using the pattern
   \[([^\]]+)\]\(([^)]+)\).  The old approach broke silently when the URL
   itself contained the two-character sequence "](".

2. Misleading diagnostic messages for imageless figures: capture the
   original figure identifier (_figure_id) before the "dummy.png"
   placeholder is appended to self.arguments.  All warning/error messages
   that referenced self.arguments[0] now use _figure_id so they report
   "<no image>" instead of "dummy.png" for caption-only figures.

3. Thread-unsafe global cache: _untranslate_map_cache is now initialised
   under a threading.Lock using the double-checked locking pattern so that
   parallel Sphinx read workers cannot race to load the JSON file at the
   same time.

https://claude.ai/code/session_01ApsmWPWsKBesMV1rq2VenA
@lkdmc
lkdmc requested a review from douden as a code owner March 31, 2026 16:11
@lkdmc
lkdmc merged commit fd16b27 into main Mar 31, 2026
3 checks passed
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