Skip to content

MAINT: Split PdfDocCommon._flatten - #4070

Merged
stefan6419846 merged 10 commits into
mainfrom
maint/flatten-helpers
Sep 14, 2026
Merged

stefan6419846 merged 10 commits into
mainfrom
maint/flatten-helpers

Conversation

@MartinThoma

@MartinThoma MartinThoma commented Sep 10, 2026 •

Copy link
Copy Markdown
Member

Split _flatten into three functions to make it easier to read:

  • _flatten_page_tree_node
  • _flatten_leaf_page

This makes it easier to understand the function.

Meta

This PR is a first step towards #4061 which is easier to review as it doesn't change the way data is processed, only the structure of the code by splitting _flatten

MartinThoma and others added 2 commits September 10, 2026 08:48
_flatten mixed argument-defaulting, page-tree-root resolution, node-type
classification, /Pages recursion and /Page construction in one ~135-line
method (cyclomatic complexity 30).

Extract three private helpers, leaving _flatten as a small orchestrator:

- _page_tree_node_type: classify a node as "/Pages" or "/Page", including
  the no-/Type strict-mode heuristic.
- _flatten_page_tree_node: propagate inheritable attributes and recurse
  into /Kids, with the cycle checks and entry-limit enforcement.
- _flatten_leaf_page: build the PageObject and append it to flattened_pages.

Behaviour is unchanged. Radon complexity drops from D(30) to
_flatten B(10), _flatten_page_tree_node C(13), _page_tree_node_type B(6),
_flatten_leaf_page A(4).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
(cherry picked from commit b45900b)
Three behaviours of PdfDocCommon._flatten that are wrong today and are
marked xfail until the traversal is reworked:

- A page tree deeper than the interpreter recursion limit raises
  RecursionError before Configuration.page_tree_maximum_depth can apply.
- A document catalog without /Pages raises AttributeError from
  .get_object() on None instead of PdfReadError.
- A mid-traversal error leaves self.flattened_pages as a truncated,
  non-None list, so a later page access silently serves the wrong count
  instead of re-raising.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The changes are a mechanical refactor plus xfail regression tests, with no functional behavior changes introduced in the page-tree processing logic.

Pull request overview

This PR is a maintenance-focused refactor of PdfDocCommon._flatten, splitting portions of its logic into smaller helper methods to make subsequent changes (notably the iterative-flatten work in #4061) easier to review and implement without changing current traversal behavior.

Changes:

  • Split _flatten by extracting page-tree node classification into _page_tree_node_type.
  • Extract /Pages node handling into _flatten_page_tree_node and leaf /Page construction into _flatten_leaf_page.
  • Add three xfail regression tests documenting known current limitations/bugs in recursive flattening and error handling.
File summaries
File Description
tests/test_doc_common.py Adds xfail tests capturing current recursive-depth and error-handling shortcomings to lock in expected fixes for the follow-up work.
pypdf/_doc_common.py Refactors _flatten into helper methods without changing the current recursive traversal approach.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@codecov

codecov Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.12%. Comparing base (d26df36) to head (8f1b2af).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4070   +/-   ##
=======================================
  Coverage   98.11%   98.12%           
=======================================
  Files          59       59           
  Lines       11489    11495    +6     
  Branches     2150     2150           
=======================================
+ Hits        11273    11280    +7     
  Misses        122      122           
+ Partials       94       93    -1     

☔ 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.

@MartinThoma
MartinThoma marked this pull request as ready for review September 11, 2026 10:16
Comment thread pypdf/_doc_common.py
Comment thread pypdf/_doc_common.py Outdated
Comment thread pypdf/_doc_common.py Outdated
Comment thread tests/test_doc_common.py Outdated
Comment thread tests/test_doc_common.py Outdated
Comment thread tests/test_doc_common.py Outdated
Comment thread tests/test_doc_common.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Address the outstanding refactoring and Ruff formatting comments before approval.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (1)

pypdf/_doc_common.py:1383

  • _flatten already retrieves the configuration at line 1311 for the depth check, so this adds a second ContextVar.get() for every /Pages node. Pass the existing configuration into this helper (or otherwise share it) to avoid the per-node lookup introduced by the refactor.
        configuration = get_configuration()
  • Files reviewed: 2/2 changed files
  • Comments generated: 4
  • Review effort level: Lite

Comment thread pypdf/_doc_common.py Outdated
Comment thread pypdf/_doc_common.py
Comment thread pypdf/_doc_common.py Outdated
Comment thread tests/test_doc_common.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Fix the test’s lint violation by adding spaces around the arithmetic operator.

Review details

Suppressed comments (1)

tests/test_doc_common.py:776

  • This expression omits the whitespace required by the repository's Ruff configuration (select = ["ALL"] in pyproject.toml:151-153), so the new test fails linting. Add spaces around the arithmetic operator.
        with apply_configuration(page_tree_maximum_depth=depth+1):
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No unresolved issues were identified, and the supplied assessments support approval.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@stefan6419846
stefan6419846 merged commit 893a010 into main Sep 14, 2026
32 of 35 checks passed
@stefan6419846
stefan6419846 deleted the maint/flatten-helpers branch September 14, 2026 14:46
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.

3 participants