BUG: Fix PageRange.__add__ crashing with TypeError when start or stop is None#3898
BUG: Fix PageRange.__add__ crashing with TypeError when start or stop is None#3898gaoflow wants to merge 2 commits into
Conversation
… is None
PageRange.__add__ compared slice bounds with `>` directly, which raises
TypeError when either bound is None. Slices with None start (":5") or
None stop ("5:") are perfectly valid and common, so adding two such
ranges could crash instead of returning the correct union.
Fix: introduce two small key functions that map None start to -inf and
None stop to +inf before all comparisons and the max-stop selection.
All existing tests continue to pass; new cases like
PageRange("0:5") + PageRange("3:") # => PageRange("0:")
PageRange(":5") + PageRange(":3") # => PageRange(":5")
now work correctly.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3898 +/- ##
==========================================
+ Coverage 97.85% 97.86% +0.01%
==========================================
Files 57 57
Lines 10702 10743 +41
Branches 2001 2006 +5
==========================================
+ Hits 10472 10514 +42
Misses 127 127
+ Partials 103 102 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| def parse_filename_page_ranges( | ||
| args: list[Union[str, PageRange, None]] | ||
| ) -> list[tuple[str, PageRange]]: | ||
| def parse_filename_page_ranges(args: list[Union[str, PageRange, None]]) -> list[tuple[str, PageRange]]: |
There was a problem hiding this comment.
Please avoid unnecessary changes.
There was a problem hiding this comment.
Restored in 3a1e152a. Verification passed:
python -m pytest tests/test_pagerange.py -q
python -m ruff check pypdf/pagerange.py tests/test_pagerange.py| raise ValueError( | ||
| "The first argument must be a filename, not a page range." | ||
| ) | ||
| raise ValueError("The first argument must be a filename, not a page range.") |
There was a problem hiding this comment.
Please avoid unnecessary changes.
There was a problem hiding this comment.
Restored in 3a1e152a. Verification passed:
python -m pytest tests/test_pagerange.py -q
python -m ruff check pypdf/pagerange.py tests/test_pagerange.py|
Reverted both unrelated reformatting changes (the |
Problem
PageRange.__add__raisesTypeError: '>' not supported between instances of 'int' and 'NoneType'(orNoneTypeandint, orNoneTypeandNoneType) whenever either operand has aNonestart orNonestop, which is perfectly normal for ranges like"5:"or":3".The problem is that
__add__comparesslice.startandslice.stopwith>directly.Nonebounds are not comparable to integers, but they are semantically well-defined:Nonestart = "beginning of sequence" andNonestop = "end of sequence".Fix
Add two small helper functions inside
__add__that mapNoneto float sentinels before any comparison:_start_key(None)→-inf(beginning sorts before any page index)_stop_key(None)→+inf(end sorts after any page index)Replace the direct comparisons and
max()call with these key functions. No public API changes.Behaviour after fix
All 23 existing tests continue to pass.
This pull request was prepared with the assistance of AI, under my direction and review.