Skip to content

STY: Type pages as a Sequence rather than a list - #3957

Merged
stefan6419846 merged 1 commit into
py-pdf:mainfrom
RavSinghChandan:fix-pages-return-annotation
Aug 11, 2026
Merged

stefan6419846 merged 1 commit into
py-pdf:mainfrom
RavSinghChandan:fix-pages-return-annotation

Conversation

@RavSinghChandan

Copy link
Copy Markdown
Contributor

Was looking at #3689 and pulled on one of the typeguard failures. PdfDocCommon.pages
is annotated list[PageObject], but it returns a _VirtualList, which is a
Sequence that looks pages up on demand. The mismatch is currently hidden with a
type: ignore[return-value] on the return.

The practical effect is that a type checker will happily accept reader.pages + [page]
or reader.pages.append(page), and both blow up at runtime — TypeError for the
first, AttributeError for the second. Nothing warns you until it runs.

It also accounts for 16 of the "is not a list" failures in test_generic.py under
make testtype. Those go to 0 with this change.

Annotated the property and the matching PdfCommonDocProtocol member as Sequence
and dropped the ignore. One call site needed a cast — _replace_object's cleanup
does del self.pages[page], and _VirtualList implements delitem even though
Sequence doesn't declare it, so I cast there rather than widen the annotation to
MutableSequence, which would be wrong (no append/setitem/insert).

mypy on pypdf/ reports the same 22 pre-existing errors before and after, none in
these two files. Full suite is unchanged: the 3 failures I see locally
(test_build_link__go_to_action_without_destination, two flatten_form_field tests)
and test_appearance_stream_rtl all fail the same way on main — missing cached
fixtures on my machine.

I left the other testtype failures alone since #3689 is still open on what to do
with them overall — this one seemed worth separating out because it's a genuine
annotation bug rather than test-only noise.

PdfDocCommon.pages is annotated list[PageObject] but returns a
_VirtualList, which is a Sequence and looks pages up on demand. The
mismatch was suppressed with a type: ignore[return-value].

A type checker therefore accepts reader.pages + [page] and
reader.pages.append(page); both raise TypeError/AttributeError at
runtime. It is also 16 of the typeguard failures under make testtype.

Annotate the property and the corresponding protocol member as
Sequence, drop the ignore, and cast at the one call site that deletes
a page - _VirtualList implements __delitem__, but Sequence does not
declare it.
@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.89%. Comparing base (0feaf26) to head (ce963ba).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3957   +/-   ##
=======================================
  Coverage   97.89%   97.89%           
=======================================
  Files          57       57           
  Lines       10869    10870    +1     
  Branches     2032     2032           
=======================================
+ Hits        10640    10641    +1     
  Misses        127      127           
  Partials      102      102           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@stefan6419846 stefan6419846 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

@stefan6419846 stefan6419846 changed the title TST: Type pages as a Sequence rather than a list STY: Type pages as a Sequence rather than a list Aug 11, 2026
@stefan6419846
stefan6419846 merged commit cefea4b into py-pdf:main Aug 11, 2026
44 of 49 checks passed
stefan6419846 added a commit that referenced this pull request Aug 13, 2026
## What's new

### Security (SEC)
- Detect cycles in TreeObject.insert_child (#3964) by @stefan6419846

### New Features (ENH)
- AppearanceStream: Allow arbitrary rotations and apply rotations for annotation appearance streams (#3917) by @PJBrs
- AppearanceStream: Consider more encodings for Type1 core fonts (#3905) by @PJBrs

### Performance Improvements (PI)
- Build /ToUnicode source-code bytes directly in parse_bfrange (#3952) by @Anai-Guo

### Bug Fixes (BUG)
- Preserve internal Link annotations when appending/merging (#3953) (#3954) by @Anai-Guo
- Fix false inline image end markers (#3922) by @ciphercom
- Reject typeless non-page /Kids entries in strict mode (#3955) by @Anai-Guo
- Apply character spacing (Tc) per glyph in layout-mode extraction (#3951) by @Anai-Guo
- Keep the Adobe CMYK inversion when an explicit /Decode is present (#3943) by @RavSinghChandan

### Robustness (ROB)
- AppearanceStream: Only escape parentheses for 8-bit fonts (#3961) by @PJBrs
- Recover the trailer from a cross-reference stream when rebuilding the xref (#3950) by @Anai-Guo

### Maintenance (MAINT)
- Deduplicate CatalogAttributes and CatalogDictionary (#3940) by @j-t-1

### Code Style (STY)
- Type pages as a Sequence rather than a list (#3957) by @RavSinghChandan

[Full Changelog](6.15.0...6.16.0)
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