Skip to content

Commit 701c32e

Browse files
committed
move to v3 downloader
1 parent 4008773 commit 701c32e

8 files changed

Lines changed: 775 additions & 251 deletions

File tree

datamule/datamule/datamule/archive_lookup.py

Lines changed: 417 additions & 0 deletions
Large diffs are not rendered by default.

datamule/datamule/datamule/downloader.py

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
from os import cpu_count
1818
from secsgml2 import parse_sgml_content_into_memory
1919
from ..utils.format_accession import format_accession
20-
from ..providers.providers import SEC_FILINGS_SGML_BUCKET_ENDPOINT
21-
from .datamule_lookup import datamule_lookup
20+
from ..providers.providers import SEC_FILINGS_ARCHIVE_SGML_ENDPOINT
21+
from .archive_lookup import lookup_archive_sgml
2222

2323
# Set up logging
2424
logging.basicConfig(
@@ -31,7 +31,7 @@
3131

3232
class Downloader:
3333
def __init__(self, api_key=None):
34-
self.BASE_URL = SEC_FILINGS_SGML_BUCKET_ENDPOINT
34+
self.BASE_URL = SEC_FILINGS_ARCHIVE_SGML_ENDPOINT
3535
self.CHUNK_SIZE = 2 * 1024 * 1024
3636
self.MAX_CONCURRENT_DOWNLOADS = 10
3737
self.MAX_DECOMPRESSION_WORKERS = cpu_count()
@@ -222,7 +222,8 @@ async def download_and_process(self, session, url, semaphore, decompression_pool
222222
chunks.append(chunk)
223223

224224
loop = asyncio.get_running_loop()
225-
if content_type == 'application/zstd':
225+
is_zstd = filename.endswith('.zst') or 'zstd' in content_type
226+
if is_zstd:
226227
logger.debug(f"Processing {filename} as compressed (zstd)")
227228
success = await loop.run_in_executor(
228229
decompression_pool,
@@ -286,20 +287,36 @@ async def process_batch(self, urls, output_dir, keep_document_types=[], max_batc
286287
finally:
287288
tar_manager.close_all()
288289

289-
def download(self, accession_numbers, output_dir="downloads", keep_document_types=[],
290-
max_batch_size=1024*1024*1024):
290+
def _url_from_archive_record(self, record):
291+
filing_date = record.get('filing_date') or record.get('filingDate')
292+
accession = record.get('accession')
293+
if filing_date is None or accession is None:
294+
raise ValueError("Archive lookup record must include filing_date and accession")
295+
296+
accession = format_accession(accession, 'no-dash')
297+
return f"{self.BASE_URL}{filing_date}/{accession}.sgml.zst"
298+
299+
def download(self, accession_numbers=None, output_dir="downloads", keep_document_types=[],
300+
max_batch_size=1024*1024*1024, archive_records=None):
291301
if self.api_key is None:
292302
raise ValueError("No API key found. Please set DATAMULE_API_KEY environment variable or provide api_key in constructor")
293303

294-
logger.debug(f"Generating URLs for {len(accession_numbers)} filings...")
304+
if archive_records is None:
305+
if not accession_numbers:
306+
logger.warning("No submissions found matching the criteria")
307+
return
308+
archive_records = lookup_archive_sgml(
309+
accession=accession_numbers,
310+
api_key=self.api_key,
311+
quiet=True,
312+
)
313+
314+
logger.debug(f"Generating URLs for {len(archive_records)} filings...")
295315

296-
urls = []
297-
for accession in accession_numbers:
298-
url = f"{self.BASE_URL}{format_accession(accession,'no-dash')}.sgml"
299-
urls.append(url)
316+
urls = [self._url_from_archive_record(record) for record in archive_records]
300317

301318
# Deduplicate URLs
302-
urls = list(set(urls))
319+
urls = list(dict.fromkeys(urls))
303320

304321
if not urls:
305322
logger.warning("No submissions found matching the criteria")
@@ -331,15 +348,24 @@ def download(cik=None, ticker=None, submission_type=None, filing_date=None,
331348
"""
332349
Download SEC filings from DataMule.
333350
334-
If accession_numbers is provided, downloads those directly.
335-
Otherwise, queries datamule_lookup with the provided filters to get accession numbers.
351+
If accession_numbers is provided, resolves those archive records directly.
352+
Otherwise, queries the v3 archive lookup with the provided filters.
336353
"""
337354

338355
downloader = Downloader(api_key=api_key)
339356

340-
# Get accession numbers if not provided
341-
if accession_numbers is None:
342-
accession_numbers = datamule_lookup(
357+
# Get archive coordinates if not provided
358+
if accession_numbers is not None:
359+
if not accession_numbers:
360+
logger.warning("No submissions found matching the criteria")
361+
return
362+
archive_records = lookup_archive_sgml(
363+
accession=accession_numbers,
364+
quiet=quiet,
365+
api_key=api_key,
366+
)
367+
else:
368+
archive_records = lookup_archive_sgml(
343369
cik=cik,
344370
ticker=ticker,
345371
submission_type=submission_type,
@@ -354,18 +380,17 @@ def download(cik=None, ticker=None, submission_type=None, filing_date=None,
354380
skip_accession_numbers=skip_accession_numbers,
355381
quiet=quiet,
356382
api_key=api_key,
357-
provider='datamule-sgml',
358383
**kwargs
359384
)
360385

361386

362-
if not accession_numbers:
363-
logger.warning("No submissions found matching the criteria")
364-
return
387+
if not archive_records:
388+
logger.warning("No submissions found matching the criteria")
389+
return
365390

366391
# Download the filings
367392
downloader.download(
368-
accession_numbers=accession_numbers,
393+
archive_records=archive_records,
369394
output_dir=output_dir,
370395
keep_document_types=keep_document_types,
371396
max_batch_size=max_batch_size

0 commit comments

Comments
 (0)