Skip to content

Commit

Permalink
Improve the display of TenK data object
Browse files Browse the repository at this point in the history
  • Loading branch information
dgunning committed Nov 12, 2024
1 parent d5efa13 commit 906ed9d
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 3 deletions.
86 changes: 84 additions & 2 deletions edgar/company_reports.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from datetime import datetime
from functools import lru_cache, partial
from typing import Dict, List

from rich.table import Table
from rich import box
from rich import print
from rich.console import Group, Text
from rich.panel import Panel

from rich.tree import Tree
from edgar.core import datefmt
from edgar._filings import Attachments, Attachment
from edgar._markdown import MarkdownContent
from edgar.richtools import repr_rich
Expand All @@ -24,6 +26,7 @@
]



class CompanyReport:

def __init__(self, filing):
Expand Down Expand Up @@ -58,6 +61,10 @@ def cash_flow_statement(self):
def financials(self):
return Financials.extract(self._filing)

@property
def period_of_report(self):
return self._filing.header.period_of_report

@property
@lru_cache(maxsize=1)
def chunked_document(self):
Expand Down Expand Up @@ -231,9 +238,84 @@ def __init__(self, filing):
assert filing.form in ['10-K', '10-K/A'], f"This form should be a 10-K but was {filing.form}"
super().__init__(filing)

@property
def business(self):
return self['Item 1']

@property
def risk_factors(self):
return self['Item 1A']

@property
def management_discussion(self):
return self['Item 7']

@property
def directors_officers_and_governance(self):
return self['Item 10']

def __str__(self):
return f"""TenK('{self.company}')"""

def get_structure(self):
# Create the main tree
tree = Tree("📄 ")

# Get the actual items from the filing
actual_items = self.items

# Create a mapping of uppercase to actual case items
case_mapping = {item.upper(): item for item in actual_items}

# Process each part in the structure
for part, items in self.structure.structure.items():
# Create a branch for each part
part_tree = tree.add(f"[bold blue]{part}[/]")

# Add items under each part
for item_key, item_data in items.items():
# Check if this item exists in the actual filing
if item_key in case_mapping:
# Use the actual case from the filing
actual_item = case_mapping[item_key]
item_text = Text.assemble(
(f"{actual_item:<7} ", "bold green"),
(f"{item_data['Title']}", "bold"),
)
else:
# Item doesn't exist - show in grey with original structure case
item_text = Text.assemble(
(f"{item_key}: ", "dim"),
(f"{item_data['Title']}", "dim"),
)

part_tree.add(item_text)

return tree

def __rich__(self):
title = Text.assemble(
(f"{self.company}", "bold deep_sky_blue1"),
(" ", ""),
(f"{self.form}", "bold"),
)
periods = Text.assemble(
(f"Period ending ", ""),
(f"{datefmt(self.period_of_report, '%B %d, %Y')}", "bold"),
(f" filed on ", ""),
(f"{datefmt(self.filing_date, '%B %d, %Y')}", "bold"),

)
panel = Panel(
Group(
periods,
self.get_structure()
),
title=title,
box=box.ROUNDED,
)
return panel


class TenQ(CompanyReport):
structure = FilingStructure({
Expand Down
14 changes: 14 additions & 0 deletions edgar/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,8 @@ def datefmt(value: Union[datetime.datetime, str], fmt: str = "%Y-%m-%d") -> str:
# If value matches %Y%m%d%H%M%s, then parse it
elif re.match(r"^\d{14}$", value):
value = datetime.datetime.strptime(value, "%Y%m%d%H%M%S")
elif re.match(r"^\d{4}-\d{2}-\d{2}$", value):
value = datetime.datetime.strptime(value, "%Y-%m-%d")
return value.strftime(fmt)
else:
return value.strftime(fmt)
Expand Down Expand Up @@ -770,3 +772,15 @@ def is_start_of_quarter():
return True

return False

def format_date(date: Union[str, datetime.datetime], fmt: str = "%Y-%m-%d") -> str:
"""
Format a date as a string
:param date: The date to format
:param fmt: The format to use
:return: The formatted date
"""
if isinstance(date, str):
return date
else:
return date.strftime(fmt)
20 changes: 19 additions & 1 deletion tests/test_company_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ def test_is_valid_item_for_filing():


def test_chunk_items_for_company_reports():
filing = find("0001193125-23-086073")
filing = Filing(form='10-K', filing_date='2023-03-31', company='7GC & Co. Holdings Inc.',
cik=1826011, accession_no='0001193125-23-086073')
html = filing.html()
chunked_document = ChunkedDocument(html)
print()
Expand Down Expand Up @@ -100,3 +101,20 @@ def test_items_for_10k_filing():
assert tenk['ITEM 15'] == item_15
print(item_15)

def test_tenk_item_structure():
filing = Filing(company='Apple Inc.', cik=320193, form='10-K', filing_date='2024-11-01', accession_no='0000320193-24-000123')
tenk = filing.obj()
tenk_repr = repr(tenk)
print()
print(tenk_repr)
assert "Item 1" in tenk_repr


def test_tenk_section_properties():
filing = Filing(company='Apple Inc.', cik=320193, form='10-K', filing_date='2024-11-01', accession_no='0000320193-24-000123')
tenk:TenK = filing.obj()
assert tenk.management_discussion
assert tenk.business
assert tenk.risk_factors
assert tenk.directors_officers_and_governance

0 comments on commit 906ed9d

Please sign in to comment.