Skip to main content

Simple. Streaming. Resilient. MFA-ready. Fetch files from SharePoint via Microsoft Graph.

Project description

๐Ÿš€ spfetch

spfetch_lg

Simple. Streaming. Resilient. MFA-ready.
List and fetch files from SharePoint via Microsoft Graph with clean APIs and cloud-native downloads.


โœจ What is spfetch?

spfetch is an asynchronous Python library built for modern data pipelines:

  • ๐Ÿ“‚ List SharePoint folders with structured metadata
  • โฌ‡๏ธ Stream large files directly to Local Disk, S3, GCS, or Azure without memory crashes
  • โšก Smart Buffering โ€“ Control chunk and buffer sizes to optimize Cloud I/O (50+ MB/s)
  • ๐Ÿ“Š Load small files directly into Pandas DataFrames
  • ๐Ÿ” Authenticate via MFA (Device Code) or Silent (Client Secret) flows
  • ๐Ÿ›ก๏ธ Auto-Recover from Microsoft API Throttling (HTTP 429) with Exponential Backoff

๐Ÿš€ Performance Benchmark (v0.1.3)

Zero Intermediate Disk Architecture + Smart Buffering

Benchmark Results

  • Payload: 10.10 GB CSV (SharePoint โžก Azure Data Lake)
  • Time: 3m 11s (191.96s)
  • Average Speed: 53.87 MB/s
  • Config: chunk_size_mb=1 | buffer_size_mb=100

๐Ÿ—๏ธ Technical Architecture

The library is designed with a layered approach to ensure high throughput and resilience. By decoupling the reading rate from the writing rate, we maximize the performance of both the Microsoft Graph API and Cloud Providers.

diagram-spfetch

The Data Pipeline Flow:

  1. Source (SharePoint): Chunks are read at a light rate (default 1MB) to avoid API throttling.
  2. Core (Smart Buffer & Router): Data is accumulated in a memory buffer. The Smart Router dynamically distributes multiple files across isolated Async Workers.
  3. Destination (Cloud): Once the buffer reaches the set size (e.g., 100MB), a single high-speed write is performed via fsspec.
  4. Resilience: The @retry_on_429 shield monitors all requests, while internal loop-retries protect individual files from network drops.

๐Ÿ” 1. Authentication

Instantiate the client using your Microsoft Entra ID (Azure AD) credentials.


Option A: Interactive / Local (Device Code Flow)

Ideal for local scripts. Supports MFA.

from spfetch.auth import DeviceCodeAuth
from spfetch.client import SharePointClient

auth = DeviceCodeAuth(
    tenant_id="<YOUR_TENANT_ID>",
    client_id="<YOUR_CLIENT_ID>"
)

client = SharePointClient(auth=auth)

Option B: Automated / CI/CD (Client Secret Flow)

Ideal for Airflow, Databricks, GitHub Actions.

from spfetch.auth import ClientSecretAuth
from spfetch.client import SharePointClient

auth = ClientSecretAuth(
    tenant_id="<YOUR_TENANT_ID>",
    client_id="<YOUR_CLIENT_ID>",
    client_secret="<YOUR_CLIENT_SECRET>"
)

client = SharePointClient(auth=auth)

๐Ÿ“Š 2. Telemetry & Dual Progress Bar

By default, spfetch does not override your logging configuration (uses NullHandler).

To enable structured logs and dual progress bars:

import asyncio
from spfetch.auth import ClientSecretAuth
from spfetch.client import SharePointClient
from spfetch.destinations import LocalDestination
from spfetch import enable_console_logs # <-- Add this line

enable_console_logs() # <-- Add this line

async def main():
    auth = ClientSecretAuth(
        tenant_id="YOUR_TENANT_ID",
        client_id="YOUR_CLIENT_ID",
        client_secret="YOUR_CLIENT_SECRET"
    )

    client = SharePointClient(auth=auth)
    destination = LocalDestination()

    await client.download(
        hostname="your_company.sharepoint.com",
        site_path="/sites/YourSite",
        file_path="/Folder/your_file.csv",
        dest_path="./data/your_file.csv",
        destination=destination
    )

