Usage¶
Project scope¶
Async Sharepoint is purpose-built for fast, non-blocking list, file, and folder workflows. It does not aim to expose every feature in SharePoint. For applications that need broad coverage of the full SharePoint API, use an established general-purpose SharePoint library instead.
Its narrower focus allows file listings to use optimistically parallel pagination and eager item refinement, avoiding a blocking request chain and a separate sequential property request for every returned file.
That said, I'm not opposed to making it feature complete, it just isn't a priority.
Connect¶
Create one client for the site and use it as an async context manager:
from async_sharepoint import CertificateCredential, SharePointClient
credential = CertificateCredential(
tenant_id="00000000-0000-0000-0000-000000000000",
client_id="11111111-1111-1111-1111-111111111111",
private_key_path="/path/to/azure-app-private.key",
thumbprint="D33CFD3BB83E0EFB90AF709C897025286244FA0E",
)
async with SharePointClient("https://example.sharepoint.com/sites/Team", credential) as client:
items = await client.ls()
The context manager verifies the credentials before entering and releases the client when finished. For credential setup, static tokens, and token refresh behavior, see Authentication. If a context manager does not fit your application lifecycle, close the client explicitly:
client = SharePointClient("https://example.sharepoint.com/sites/Team", credential)
try:
items = await client.ls()
finally:
await client.aclose()
Lists and list items¶
Get all lists, one list by title or ID, or the site's default document library:
lists = await client.get()
documents = await client.get("Documents")
documents_by_id = await client.get(id="b8d3d4a2-...")
default_documents = await client.get_default_document_library()
print(documents.title, documents.id)
print(documents.get_url())
Get list items through an SPList, or directly through the client by title or ID:
items = await documents.get_items()
items_by_title = await client.get_items("Documents")
items_by_id = await client.get_items(id=documents.id)
Both forms accept CAML. Use folder_path to scope a CAML query to a folder:
caml = """
<View>
<Query><Where><Eq>
<FieldRef Name="Status" />
<Value Type="Text">Active</Value>
</Eq></Where></Query>
</View>
"""
active_items = await documents.get_items(
caml=caml,
folder_path="/sites/Team/Documents/Current",
)
Return promptly with max_wait¶
For a paginated list or item query, max_wait limits how long the initial call spends following
pages. The call returns the items collected during that interval and an awaitable for everything
remaining:
items, remaining = await documents.get_items(max_wait=1)
# Start useful work once the initial pagination budget is spent.
for item in items:
print(item)
all_items = items + await remaining
The first page is always fetched. max_wait is also available when fetching all lists:
See Eager and parallel fetching for how pagination and item properties are fetched concurrently.
Browse files and folders¶
ls() lists the default document library root, a server-relative folder path, or a folder item:
root_items = await client.ls()
report_items = await client.ls("/sites/Team/Documents/Reports")
report_folder = next(item for item in root_items if item.FileSystemObjectType == 1)
folder_items = await report_folder.ls()
print(report_folder.get_url())
Items expose their SharePoint fields through both properties and attribute access, so
item.properties["Name"] and item.Name refer to the same value.
Get and download files¶
Get a file using a server-relative path:
file = await client.get_file("/sites/Team/Documents/Reports/summary.xlsx")
content = await file.download()
with open("summary.xlsx", "wb") as output:
output.write(content)
Or download directly when you do not need the SPFile:
Both get_file() and download() also accept native SharePoint browser links. Supported links
include an AllItems.aspx?id=... URL and a Doc.aspx?sourcedoc=... sharing URL:
browser_link = (
"https://example.sharepoint.com/sites/Team/Documents/Forms/AllItems.aspx"
"?id=%2Fsites%2FTeam%2FDocuments%2FReports%2Fsummary.xlsx"
)
file = await client.get_file(browser_link)
sharing_link = (
"https://example.sharepoint.com/sites/Team/_layouts/15/Doc.aspx"
"?sourcedoc=%7B01246A4B-84D7-49D6-8937-895D3C0F50A9%7D"
)
content = await client.download(sharing_link)
An SPFile can produce two useful SharePoint links. get_url() uses SharePoint's preferred URL
for the file, while browser_url() builds its document-library browsing URL:
Items returned by a list query start resolving their additional properties immediately in the
background. Methods such as download() wait for that work when necessary; call resolve()
explicitly before synchronously reading a property or generating a link that depends on it.
Upload files and create folders¶
folder = await client.add_folder("/sites/Team/Documents/Exports")
print(folder.get_url())
with open("results.csv", "rb") as source:
uploaded = await client.upload(
"/sites/Team/Documents/Exports",
"results.csv",
source.read(),
overwrite=True,
)
print(uploaded.server_relative_path)
Set overwrite=False on upload() to reject an existing filename. add_folder() also accepts
overwrite=True when an existing folder should be accepted.
Search, users, and permissions¶
Search within a list selected by title or ID:
results = await client.search("quarterly forecast", title="Documents", row_limit=20)
results_by_id = await client.search("quarterly forecast", id=documents.id)
Get the current SharePoint user and effective permissions for either that user or a specified login:
current_user = await client.get_current_user()
my_permissions = await client.get_effective_permissions("/sites/Team/Documents")
user_permissions = await client.get_effective_permissions(
"/sites/Team/Documents",
login_name="user@example.com",
)
Compared with Office365-REST-Python-Client¶
A basic file download with office365-rest-python-client is synchronous and requires each query
to be executed explicitly. A list item also needs another file query before it knows the file's
name:
ctx = ClientContext(some_site).with_access_token(gen_token)
ctx_all = ctx.web.lists.get_all().execute_query()
docs = ctx_all[8]
items = docs.get_items().execute_query()
first_file = next(x for x in items if x.properties.get("FileSystemObjectType") == 0)
usable_file = first_file.file.get().execute_query()
file_name = usable_file.properties.get("Name")
with open(target_path, "wb") as output:
usable_file.download(output).execute_query()
Async Sharepoint performs I/O asynchronously and begins resolving every returned item's additional properties in parallel:
ctx = SharePointClient(some_site, credential)
root = await ctx.get_default_document_library()
items, more_items = await root.get_items(max_wait=1)
usable_file = next(x for x in items if x.FileSystemObjectType == 0)
await usable_file.resolve()
file_name = usable_file.Name
with open(target_path, "wb") as output:
output.write(await usable_file.download())
Unlike the synchronous query chain, resolve() joins property retrieval that was already started
in parallel for every item. Await more_items when the operation needs the rest of the paginated
result.