Skip to content

Don't read a number inside a scanner tag as the issue number - #547

Closed
andreasorbelli wants to merge 1 commit into
allaboutduncan:mainfrom
andreasorbelli:fix/bracket-tags-read-as-issue-number
Closed

Don't read a number inside a scanner tag as the issue number#547
andreasorbelli wants to merge 1 commit into
allaboutduncan:mainfrom
andreasorbelli:fix/bracket-tags-read-as-issue-number

Conversation

@andreasorbelli

@andreasorbelli andreasorbelli commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

📝 Description

Closes #545

extract_issue_number strips parenthetical groups before looking for the number — the comment
there says year groups must not interfere with finding the last digit sequence. Square brackets
carry the same kind of noise, resolutions and years and scanner handles, and were left in.

The three-or-more-digit rule takes the last match and requires whitespace on both sides, so a
number in the middle of a tag beats the real issue number, while one that opens or closes the tag
is safe:

Filename main this branch
Daredevil 012 [c2c 1440 px].cbz 1440 12
Hellblazer 25 [Minutemen 2011 ed].cbz 2011 25
Batman 001 (2016) [Empire 2015 rescan].cbz 2015 1
Topolino 0330 (Mondadori 1962-03-25) [c2c Hal 2008 & Bibbo64].cbr 2008 330
Preacher 007 [1280 web].cbz 7 7
Batman 001 (2016) [digital] [Empire 2015].cbz 1 1
Tex 700 [c2c].cbz 700 700

The failure is silent: the file matches a real issue, just the wrong one, and metadata is written
with no warning. The last row of the first group is not constructed — it came out of the
measurement in #540, over a real library, where the file is tagged as issue #2008 published 1994
when it is issue #330 from 1962.

Which paths this reaches

core/bulk_metadata.py calls extract_issue_number directly, so a bulk run is exposed for every
name in the table. /api/search-metadata parses with the rename parser first and only falls back
to extract_issue_number when that yields no issue number — so it is exposed for some of these and
not others, which is worth being precise about:

Daredevil 012 [c2c 1440 px].cbz     rename parser -> issue '12'   (no fallback; search path fine)
Hellblazer 25 [Minutemen 2011 ed]   rename parser -> issue ''     -> fallback -> 2011 on main

So the same filename can tag correctly through one path and incorrectly through another, which is
part of why it is hard to spot from the outside.

The change

Strip bracketed groups where parenthetical groups are already stripped, as properly-paired
alternatives so a (…) containing a […] is still handled as one group. That is the
three-or-more-digit rule only. The one- and two-digit rule runs against the raw name and takes its
first match rather than its last, so it is not exposed the same way, and leaving it alone keeps
the change on the path that is actually wrong.

What it costs. An issue number that only ever appears inside brackets stops being found —
Daredevil [012].cbz returns nothing rather than 12. No convention writes them that way, and such
a file falls back to the remaining rules rather than being mistagged, but there is a test pinning
it so it stays a recorded decision rather than a later surprise.

🛠️ Changes Made

  • Added new feature logic
  • Updated Docker/Config if necessary — nothing to update; no new settings, no new dependencies
  • Verified build locally (docker build -t dev .)

Two files: the parser in models/providers/base.py, and the tests. +42 / −4.

📸 Screenshots / Logs

Both parsers, run inside the built images — main at d8e046e and this branch — so the numbers
above are what the shipped code does, not what the test suite mocks:

main:    bulk path -> 1440   Daredevil 012 [c2c 1440 px].cbz
         bulk path -> 2011   Hellblazer 25 [Minutemen 2011 ed].cbz   (search path too: 2011)
         bulk path -> 2008   Topolino 0330 (Mondadori 1962-03-25) [c2c Hal 2008 & Bibbo64].cbr
branch:  bulk path ->   12 /   25 /  330 for the same three
both:    bulk path ->    7 / 700       Preacher 007 [1280 web].cbz, Tex 700 [c2c].cbz

🧪 Testing Performed

  • Manual test in dev container — the parse comparison above
  • Linting/Unit tests pass

Twelve new cases in tests/unit/test_provider_base.py: the four broken shapes, the four that
already parsed correctly and must keep doing so, both group kinds together in either order, the
bracket-only number that is the cost of the change, and an unterminated bracket, which is left
untouched exactly as an unterminated parenthesis always was. Six fail on main — the four broken
shapes and the two mixed ones; the rest pass either way and are there as guards.

Every existing case in that file is unchanged and still passes, including the ones the docstring
advertises (Spider-Man 2099 001 (1992), Amazing Spider-Man (2018) Issue 080.BEY, Gen 13 013A)
and the filename from #223, the V2021 bug you closed earlier in this same family.


🤖 Generated with Claude Code

https://claude.ai/code/session_01MTCdHCCLmS4uMZG9NZWTz6

The parser strips parenthetical groups before looking for the number, with a
comment saying year groups must not interfere with finding the last digit
sequence. Square brackets carry the same noise — resolutions, years, scanner
handles — and were left in.

The three-or-more-digit rule takes the LAST match and wants whitespace on both
sides, so a number in the middle of a tag beats the real issue number, while
one that opens or closes the tag is safe:

    Daredevil 012 [c2c 1440 px].cbz          -> 1440, not 12
    Hellblazer 25 [Minutemen 2011 ed].cbz    -> 2011, not 25
    Preacher 007 [1280 web].cbz              -> 7      (already right)

The failure is silent. The file matches a real issue, just the wrong one, and
metadata is written with no warning. From the measurement in allaboutduncan#540, over a real
library: Topolino 0330 (Mondadori 1962-03-25) [c2c Hal 2008 & Bibbo64].cbr is
tagged as issue #2008 published 1994, when it is allaboutduncan#330 from 1962.

So strip bracketed groups where parenthetical groups are already stripped.
This is the three-or-more-digit rule only: the one- and two-digit rule runs
against the raw name and takes its first match rather than its last, so it is
not exposed the same way and is left alone.

It costs one thing, and there is a test pinning it: an issue number that only
ever appears inside brackets stops being found. No convention writes them that
way, and such a file falls back to the remaining rules rather than being
mistagged, but it should be a recorded decision rather than a surprise.

Closes allaboutduncan#545

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MTCdHCCLmS4uMZG9NZWTz6
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.

Scanner tags in square brackets are read as the issue number

2 participants