if __name__ == "__main__":
    asyncio.run(main())

๐Ÿ–ฅ๏ธ Expected Terminal Output

๐Ÿš€ Iniciando Ingestรฃo | Starting Ingestion (Number of files: 3 | concurrency: 3)

โœ… INGESTION COMPLETED SUCCESSFULLY
๐Ÿ“‚ Source | Fonte: Data/file1.csv (1.00 GB)
๐Ÿ“ Destination | Destino: AzureDestination -> abfs://landing/file1.csv (Chunk: 2MB | Buffer: 50MB)

โŒ› Total Time | Tempo total: 40.07s
๐Ÿš€ Started at | Comeรงou em: 2026-03-01 01:41:18
๐Ÿ Finished at | Terminou em: 2026-03-01 01:41:58
โšก Average Speed | Velocidade mรฉdia: 25.20 MB/s

๐Ÿ“ฅ Reading | Leitura: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1024.0M/1024.0M [00:40<00:00, 25.2MB/s]
๐Ÿ“ค Saving  | Salvando: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1024.0M/1024.0M [00:40<00:00, 25.2MB/s]
-------------------------------------------------------

๐Ÿ“– 3. Exploration โ€“ Listing Folders

๐Ÿ“ฆ Installation:

pip install spfetch
import asyncio

async def list_files():
    items = await client.ls(
        hostname="<tenant>.sharepoint.com",
        site_path="/sites/<YourSite>",
        folder_path="/Shared Documents/General"
    )

    for item in items:
        print(item["name"], item["size"], item["is_folder"])

asyncio.run(list_files())

๐Ÿš€ 4. Concurrent Batch Downloads & Smart UI

spfetch allows you to download multiple files in parallel using the max_concurrency parameter. You can pass the files as a Python List or as a pipe-separated string |.

The library uses an advanced tqdm slot-manager to display concurrent progress bars without polluting your terminal. Once a file finishes, the animation disappears and leaves a clean, static audit log behind.

import asyncio
from spfetch.auth import ClientSecretAuth
from spfetch.client import SharePointClient
from spfetch.destinations import AzureDestination

async def main():
    auth = ClientSecretAuth(tenant_id="...", client_id="...", client_secret="...")
    client = SharePointClient(auth=auth)
    azure_dest = AzureDestination(account_name="...", account_key="...")

    # Pass multiple files separated by pipe "|"
    arquivos_origem = "Data/file1.csv | Data/file2.csv | Data/file3.csv"
    arquivos_destino = "abfs://landing/file1.csv | abfs://landing/file2.csv | abfs://landing/file3.csv"

    await client.download(
        hostname="your_company.sharepoint.com",
        site_path="/sites/YourSite",
        file_path=arquivos_origem,
        dest_path=arquivos_destino,
        destination=azure_dest,
        chunk_size_mb=2,
        buffer_size_mb=50,
        max_concurrency=3 # <-- ๐Ÿš€ 3 files will be downloaded simultaneously!
    )

if __name__ == "__main__":
    asyncio.run(main())

๐ŸŒŠ 5. Ingestion Workflows


โ˜๏ธ A) Azure (ADLS / Blob)

๐Ÿ“ฆ Installation:

pip install "spfetch[azure]"
from spfetch.destinations import AzureDestination
import asyncio

async def download_to_azure():
    destination = AzureDestination(
        account_name="<YOUR_STORAGE_ACCOUNT_NAME>",
        account_key="<YOUR_STORAGE_ACCOUNT_KEY>"
    )

    await client.download(
        hostname="<tenant>.sharepoint.com",
        site_path="/sites/<YourSite>",
        file_path="/Shared Documents/Data/file.parquet",
        dest_path="abfs://<container>/bronze/file.parquet",
        destination=destination,
        chunk_size_mb=1,
        buffer_size_mb=100
    )

asyncio.run(download_to_azure())

โ˜๏ธ B) Amazon S3

๐Ÿ“ฆ Installation:

pip install "spfetch[s3]"
from spfetch.destinations import S3Destination
import asyncio

