โ Easy SharePoint file operations using Microsoft Graph API. ๐ค๐ผ
- Download & Upload - Single files or entire folders
- File Management - Create folders, move, copy, delete
- Batch Operations - Process multiple files efficiently
- Async Support - Full async/await API for parallel operations
- Progress Callbacks - Track progress of transfers
- CLI Tool - Command-line interface for quick operations
- Retry & Resilience - Automatic retry with exponential backoff
- Version History - List and download file versions
- Sharing - Create share links with permissions
- Calendar - Access Outlook/Exchange calendars and events via Microsoft Graph
pip install sharepointeasyWith progress bar support (rich):
pip install sharepointeasy[rich]Set environment variables:
export MICROSOFT_CLIENT_ID="your-client-id"
export MICROSOFT_CLIENT_SECRET="your-client-secret"
export MICROSOFT_TENANT_ID="your-tenant-id"from sharepointeasy import SharePointClient
client = SharePointClient()
client.download_file(
hostname="contoso.sharepoint.com",
site_path="sites/MySite",
file_path="Documents/report.xlsx",
destination="./report.xlsx",
)client.upload_file(
hostname="contoso.sharepoint.com",
site_path="sites/MySite",
file_path="Documents/new-report.xlsx",
source="./local-report.xlsx",
)After installation, use the sharepointeasy command:
# List sites
sharepointeasy list-sites
# List files
sharepointeasy -H contoso.sharepoint.com -S sites/MySite list Documents/
# Download file
sharepointeasy -H contoso.sharepoint.com -S sites/MySite download Documents/report.xlsx
# Upload file
sharepointeasy -H contoso.sharepoint.com -S sites/MySite upload ./report.xlsx -d Documents/
# Download entire folder
sharepointeasy -H contoso.sharepoint.com -S sites/MySite download-folder Documents/Reports
# Create folder
sharepointeasy -H contoso.sharepoint.com -S sites/MySite mkdir Documents/NewFolder -p
# Delete file
sharepointeasy -H contoso.sharepoint.com -S sites/MySite delete Documents/old-file.xlsx
# Create share link
sharepointeasy -H contoso.sharepoint.com -S sites/MySite share Documents/report.xlsx --type viewFor parallel operations, use the async client:
import asyncio
from sharepointeasy import AsyncSharePointClient
async def main():
async with AsyncSharePointClient() as client:
# Download multiple files in parallel
site = await client.get_site("contoso.sharepoint.com", "sites/MySite")
drive = await client.get_drive(site["id"])
# Download entire folder (parallel)
await client.download_batch(
site["id"],
drive["id"],
"Documents/Reports",
"./local-reports",
max_concurrent=10,
)
asyncio.run(main())SharePointClient(
client_id: str | None = None,
client_secret: str | None = None,
tenant_id: str | None = None,
max_retries: int = 3,
retry_delay: float = 1.0,
)| Method | Description |
|---|---|
list_sites() |
List all available SharePoint sites |
get_site(hostname, site_path) |
Get a site by hostname and path |
get_site_by_name(site_name) |
Search for a site by name |
| Method | Description |
|---|---|
list_drives(site_id) |
List drives (document libraries) in a site |
get_drive(site_id, drive_name) |
Get a drive by name |
| Method | Description |
|---|---|
list_files(site_id, drive_id, folder_path) |
List files in a folder |
list_files_recursive(site_id, drive_id, folder_path) |
List all files recursively |
search_file(site_id, drive_id, filename) |
Search for a file by name |
get_file_metadata(site_id, drive_id, file_path) |
Get file metadata |
| Method | Description |
|---|---|
download(site_id, drive_id, file_path, destination) |
Download a file |
download_batch(site_id, drive_id, folder_path, destination_dir) |
Download folder recursively |
download_file(hostname, site_path, file_path, destination) |
Download file (simplified) |
| Method | Description |
|---|---|
upload(site_id, drive_id, file_path, source) |
Upload a file (auto chunked for large files) |
upload_batch(site_id, drive_id, source_dir, destination_folder) |
Upload folder recursively |
upload_file(hostname, site_path, file_path, source) |
Upload file (simplified) |
| Method | Description |
|---|---|
create_folder(site_id, drive_id, folder_path) |
Create a folder |
create_folder_recursive(site_id, drive_id, folder_path) |
Create folder with parents |
delete(site_id, drive_id, file_path) |
Delete a file or folder |
move(site_id, drive_id, source_path, destination_folder) |
Move a file or folder |
copy(site_id, drive_id, source_path, destination_folder) |
Copy a file or folder |
| Method | Description |
|---|---|
list_versions(site_id, drive_id, file_path) |
List file versions |
download_version(site_id, drive_id, file_path, version_id, destination) |
Download specific version |
| Method | Description |
|---|---|
create_share_link(site_id, drive_id, file_path, link_type, scope) |
Create share link |
list_permissions(site_id, drive_id, file_path) |
List file permissions |
| Method | Description |
|---|---|
list_lists(site_id) |
List all lists in a site |
get_list(site_id, list_name) |
Get a list by name or ID |
get_list_columns(site_id, list_id) |
Get list columns/fields |
list_items(site_id, list_id, ...) |
List items with filtering |
list_all_items(site_id, list_id, ...) |
List all items (auto-pagination) |
get_item(site_id, list_id, item_id) |
Get a specific item |
create_item(site_id, list_id, fields) |
Create a new item |
update_item(site_id, list_id, item_id, fields) |
Update an item |
delete_item(site_id, list_id, item_id) |
Delete an item |
create_list(site_id, display_name, columns) |
Create a new list |
delete_list(site_id, list_id) |
Delete a list |
batch_create_items(site_id, list_id, items) |
Create multiple items |
batch_update_items(site_id, list_id, updates) |
Update multiple items |
batch_delete_items(site_id, list_id, item_ids) |
Delete multiple items |
| Method | Description |
|---|---|
search(query, entity_types, site_id, size) |
Global search in SharePoint |
search_files(query, file_extension, site_id, size) |
Search files only |
| Method | Description |
|---|---|
get_item_by_id(drive_id, item_id) |
Get item metadata by ID |
download_by_id(drive_id, item_id, destination) |
Download file by ID |
upload_by_id(drive_id, parent_id, filename, source) |
Upload file to folder by ID |
delete_by_id(drive_id, item_id) |
Delete item by ID |
| Method | Description |
|---|---|
list_user_calendars(user_id) |
List calendars for a user |
list_user_events(user_id, ...) |
List events with filters (date range, subject, attendee) |
list_all_user_events(user_id, ...) |
List all events with auto-pagination |
get_user_event(user_id, event_id) |
Get a specific event by ID |
search_meetings_with_attendee(user_id, attendee_email, ...) |
Search meetings by attendee |
| Method | Description |
|---|---|
list_teams() |
List all teams |
get_team(team_id) |
Get team info |
list_team_channels(team_id) |
List team channels |
get_team_drive(team_id) |
Get team's drive |
list_team_files(team_id, folder_path) |
List files in team |
list_channel_files(team_id, channel_id) |
List files in channel |
download_team_file(team_id, file_path, destination) |
Download from team |
upload_team_file(team_id, file_path, source) |
Upload to team |
| Exception | Description |
|---|---|
SharePointError |
Base exception |
AuthenticationError |
Authentication failed |
SiteNotFoundError |
Site not found |
DriveNotFoundError |
Drive not found |
FileNotFoundError |
File not found |
DownloadError |
Download failed |
UploadError |
Upload failed |
DeleteError |
Delete failed |
FolderCreateError |
Folder creation failed |
MoveError |
Move/copy failed |
ShareError |
Share link creation failed |
ListError |
List operations failed |
CalendarError |
Calendar operations failed |
EventNotFoundError |
Event not found |
from sharepointeasy import SharePointClient, create_progress_callback
client = SharePointClient()
progress = create_progress_callback("Downloading")
client.download_file(
hostname="contoso.sharepoint.com",
site_path="sites/MySite",
file_path="Documents/large-file.zip",
destination="./large-file.zip",
progress_callback=progress,
)from sharepointeasy import SharePointClient, RICH_AVAILABLE
if RICH_AVAILABLE:
from sharepointeasy.utils import create_rich_progress, RichProgressCallback
client = SharePointClient()
with create_rich_progress() as progress:
task = progress.add_task("Downloading...", total=100)
# Your download with callback...To use this library, you need to register an app in Azure AD:
- Go to Azure Portal โ Azure Active Directory โ App registrations
- Click "New registration"
- Name your app and click "Register"
- Go to "Certificates & secrets" โ "New client secret"
- Copy the secret value (this is your
MICROSOFT_CLIENT_SECRET) - Go to "API permissions" โ "Add a permission" โ "Microsoft Graph"
- Add these Application permissions:
Sites.Read.All- Read sitesSites.ReadWrite.All- Read and write sites (for upload, delete, etc.)Files.Read.All- Read filesFiles.ReadWrite.All- Read and write filesCalendars.Read- Read calendars and events (for calendar features)
- Click "Grant admin consent"
Your credentials:
MICROSOFT_CLIENT_ID= "Application (client) ID" on the app overview pageMICROSOFT_TENANT_ID= "Directory (tenant) ID" on the app overview pageMICROSOFT_CLIENT_SECRET= The secret value you copied
from sharepointeasy import SharePointClient
client = SharePointClient()
sites = client.list_sites()
for site in sites:
print(f"{site['displayName']}: {site['webUrl']}")from sharepointeasy import (
SharePointClient,
FileNotFoundError,
AuthenticationError,
)
client = SharePointClient()
try:
client.download_file(
hostname="contoso.sharepoint.com",
site_path="sites/MySite",
file_path="Documents/report.xlsx",
destination="./report.xlsx",
)
print("Download completed!")
except FileNotFoundError:
print("File not found")
except AuthenticationError:
print("Authentication failed - check your credentials")from sharepointeasy import SharePointClient, create_progress_callback
client = SharePointClient()
# Files larger than 4MB are automatically uploaded in chunks
client.upload_file(
hostname="contoso.sharepoint.com",
site_path="sites/MySite",
file_path="Backups/database.sql",
source="./database.sql",
progress_callback=create_progress_callback("Uploading"),
)from sharepointeasy import SharePointClient
client = SharePointClient()
site = client.get_site("contoso.sharepoint.com", "sites/MySite")
drive = client.get_drive(site["id"])
# Download all files from SharePoint folder
client.download_batch(
site["id"],
drive["id"],
"Documents/Project",
"./local-project",
)
# Upload all files to SharePoint
client.upload_batch(
site["id"],
drive["id"],
"./local-project",
"Documents/Project-Backup",
)from sharepointeasy import SharePointClient
client = SharePointClient()
site = client.get_site("contoso.sharepoint.com", "sites/MySite")
lst = client.get_list(site["id"], "Tasks")
# List items with filter
items = client.list_items(
site["id"],
lst["id"],
filter_query="fields/Status eq 'Active'",
)
# Create a new item
client.create_item(site["id"], lst["id"], {
"Title": "New Task",
"Status": "Pending",
"Priority": "High",
})
# Update an item
client.update_item(site["id"], lst["id"], "123", {
"Status": "Completed",
})
# Batch operations
client.batch_create_items(site["id"], lst["id"], [
{"Title": "Task 1", "Status": "New"},
{"Title": "Task 2", "Status": "New"},
{"Title": "Task 3", "Status": "New"},
])from sharepointeasy import SharePointClient
client = SharePointClient()
# List calendars
calendars = client.list_user_calendars("[email protected]")
# List events in a date range
events = client.list_user_events(
user_id="[email protected]",
start_datetime="2025-01-01T00:00:00",
end_datetime="2025-12-31T23:59:59",
subject_contains="weekly sync",
)
# Search meetings with a specific attendee
meetings = client.search_meetings_with_attendee(
user_id="[email protected]",
attendee_email="[email protected]",
start_datetime="2025-01-01T00:00:00",
end_datetime="2025-12-31T23:59:59",
)
for m in meetings:
print(f"{m['start']['dateTime'][:10]} - {m['subject']}")import asyncio
from sharepointeasy import AsyncSharePointClient
async def download_reports():
async with AsyncSharePointClient() as client:
site = await client.get_site("contoso.sharepoint.com", "sites/MySite")
drive = await client.get_drive(site["id"])
# Download 10 files in parallel
files = await client.download_batch(
site["id"],
drive["id"],
"Documents/Reports/2024",
"./reports",
max_concurrent=10,
)
print(f"Downloaded {len(files)} files")
asyncio.run(download_reports())MIT