Simple. Streaming. Resilient. MFA-ready. Fetch files from SharePoint via Microsoft Graph.
Project description
๐ spfetch
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.
The Data Pipeline Flow:
- Source (SharePoint): Chunks are read at a light rate (default 1MB) to avoid API throttling.
- Core (Smart Buffer & Router): Data is accumulated in a memory buffer. The Smart Router dynamically distributes multiple files across isolated Async Workers.
- Destination (Cloud): Once the buffer reaches the set size (e.g., 100MB), a single high-speed write is performed via
fsspec. - Resilience: The
@retry_on_429shield 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:
-
Microsoft Graph API Throttling (HTTP 429): If
HTTP 429 Too Many Requestsoccurs, the execution pauses, reads theRetry-Afterheader, applies Exponential Backoff, and retries up to 5 times. -
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59aa3672dcc17d0d89d778b952cef4fc588365045ac618ace351e145e10e6de8
|
|
| MD5 |
2f624b30dad0e164d0c94a33cfa38082
|
|
| BLAKE2b-256 |
294b6f3c6247693edc9400ee988e6cd4c92f112b20d5bd36a96471634e215c92
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fdbb3a4c98c025e59d7e3081425ad5a6f0e9430b76e2558bd59c36294f30a5fc
|
|
| MD5 |
d5617c9548661dd142a7c4f0fe6c3504
|
|
| BLAKE2b-256 |
f1225b6a02fcfd806dafdc1b6c4da61d9a8a12444d853dec9067420dcd88dd3e
|