async def download_to_s3():
    destination = S3Destination(
        key="<AWS_ACCESS_KEY_ID>",
        secret="<AWS_SECRET_ACCESS_KEY>"
    )

    await client.download(
        hostname="<tenant>.sharepoint.com",
        site_path="/sites/<YourSite>",
        file_path="/Shared Documents/Data/file.csv",
        dest_path="s3://<bucket>/raw/file.csv",
        destination=destination,
        chunk_size_mb=1,
        buffer_size_mb=16
    )

asyncio.run(download_to_s3())

โ˜๏ธ C) Google Cloud Storage (GCS)

๐Ÿ“ฆ Installation:

pip install "spfetch[gcs]"
from spfetch.destinations import GCSDestination
import asyncio

async def download_to_gcs():
    destination = GCSDestination(
        project="<my-gcp-project-id>",
        token="google_default"
    )

    await client.download(
        hostname="<tenant>.sharepoint.com",
        site_path="/sites/<YourSite>",
        file_path="/Shared Documents/Data/file.csv",
        dest_path="gs://<bucket>/raw/file.csv",
        destination=destination
    )

asyncio.run(download_to_gcs())

๐Ÿ’ป D) Local Disk

๐Ÿ“ฆ Installation:

pip install spfetch
from spfetch.destinations import LocalDestination
import asyncio

async def download_local():
    destination = LocalDestination()

    await client.download(
        hostname="<tenant>.sharepoint.com",
        site_path="/sites/<YourSite>",
        file_path="/Shared Documents/Data/file.csv",
        dest_path="./local_downloads/file.csv",
        destination=destination
    )

asyncio.run(download_local())

๐Ÿ“Š E) Read Directly to Pandas

๐Ÿ“ฆ Installation:

pip install "spfetch[pandas]"
import asyncio

async def read_to_memory():
    df = await client.read_df(
        hostname="<tenant>.sharepoint.com",
        site_path="/sites/<YourSite>",
        file_path="/Shared Documents/Reports/data.xlsx",
        sheet_name="Sheet1",
        skiprows=2,
        usecols="A:D"
    )

    print(df.head())

asyncio.run(read_to_memory())

๐Ÿ›ก๏ธ 6. Resilience โ€“ Handling Failures

spfetch automatically protects your pipeline at two levels:

  1. Microsoft Graph API Throttling (HTTP 429): If HTTP 429 Too Many Requests occurs, the execution pauses, reads the Retry-After header, applies Exponential Backoff, and retries up to 5 times.

  2. Network Drops during Concurrent Downloads: If a file connection drops midway through downloading a batch, its specific worker catches the error, waits 3 seconds, and restarts only that file (up to 3 attempts), while other files continue streaming at max speed.

Your pipeline will wait and recover gracefully instead of crashing.


๐Ÿค Contributing

Pull Requests are welcome.

Before submitting:

make format
make lint
make test

Ensure all tests pass.


๐Ÿ“„ License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spfetch-0.2.0.tar.gz (19.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spfetch-0.2.0-py3-none-any.whl (16.1 kB view details)

Uploaded Python 3

File details

Details for the file spfetch-0.2.0.tar.gz.

File metadata

  • Download URL: spfetch-0.2.0.tar.gz
  • Upload date:
  • Size: 19.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for spfetch-0.2.0.tar.gz
Algorithm Hash digest
SHA256 59aa3672dcc17d0d89d778b952cef4fc588365045ac618ace351e145e10e6de8
MD5 2f624b30dad0e164d0c94a33cfa38082
BLAKE2b-256 294b6f3c6247693edc9400ee988e6cd4c92f112b20d5bd36a96471634e215c92

See more details on using hashes here.

File details

Details for the file spfetch-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: spfetch-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 16.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for spfetch-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fdbb3a4c98c025e59d7e3081425ad5a6f0e9430b76e2558bd59c36294f30a5fc
MD5 d5617c9548661dd142a7c4f0fe6c3504
BLAKE2b-256 f1225b6a02fcfd806dafdc1b6c4da61d9a8a12444d853dec9067420dcd88dd3e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page