Skip to content

Commit f31b84c

Browse files
committed
feat: Improve logging and error handling in async session and parser; add unit tests for logging output
1 parent fb802ac commit f31b84c

5 files changed

Lines changed: 164 additions & 195 deletions

File tree

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121
- **edgar/datasets.py**: Added `logger` — logs `info` on bulk download start, `debug` on per-file extraction with row counts.
2222
- **edgar/search.py**: Added `logger` — logs `debug` with EFTS search params before request.
2323
- **edgar/company.py**: Added `logger` — logs `debug` on identifier resolution path (CIK vs ticker).
24+
- **edgar/async_session.py**: Added `logger.error()` before each `raise EdgarRequestError`, matching `session.py` pattern for consistent error observability.
25+
26+
### Added
27+
28+
- **tests/test_logging.py**: 7 unit tests for logging output (cache hit/miss/set/invalidate, session error, rate-limit sleep, async session error).
29+
30+
### Fixed
31+
32+
- **edgar/parser.py**: Changed `except KeyError` to `except IndexError` in ticker symbol extraction — `values[2]` is a list index, not a dict key.
33+
34+
### Removed
35+
36+
- **edgar/utilis.py**: Deleted dead duplicate of `utils.py` (nothing imported it).
37+
- **edgar/parser.py**: Removed 3 commented-out `print()` debug lines.
2438

2539
## [0.2.0] - 2026-04-19
2640

edgar/async_session.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ async def make_request( # pylint: disable=too-many-positional-arguments
161161
json=json_payload,
162162
)
163163
except httpx.HTTPError as exc:
164+
logger.error("Request failed: %s", exc)
164165
raise EdgarRequestError(f"Request to {url} failed: {exc}") from exc
165166

166167
retries = 0
@@ -186,6 +187,7 @@ async def make_request( # pylint: disable=too-many-positional-arguments
186187
)
187188
except httpx.HTTPError as exc:
188189
if retries >= MAX_RETRIES:
190+
logger.error("Retry %s failed: %s", retries, exc)
189191
raise EdgarRequestError(
190192
f"Request to {url} failed after {MAX_RETRIES} retries: {exc}"
191193
) from exc
@@ -223,6 +225,7 @@ async def fetch_page(self, url: str) -> bytes | None:
223225
try:
224226
response = await self.http_client.get(url)
225227
except httpx.HTTPError as exc:
228+
logger.error("Failed to fetch page %s: %s", url, exc)
226229
raise EdgarRequestError(f"Failed to fetch page {url}: {exc}") from exc
227230

228231
if response.status_code == 200:
@@ -251,6 +254,7 @@ async def download(self, url: str, path: str | None = None) -> str | bytes:
251254
try:
252255
response = await self.http_client.get(url)
253256
except httpx.HTTPError as exc:
257+
logger.error("Failed to download %s: %s", url, exc)
254258
raise EdgarRequestError(f"Failed to download {url}: {exc}") from exc
255259

256260
if response.status_code != 200:

edgar/parser.py

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,6 @@ def parse_transaction_report(self, table: Tag) -> list[dict]:
337337
values.insert(5, href)
338338

339339
master_list.append(dict(zip(headers, values)))
340-
# print([header.strip() for header in row.strings if header != '\n'])
341340

342341
return master_list
343342

@@ -499,7 +498,8 @@ def _parse_variable_product_page(self, product_page_soup: Tag) -> list[dict]:
499498
# Set the Ticker symbol.
500499
try:
501500
row_dict["ticker_symbol"] = values[2]
502-
except KeyError:
501+
except IndexError:
502+
logger.debug("No ticker symbol at index 2 for %s", product_id)
503503
row_dict["ticker_symbol"] = "null"
504504

505505
for link in row_links:
@@ -596,57 +596,6 @@ def parse_loc_elements(self, response_text: str) -> list[dict]:
596596
entries.append(location_dict)
597597

598598
return entries
599-
600-
# def parse_series_filings(self, response_text: str) -> List[dict]:
601-
602-
# root = ET.fromstring(response_text)
603-
604-
# for elem in root.iterfind(
605-
# '.atom:entry/atom:content/atom:company-info/atom:sids/atom:sid',
606-
# namespaces=self.entries_namespace
607-
# ):
608-
# print(elem)
609-
610-
# soup = BeautifulSoup(response_text, 'html.parser')
611-
612-
# sid_data = []
613-
614-
# for sid in soup.find_all(name='sid'):
615-
616-
# sid: Tag = sid
617-
# element_dict = {}
618-
619-
# print(len(list(sid.children)))
620-
621-
# for element in sid.children:
622-
623-
# if not isinstance(element, NavigableString) and element.name != 'cids':
624-
# element_dict[
625-
# element.name.replace('-', '_')
626-
# ] = element.text.strip()
627-
628-
# elif not isinstance(element, NavigableString) and element.name == 'cids':
629-
# element_dict['cids'] = []
630-
631-
# for cid in element.find_all('cid'):
632-
# cid_dict = {}
633-
# cid_dict['cid_id'] = cid['id']
634-
635-
# for cid_element in cid.find_all():
636-
# cid_dict[
637-
# cid_element.name.replace('-', '_').strip()
638-
# ] = cid_element.text.strip()
639-
640-
# element_dict['cids'].append(
641-
# cid_dict
642-
# )
643-
644-
# sid_data.append(
645-
# element_dict
646-
# )
647-
648-
# return sid_data
649-
650599
def parse_series_table(self, response_text: str) -> list[dict]:
651600
"""Parses the series table returned from a Series query.
652601

edgar/utilis.py

Lines changed: 0 additions & 142 deletions
This file was deleted.

0 commit comments

Comments
 (0)