Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 51 additions & 13 deletions docs/upgrade/6.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@ absent here has not shipped. Items known to be coming are listed under
[Still to come](#still-to-come) so you can plan for them, but do not write code
against them yet.

!!! note "Almost nothing here is a rename"
With two exceptions — the cash-flow method names and the `edgar.effect` /
`edgar.form144` module moves below — 6.0 changes *what values you get back*,
not what anything is called. Every other symbol on this page has the same
import path and signature it had in 5.x. That makes those changes quiet:
your code will not fail to import, and in most cases it will not raise — it
will return something different.

Those two are the opposite kind of change, and deliberately so: both warn in
5.x before they break in 6.0.
!!! note "Two kinds of change"
**Loud ones** rename, move or remove something: the cash-flow method names,
the `edgar.effect` / `edgar.form144`, settings and date-helper moves, the
access modes, and `FilingHomepage(soup=...)`. Each of these warns in 5.x
before it breaks in 6.0, so running your code on the latest 5.x with
warnings visible finds them.

**Quiet ones** keep every import path and signature and change *what values
you get back*. Your code will not fail to import, and in most cases it will
not raise; it will return something different. A few of these warn in 5.x
too (the error changes emit a `FutureWarning`), but most cannot, so read
those sections closely.

---

Expand Down Expand Up @@ -542,8 +544,12 @@ still a 5.x release to fix it in.
| `get_financials()` on a filing with no XBRL | warns, returns a `Financials` whose accessors all answer `None` | raises `XBRLFilingWithNoXbrlData` |

`filing.obj()` on a form edgartools does not model still returns `None`, and
so does `filing.xbrl()` on a filing without XBRL. Those are answers, not
failures, and that distinction is the point of the whole change.
so does `filing.xbrl()` on a filing without XBRL. `filing.html()` also keeps
returning `None` when the filing has no HTML primary document, which is
common: the primary document is a PDF, a text file or XML, or, since 5.59.0,
the index page lists no primary document at all, where it used to raise
`AttributeError`. Those are answers, not failures, and that distinction is
the point of the whole change.

The `get_financials()` row is on the other side of exactly that line, which is
worth spelling out because the two look alike. `filing.xbrl()` is *asking
Expand Down Expand Up @@ -631,6 +637,38 @@ module-level `limits` object is a different name and is unaffected.

---

## `FilingHomepage` takes an lxml tree, not BeautifulSoup

**What changed.** The filing index page is parsed with lxml instead of
BeautifulSoup since 5.53.0. Two call shapes that handed edgartools a soup
object still work in 5.x and emit a `DeprecationWarning`. **6.0 removes both.**

| 5.x call (warns) | 6.0 |
|---|---|
| `FilingHomepage(url, soup=soup)` | the `soup=` keyword is gone; pass the tree as the second argument, `root` |
| a `BeautifulSoup` passed as `root` to `FilingHomepage(...)` or `Attachments.load(...)` | raises; pass an lxml tree |

```python
# Before
soup = BeautifulSoup(html, "lxml")
homepage = FilingHomepage(url, soup=soup)

# Now
from edgar.attachments import parse_homepage_html
homepage = FilingHomepage(url, parse_homepage_html(html))
```

In 5.x a soup is re-parsed with lxml for you, which costs a second parse.
`parse_homepage_html` accepts `str` or `bytes`; prefer bytes, since lxml refuses
a `str` that opens with an encoding declaration, which SEC markup often does.

**You probably do not need to do anything.** `filing.homepage` and
`FilingHomepage.load(url)` build the tree themselves and never warn. This only
affects code that constructs a `FilingHomepage` or calls `Attachments.load`
directly.

---

## Quarter and date helpers moved to `edgar.dates`

**What changed.** `filing_date_to_year_quarters`, `current_year_and_quarter`,
Expand Down Expand Up @@ -672,7 +710,7 @@ against these; each will get a section above when it lands.
| `CurrentReport.doc` (8-K) | Already deprecated in 5.x. It returns the legacy `ChunkedDocument`, unlike `.doc` on every other report class, which returns the `edgar.documents` document — one attribute name, two unrelated types, and only the 8-K one stands on the package being removed. Use `.document` for the parsed document, or `.items` / `report[item]` for item access. In 6.0 `.doc` becomes the modern document on 8-K too, so code that reads `ChunkedDocument`-specific attributes off it needs changing, not just re-pointing. |
| `detect_page_breaks()`, `mark_page_breaks()` | Already deprecated in 5.x, and importable from the top level (`from edgar import detect_page_breaks`), which is why they warn on their own rather than only going out with the package. No replacement — see the row below for why page breaks are not part of the new document model. |
| `include_page_breaks` on `markdown()` | Already deprecated in 5.x: `Filing.markdown()` and `Attachment.markdown()` render through `edgar.documents`, but `include_page_breaks=True` still falls back to the legacy renderer — which drops images. Both it and `start_page_number` go with `edgar.files`. There is no replacement: the new builder treats page-break `<hr>`s and page-number containers as print chrome and discards them. |
| `httpx` → `httpx2` | Under consideration, not committed. It is no longer a breaking change for you either way: `TransportError` now owns the exception types at the network boundary, so the HTTP client underneath is ours to change. |
| `httpx` → `httpx2` | **Not in 6.0** (decided 2026-09-30). It is waiting on an upstream vcrpy fix and may land in a later 6.x. It is no longer a breaking change for you either way: `TransportError` now owns the exception types at the network boundary, so the HTTP client underneath is ours to change. Catch `edgar.exceptions` types, not `httpx` ones, and the swap will not reach your code. |
| Public API **enforcement** | `__all__` is already declared (see below) — 6.0 makes the names outside it private, and some currently-importable names will move. |
| Source tree reorganisation | Module locations change; import paths follow. The first moves have landed and have their own section above — `edgar.effect` and `edgar.form144`. Further moves will each get a section as they ship. |
| `FactQuery.to_dataframe()` sentinels | `preferred_sign` and `fiscal_year` move to nullable `Int64`. |
Expand Down
Loading