Skip to content

fix(loaders): accumulate all pages in CustomDocLoader (#376) - #400

Merged
EnjoyBacon7 merged 5 commits into
refactor/hexagonalfrom
fix/376-customdocloader-page-accumulation
May 21, 2026
Merged

fix(loaders): accumulate all pages in CustomDocLoader (#376)#400
EnjoyBacon7 merged 5 commits into
refactor/hexagonalfrom
fix/376-customdocloader-page-accumulation

Conversation

@EnjoyBacon7

@EnjoyBacon7 EnjoyBacon7 commented May 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

openrag/components/indexer/loaders/CustomDocLoader.py:37 used s = p.page_content.strip() + ... inside the page loop, overwriting s on every iteration. Result: every multi-page legacy .doc/.docx/.odt document indexed via this loader silently dropped every page except the last, with no error visible in logs.

This PR changes the assignment to s += so all pages are accumulated.

Test plan

  • Load a .doc file with three or more pages and confirm all pages are present in the returned content
  • Existing unit tests for loaders still pass

Fixes #376

Summary by CodeRabbit

  • Bug Fixes

    • Fixed document loader so multi-page documents now preserve and concatenate every page’s content with page separators, preventing data loss across pages.
  • Tests

    • Added a regression test that verifies multi-page documents are fully accumulated and include the expected page markers to prevent regressions.

Review Change Stack

Previously the loop body used '=' so each iteration overwrote 's',
returning only the final page. Switch to '+=' so all pages are
concatenated as intended.

Fixes #376
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 46d64661-6084-4681-b729-cb21962f023e

📥 Commits

Reviewing files that changed from the base of the PR and between b6a24b5 and 186fbcc.

📒 Files selected for processing (1)
  • openrag/components/indexer/loaders/test_customdocloader.py

📝 Walkthrough

Walkthrough

CustomDocLoader.aload_document now concatenates each cleaned page's text (s += ...) instead of overwriting, and a new async regression test verifies that three mocked pages are aggregated with their [PAGE_n] markers present.

Changes

Multi-page Document Content Preservation

Layer / File(s) Summary
Page content accumulation fix
openrag/components/indexer/loaders/CustomDocLoader.py
Line 37 changed from s = ... to s += ..., accumulating cleaned page content across iterations so all pages are preserved in the returned Document.
Regression test: multi-page aggregation
openrag/components/indexer/loaders/test_customdocloader.py
Adds test_customdocloader_accumulates_all_pages that patches the .docx loader to return three mocked Document pages and asserts the aggregated page_content contains each page’s text and [PAGE_n] markers.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I nibble lines and stitch each page,

no text escapes my tiny sage.
Where once the last page took the crown,
now every page gets hopped upon.
All pages saved — hooray, abound!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(loaders): accumulate all pages in CustomDocLoader' clearly and specifically describes the main change: fixing the page accumulation bug in the CustomDocLoader component.
Linked Issues check ✅ Passed The PR fully addresses issue #376 by changing the assignment to accumulation (s +=) and adding a regression test that verifies all pages are accumulated.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the page accumulation bug and adding a test for it; no out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/376-customdocloader-page-accumulation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
openrag/components/indexer/loaders/CustomDocLoader.py (1)

22-39: ⚠️ Potential issue | 🔴 Critical

Add a unit test for CustomDocLoader that verifies multi-page document accumulation.

The PR objectives require a unit test loading a multi-page fixture (≥3 pages) and asserting that text from each page is present in the returned content, but no such test exists in the repository. The implementation in aload_document() correctly accumulates pages with [PAGE_N] markers, but this critical functionality is untested.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openrag/components/indexer/loaders/CustomDocLoader.py` around lines 22 - 39,
Add a new async unit test that exercises CustomDocLoader.aload_document by
loading a multi-page fixture (≥3 pages) and asserting the returned
Document.page_content contains the text from each page and the corresponding
"[PAGE_1]", "[PAGE_2]", "[PAGE_3]" markers; instantiate or reference the same
loader registration used by CustomDocLoader.doc_loaders for the fixture suffix,
call await CustomDocLoader().aload_document(fixture_path, metadata=...) (or the
correct class/method used in your code), and use pytest/pytest-asyncio to run
the coroutine and assert that each page's unique text and all PAGE_N markers
appear in the combined content. Ensure the test uses a deterministic multi-page
fixture and cleans up any temp files if created.
🧹 Nitpick comments (1)
openrag/components/indexer/loaders/CustomDocLoader.py (1)

35-37: ⚡ Quick win

Consider using list + join for string concatenation.

The current implementation using += in a loop creates a new string object on each iteration (since strings are immutable in Python). For documents with many pages, accumulating parts in a list and joining once at the end is more efficient.

⚡ Performance optimization using list + join
-        s = ""
+        parts = []
         for page_num, p in enumerate(pages, start=1):
-            s += p.page_content.strip() + f"\n[PAGE_{page_num}]\n"
+            parts.append(p.page_content.strip())
+            parts.append(f"\n[PAGE_{page_num}]\n")
+        s = "".join(parts)
 
         return Document(page_content=s, metadata=metadata)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openrag/components/indexer/loaders/CustomDocLoader.py` around lines 35 - 37,
The string accumulation using s += inside the loop (variable s built from pages,
page_num and p.page_content) is inefficient; change it to collect fragments in a
list (append each p.page_content.strip() plus the page marker like
"\n[PAGE_{page_num}]\n") and after the loop call "".join(fragments) to produce
the final string, using the same page marker format so behavior of the code (and
any function/class in this file that uses s) remains identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@openrag/components/indexer/loaders/CustomDocLoader.py`:
- Around line 22-39: Add a new async unit test that exercises
CustomDocLoader.aload_document by loading a multi-page fixture (≥3 pages) and
asserting the returned Document.page_content contains the text from each page
and the corresponding "[PAGE_1]", "[PAGE_2]", "[PAGE_3]" markers; instantiate or
reference the same loader registration used by CustomDocLoader.doc_loaders for
the fixture suffix, call await CustomDocLoader().aload_document(fixture_path,
metadata=...) (or the correct class/method used in your code), and use
pytest/pytest-asyncio to run the coroutine and assert that each page's unique
text and all PAGE_N markers appear in the combined content. Ensure the test uses
a deterministic multi-page fixture and cleans up any temp files if created.

---

Nitpick comments:
In `@openrag/components/indexer/loaders/CustomDocLoader.py`:
- Around line 35-37: The string accumulation using s += inside the loop
(variable s built from pages, page_num and p.page_content) is inefficient;
change it to collect fragments in a list (append each p.page_content.strip()
plus the page marker like "\n[PAGE_{page_num}]\n") and after the loop call
"".join(fragments) to produce the final string, using the same page marker
format so behavior of the code (and any function/class in this file that uses s)
remains identical.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d5522239-e9c0-4eb0-a31a-714ce611f6a1

📥 Commits

Reviewing files that changed from the base of the PR and between 470c30e and c934b22.

📒 Files selected for processing (1)
  • openrag/components/indexer/loaders/CustomDocLoader.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
openrag/components/indexer/loaders/test_customdocloader.py (1)

23-34: ⚡ Quick win

Verify mocked loader interactions to avoid false positives.

The test should also assert the mocked loader path was actually used and awaited once, so it fails if aload_document stops calling the patched loader.

Suggested interaction assertions
     with patch.dict(CustomDocLoader.doc_loaders, {".docx": fake_loader_cls}, clear=True):
         # BaseLoader.__init__ pulls a config; we bypass it with object.__new__
         loader = object.__new__(CustomDocLoader)
         result = await loader.aload_document(str(file_path), metadata={"src": "x"})
 
+    fake_loader_cls.assert_called_once()
+    fake_loader_instance.aload.assert_awaited_once()
+
     assert "page-one" in result.page_content
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openrag/components/indexer/loaders/test_customdocloader.py` around lines 23 -
34, Add assertions to verify the patched loader was invoked and its async load
was awaited: after creating loader and calling await loader.aload_document(...),
assert that fake_loader_cls was called once with the file path string (the
loader factory was used) and assert that fake_loader_instance.aload was awaited
exactly once with the expected metadata argument (e.g. metadata={"src":"x"}) so
the test fails if CustomDocLoader.aload_document stops calling the patched
loader.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openrag/components/indexer/loaders/test_customdocloader.py`:
- Around line 38-39: The test currently only asserts "[PAGE_1]" and "[PAGE_3]"
in result.page_content, missing the middle marker; update the test in
test_customdocloader.py (around the assertions for result.page_content) to also
assert that "[PAGE_2]" is present so the intermediate page marker is validated
(i.e., add an assertion that result.page_content contains "[PAGE_2]").

---

Nitpick comments:
In `@openrag/components/indexer/loaders/test_customdocloader.py`:
- Around line 23-34: Add assertions to verify the patched loader was invoked and
its async load was awaited: after creating loader and calling await
loader.aload_document(...), assert that fake_loader_cls was called once with the
file path string (the loader factory was used) and assert that
fake_loader_instance.aload was awaited exactly once with the expected metadata
argument (e.g. metadata={"src":"x"}) so the test fails if
CustomDocLoader.aload_document stops calling the patched loader.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f34a8441-e730-4605-916c-751298c89f0c

📥 Commits

Reviewing files that changed from the base of the PR and between c934b22 and b6a24b5.

📒 Files selected for processing (1)
  • openrag/components/indexer/loaders/test_customdocloader.py

Comment thread openrag/components/indexer/loaders/test_customdocloader.py
@EnjoyBacon7
EnjoyBacon7 merged commit 90fec29 into refactor/hexagonal May 21, 2026
6 checks passed
@EnjoyBacon7
EnjoyBacon7 deleted the fix/376-customdocloader-page-accumulation branch May 21, 2026 11:38
@Ahmath-Gadji Ahmath-Gadji added the fix Fix issue label Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Fix issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants