You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
FundReport.options_data() crashed with TypeError: bad operand type for abs(): 'NoneType' on N-PORT filings whose nested forwards had null USD amounts — edgar/funds/reports.py:1011-1012 cast fwd.amount_sold / fwd.amount_purchased through abs() when the corresponding currency_* field equalled 'USD', but valid N-PORT XBRL can pair a stated USD currency with a null amount — every option-on-forward in such a filing tripped the crash before any data was returned. The documented public API was effectively unusable for any fund whose options referenced such a forward (reproducer: GOF NPORT-P). Both assignments now guard on amount_* is not None; the exchange-rate calculation just below was already safe via Python's short-circuiting. Defensive grep across the file confirmed lines 1011-1012 were the only unguarded abs() calls. (#811, reporter @HristoRaykov)
viewer.concept_rows[i].numeric_value silently returned a prior-year value when the primary reporting period had no fact for the row — ConceptRow.numeric_value (and the sibling Concept.value accessor on the concept graph) returned parse_numeric(next(iter(self.values.values()))) — the first entry of the values dict, which was populated only for periods that had a non-empty cell. When the primary (leftmost) reporting period had no value, the singular accessor silently returned whichever period happened to be first in the dict, masking missing-period as a prior-year value. Most visible on the ABT 2019 10-K income statement: concept_rows[16] (us-gaap_IncomeLossFromDiscontinuedOperationsNetOfTax) returned 34.0 (the 2018 value) because ABT had no 2019 discontinued-ops fact. Tracks primary_period on ConceptRow (populated by the R*.htm parser from period_headers[0]) and resolves numeric_value against it explicitly, returning None when the primary period has no value. Concept.value in concept_graph.py got the same fix — same antipattern, same underlying row data, user-visible via the concept graph's Rich/text rendering. (#810, reporter @mpreiss9)
FundFeeNotice crashed with AttributeError: 'list' object has no attribute 'get' on per-class 24F-2NT filings — xmltodict-style parsing returns repeated annualFilingInfo blocks as a list, but every typed accessor (fund_name, series, aggregate_sales, etc.) called .get() on the result. ~2% of recent 24F-2NT filings — including all five BNY Mellon family filings — file one block per share class, so the first call into the data object raised before any data was returned. The data model now iterates every annualFilingInfo block: typed financial properties (aggregate_sales, net_sales, redemptions_current_year, registration_fee, total_due, …) sum across blocks; metadata properties (fund_name, fiscal_year_end, investment_company_act_file_number) read from block[0] (identical across blocks); series deduplicates by seriesId. A new FundClassFee dataclass + is_per_class flag + class_fees list expose the per-share-class breakdown. The _parse_float helper now also handles accounting-parens notation (NNN) → -NNN, which appears in redemptionCreditsAvailableForUseInFutureYears. Backwards-compatible: every existing property keeps the same return shape; the fund total invariant aggregate_sales == sum(cf.aggregate_sales for cf in class_fees) is verified against BNY Mellon Research Growth Fund. (edgartools-8ohs)
viewer.concept_report.currency_scaling returned wrong scales for filers using non-Apple header formats — ConceptReport.currency_scaling was derived from a narrow text match on the R*.htm <th class='tl'> header ($ in millions / $in millions). Filers using In Millions, (in millions), USD ($) in Millions, or Dollars in Millions silently fell through to the default of 1, producing scaling that disagreed across statements within a single filing (ALGN balance sheet vs income statement) and wrong values for whole multi-year ranges (ABNB showing 1 for 2023/2024 when the actual scale is millions). ViewerReport.currency_scaling now derives the scale from the XBRL decimals attribute on monetary facts mapped to the report's role in the presentation linkbase — filer-mandated and uniform (-6 → millions, -3 → thousands, 0 → units). The text-match value is retained as a fallback when XBRL is unavailable. The resolved scale is mirrored back onto ConceptReport.currency_scaling so existing code reading it via the concept-report path also benefits. Same precedent as GH #799 (level enrichment from XBRL). (#807, reporter @mpreiss9)