Skip to content

fix(sections): end an 8-K's last item at a preformatted signature statement (GH #1563) - #1564

Merged
dgunning merged 2 commits into
dgunning:mainfrom
shivampwm2020:fix/1563-8k-signature-preformatted
Oct 18, 2026
Merged

dgunning merged 2 commits into
dgunning:mainfrom
shivampwm2020:fix/1563-8k-signature-preformatted

Conversation

@shivampwm2020

Copy link
Copy Markdown
Contributor

What this changes

An 8-K whose primary document is one preformatted (<pre>) block of plain text keeps the SIGNATURE block out of its last item again. Item 8.01 of 0000710782-24-000002 went back to its pre-#1534 length.

Fixes #1563

Root cause

#1393 ends an 8-K's last item at the signature statement when the filing has no SIGNATURES heading — Strategy 5c of pattern_section_extractor.py, matching _SIGNATURE_STATEMENT, anchored at ^Pursuant to the requirements of the Securities Exchange Act of 1934.

#1534 then made a no-<TABLE> plain-text body split at blank lines (document_builder._add_text). In this filing the source has no blank line between the bare SIGNATURE heading and that prescribed sentence, so the two now arrive as one paragraph starting SIGNATURE Pursuant to .... The ^-anchored pattern no longer matched, Strategy 5c found no boundary, and the last item ran on through the signature block.

_SIGNATURE_STATEMENT now accepts an optional leading SIGNATURE/SIGNATURES label before the prescribed sentence. The caused this (report|amendment) to be signed requirement is unchanged, so a paragraph that merely cites the Exchange Act still is not a boundary.

Verification

  • Ground truth: at least one assertion checks a specific value against a real SEC filing I verified by hand. Filing and accession: Liaoning Shuiyun Qinghe Rice Industry Co., Ltd., CIK 710782, 8-K 0000710782-24-000002, filed 2024-02-05, Item 8.01 (primary document 8k01.htm, one <pre> block, 3,411 chars; SIGNATURE at offset 3,037). Item 8.01 is 972 chars after the fix (was 1,348), ending ...enhancing the company's global competitiveness.; the signature statement is still exposed as the signatures section (374 chars, contains Baobing He).
  • Regression test for a bug is in tests/issues/regression/, and its docstring links the issue: tests/issues/regression/test_issue_1563.py, offline against the real document stored at tests/fixtures/issues/0000710782-24-000002.html.
  • Cassettes were recorded from live SEC and not edited afterwards (see CONTRIBUTING.md). Recorded on: n/a — the test is offline and needs no cassette; no cassette is touched.
  • Silence check: bad or missing input produces a useful error, not None — unchanged by this PR.
  • Docs: any documented example this touches still runs — no documented example touches this path.
  • Changelog: changelog.d/1563.fixed.md.

Red → green: reverting the one-line regex change makes all three assertions in test_issue_1563.py fail with 1348 != 972 and 'SIGNATURE' in text; restoring it passes. test_issue_879.py (the #879/#1393 SIGNATURE suite, offline class) and test_issue_1ho_8k_section_detection.py still pass: 28 passed, 7 skipped. Suite run locally with EDGAR_IDENTITY set; cassette-backed tests were not run (they need the repo's recorded cassettes, which I did not fetch).

6.0

  • This PR adds a deprecation, a 6.0 warning, or a "removed in 6.0" note, and docs/upgrade/6.0.md says what users see now and what to do instead — not applicable.

AI assistance

  • None
  • Assisted. Tool and model: Hermes Agent (Nous Research), model deepseek/deepseek-flash.

Working context

Reproduced first: parse_html(8k01.htm, ParserConfig(form="8-K")) gave item_801 at 1,348 chars with SIGNATURE included, matching the report exactly. Instrumenting ParagraphNodes showed the signature paragraph's normalized text is SIGNATURE Pursuant to the requirements of the Securities Exchange Act of 1934, the Registrant has duly caused this report to be sig... — the ^Pursuant anchor is what broke, not the node type or the blank-line split itself. That ruled out a fix in document_builder (#1534) and left the pattern. After the fix the filing yields two sections: item_801 (972) and signatures (374).

…tement (GH dgunning#1563)

An 8-K whose primary document is one preformatted (<pre>) block of plain
text kept the SIGNATURE block inside its last item, the behavior dgunning#1393
had already fixed for other layouts.

dgunning#1534 split a no-<TABLE> plain-text body at blank lines
(document_builder._add_text), so a bare SIGNATURE heading and the
sentence Form 8-K's General Instructions prescribe arrive as one
paragraph when the source has no blank line between them. Strategy 5c's
_SIGNATURE_STATEMENT was anchored at ^Pursuant to, so it no longer
matched and the last item ran on through the signature block.

_SIGNATURE_STATEMENT now accepts an optional leading SIGNATURE(S) label
before the prescribed sentence.

Filing 0000710782-24-000002 (CIK 710782, filed 2024-02-05, Item 8.01,
primary document 8k01.htm, one <pre> of 3,411 characters):
  before: Item 8.01 = 1,348 chars, SIGNATURE at offset 3,037 included
  after:  Item 8.01 = 972 chars, ending "...global competitiveness."

Regression test: tests/issues/regression/test_issue_1563.py (offline,
fixture tests/fixtures/issues/0000710782-24-000002.html).
@dgunning

Copy link
Copy Markdown
Owner

Thanks, this is a clean fix with a well-documented root cause. I verified:

  • the fixture is byte-identical to 8k01.htm as served by SEC for 0000710782-24-000002;
  • 972 chars by hand: the 24-char heading plus paragraphs of 440, 220 and 282, joined by \n\n; SIGNATURE (line 84) and the prescribed sentence (line 85) have no blank line between them, as you describe;
  • reverting the regex fails all three new tests; with it, they pass, along with the 8-K item text includes the trailing SIGNATURES section (leaks into the last item) #879 and 8-K section suites, including the cassette-backed tests (35 passed) on top of current main.

Fixing the regex rather than the #1534 split is the right call: the change applies only to 8-Ks, only after the last item, and still requires "caused this report to be signed". Two optional nits: a module-scoped fixture would avoid parsing the document three times, and the changelog bullet could drop the root-cause clause (we keep that in the PR and commit). Neither blocks the merge.

…viour

dgunning's review noted the document was parsed three times and that the
changelog bullet duplicated the root cause we keep in the PR and commit.
The fixture is now module-scoped and the bullet states the behaviour only.

No assertion or fixture content changes; 3 tests still pass.
@shivampwm2020

Copy link
Copy Markdown
Contributor Author

Both nits taken in 93c3cee.

Fixture: the document is now parsed once per module via a module-scoped report fixture, and the three cases take it as an argument instead of calling _parse_report() each time. Parsing cost is now paid once rather than three times.

Changelog: dropped the root-cause clause from changelog.d/1563.fixed.md, as you did on #1556. The bullet now states the behaviour only; the mechanism stays in the commit and PR.

No assertion, fixture content or expected-length changes. pytest tests/issues/regression/test_issue_1563.py -> 3 passed.

Neither nit blocked the merge, so this is purely polish before you merge.

@dgunning
dgunning merged commit 6fcc0fb into dgunning:main Oct 18, 2026
11 checks passed
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.

8-K last item keeps the SIGNATURE block since #1534 (preformatted filing body)

2 participants