Office365-REST-Python-Client

Microsoft 365 & Microsoft Graph Library for Python

MIT License

Downloads
7.9M
Stars
1.2K
Committers
46

Bot releases are hidden (Show)

Office365-REST-Python-Client - v 2.3.12

Published by vgrem over 2 years ago

Changelog

SharePoint API:

  • ListItem.validate_update_list_item method: setting dates_in_utc as an optional parameter (#509)
  • Search namespace enhancements #496

Example 1: submit search (KQL) query expression via SearchService.query method

ctx = ClientContext(site_url).with_credentials(credentials)
search = SearchService(ctx)
result = search.query("IsDocument:1").execute_query()

Example 2: construct sorting search results query and submit via SearchService.post_query method

ctx = ClientContext(site_url).with_credentials(credentials)
search = SearchService(ctx)
request = SearchRequest(query_text="IsDocument:1",
                        sort_list=[Sort("LastModifiedTime", 1)],
                        select_properties=["Path", "LastModifiedTime"],
                        row_limit=20)
result = search.post_query(request).execute_query()
Office365-REST-Python-Client - v 2.3.11

Published by vgrem over 2 years ago

Changelog

SharePoint API:

  • ListItem introduced support for system metadata update (#330)
  • SiteProperies.update method bug fix #480
  • Web.ensure_folder_path method bug fix #452

Support for ListItem system update

Prefer ListItem.validate_update_list_item method which supports overriding system metadata,
Here is an example which demonstrates how to update list item system metadata (namely Author and Modified field values):

ctx = ClientContext(site_url).with_credentials(credentials)

list_tasks = ctx.web.lists.get_by_title("Tasks")
items = list_tasks.items.get().top(1).execute_query()
if len(items) == 0:
    sys.exit("No items for update found")

item_to_update = items[0]  # type: ListItem
author = ctx.web.site_users.get_by_email(user_principal_name)

modified_date = datetime.utcnow() - timedelta(days=3)
result = item_to_update.validate_update_list_item({
    "Author": FieldUserValue.from_user(author),
    "Modified": modified_date
}).execute_query()

has_any_error = any([item.HasException for item in result.value])
if has_any_error:
    print("Item update completed with errors, for details refer 'ErrorMessage' property")
else:
    print("Item has been updated successfully")
Office365-REST-Python-Client - v 2.3.10

Published by vgrem over 2 years ago

Changelog

  • #433: OneDrive API: support for downloading large files (via chunked download) by @juguerre

Example:

from office365.graph_client import GraphClient
from office365.onedrive.driveitems.driveItem import DriveItem


def print_download_progress(offset):
    print("Downloaded '{0}' bytes...".format(offset))


client = GraphClient(acquire_token_by_username_password)
# # 1. address file by path and get file metadata
file_item = client.me.drive.root.get_by_path("archive/big_buck_bunny.mp4").get().execute_query()  # type: DriveItem
# 2 download a large file (chunked file download)
with tempfile.TemporaryDirectory() as local_path:
    with open(os.path.join(local_path, file_item.name), 'wb') as local_file:
        file_item.download_session(local_file, print_download_progress).execute_query()
    print("File '{0}' has been downloaded into {1}".format(file_item.name, local_file.name))

  • #430: improved support for overriding underlying HTTP request settings(such as proxy and SSL) by @juguerre

  • #465: SharePoint API: allow passing scopes via certificate authentication method by @theodoriss

Example

from office365.sharepoint.client_context import ClientContext


cert_settings = {
    'client_id': '-- app id--',
    'thumbprint': "-- cert thumbprint--",
    'cert_path': 'mycert.pem'),
    'scopes': ['https://contoso.onmicrosoft.com/.default']
}

ctx = ClientContext(test_site_url).with_client_certificate(test_tenant, **cert_settings)
current_web = ctx.web.get().execute_query()
print("{0}".format(current_web.url))
  • #461: include pytz to install dependency by @Zahlii

  • Microsoft Graph API: Improved support for delta queries (official docs)

Example: get incremental changes for users

client = GraphClient(acquire_token_func)
changed_users = self.client.users.delta.get().execute_query()
Office365-REST-Python-Client - v 2.3.9

Published by vgrem almost 3 years ago

Changelog

List of changes:

  • #234: determines if security validation expired and refresh if expired for SharePoint client
  • SharePoint API enhanced support for publishing & webhooks namespaces
  • Planner API model has been updated
  • Outlook API enhancements, namely the support for download MIME content of a message

SharePoint API: create a Site Page

The example demonstrates how to create a Site Page


ctx = ClientContext(team_site_url).with_credentials(client_credentials)
new_page = ctx.site_pages.pages.add()
new_page.save_draft(title="My news page")
new_page.publish().execute_query()

SharePoint API: create a new webhook

The example demonstrates how to create a webhook to SharePoint list:


ctx = ClientContext(site_url).with_credentials(client_credentials)
push_service_url = "https://westeurope0.pushnp.svc.ms/notifications?token=526a9d28-d4ec-45b7-81b9-4e1599524784"
target_list = client.web.lists.get_by_title("Documents")
subscription = target_list.subscriptions.add(push_service_url).execute_query()

where

push_service_url - your service endpoint URL. SharePoint sends an HTTP POST to this endpoint when events occur in the specified resource

Refer Overview of SharePoint webhooks for a details.

Planner API: create a task (Create plannerTask endpoint)

from office365.graph_client import GraphClient

client = GraphClient(acquire_token_func)
plan = ensure_plan(client.me.planner, "My plan")
task = client.planner.tasks.add(title="New task", planId=plan.id).execute_query()

Outlook API: download MIME content of a message (Get MIME content of a message endpoint)

The example demonstrates how to download an Outlook message body in MIME format and save into a file:

client = GraphClient(acquire_token_func)
# requires Mail.ReadWrite permission
user = client.users[test_user_principal_name]
messages = user.messages.select(["id"]).top(10).get().execute_query()
with tempfile.TemporaryDirectory() as local_path:
    for message in messages:  # type: Message
        with open(os.path.join(local_path, message.id + ".eml"), 'wb') as local_file:
            message.download(local_file).execute_query()  # download MIME representation of a message

Office365-REST-Python-Client - v 2.3.8

Published by vgrem about 3 years ago

Changelog

Bug fixes

  • #407 SecurableObject.get_user_effective_permissions de-serializing response bug fixed
  • #400 improved support for managing file versions (SharePoint API)
  • initial support for Reports API has been introduced
  • initial support for Search API has been introduced

Examples

Example: how to download a file version

ctx = ClientContext(team_site_url).with_credentials(client_credentials)
version = ctx.web.get_file_by_server_relative_path(file_url).versions.get_by_id(512)
with open(download_path, "wb") as local_file:
    file = version.download(local_file).execute_query()

Documentation:

Example: how to determine what kind of permissions the user has on a file

Documentation: ListItem.GetUserEffectivePermissions method

from pprint import pprint

from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.permissions.permission_kind import PermissionKind


client = ClientContext(team_site_url).with_credentials(user_credentials)
file_url = "/sites/team/Shared Documents/Guide.docx"

target_user = client.web.site_users.get_by_email(test_user_principal_name_alt)
target_file = client.web.get_file_by_server_relative_path(file_url)
result = target_file.listItemAllFields.get_user_effective_permissions(target_user).execute_query()
pprint(result.value.permission_levels)  # print all permission levels

# verify whether user has Reader role to a file
if result.value.has(PermissionKind.OpenItems):
    print("User has access to read a file")

Example: how to get the count of Microsoft 365 activations on desktops and devices (via Reports API)

Documentation: reportRoot: getOffice365ActivationsUserCounts

import msal
from office365.graph_client import GraphClient

def acquire_token_by_client_credentials():
    settings = load_settings()
    authority_url = 'https://login.microsoftonline.com/{0}'.format(tenant)
    app = msal.ConfidentialClientApplication(
        authority=authority_url,
        client_id=client_id,
        client_credential=client_secret
    )
    return app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])

client = GraphClient(acquire_token_by_client_credentials)
result = client.reports.get_office365_activations_user_counts().execute_query()

Example: how to search files (via Search API)

Documentation: use the Microsoft Search API to search content in OneDrive and SharePoint

import msal
from office365.graph_client import GraphClient

def acquire_token_by_client_credentials():
    settings = load_settings()
    authority_url = 'https://login.microsoftonline.com/{0}'.format(tenant)
    app = msal.ConfidentialClientApplication(
        authority=authority_url,
        client_id=client_id,
        client_credential=client_secret
    )
    return app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])

client = GraphClient(acquire_token_by_client_credentials)
result = client.search.query("Guide.docx", entity_types=["driveItem"]).execute_query()

Office365-REST-Python-Client - v 2.3.7

Published by vgrem about 3 years ago

Changelog

Bug fixes

  • #402 and #387: removed invalid dependency to generator module @rikeshtailor
  • #399: fix for downloading a file
  • Web.get_folder_by_server_relative_path return type fix @sharifhsn

Improvements:

  • error handling improvements (in terms of covering network exceptions along with invalid HTTP requests) @beliaev-maksim
  • improvements for JSON Batching support, for both v3 and v4 versions
Office365-REST-Python-Client - v 2.3.6

Published by vgrem about 3 years ago

Changelog

General

  • a preliminary support for communications API has been introduced
  • optimizing PyPI package in terms of excluding packages from production (e.g. tests)

SharePoint API specific

  • upload large files improvements in terms of optimizing of memory consumption (#377) @beliaev-maksim
  • new examples for SharePoint section (#293) @beliaev-maksim
  • Document Set improvements and bug fixes #379
  • settings Taxonomy field values fixes #380

OneDrive API specific

  • fixes for addressing drive items #374
  • improvements in terms of supporting and new nav types and methods for better API coverage, for example:

Example 1: address folder by path, where archive/2018 is a folder path:

folder_item = client.me.drive.root.get_by_path("archive/2018").get().execute_query()  # type: DriveItem

Teams API specific

  • improvements in terms of supporting and new nav types and methods for better API coverage

Examples: list all teams

client = GraphClient(acquire_token_by_client_credentials)
teams = client.teams.get_all(["displayName"]).execute_query()
for team in teams:  # type: Team
    print(team.display_name)
Office365-REST-Python-Client - v 2.3.5

Published by vgrem over 3 years ago

Changelog

  • general: compatibility with Python 2.7 (related: #326 & #275)
  • OneDrive API: improvements and fixes for addressing drive items #276
  • Graph client: improvements in terms of error handling for batch request, dependencies updated: msal 1.12.0
  • SharePoint API: fix for ListItem.update method (related #365)
  • SharePoint API: better support for addressing resources by resource path
  • SharePoint API: batch request improvements, i.e. support for specifying maximum of items to be executed per bulk operations, default is 100 (related: #349)
Office365-REST-Python-Client - v 2.3.4

Published by vgrem over 3 years ago

Changelog

  • SharePoint API: improved support for a file and folders addressing details

  • SharePoint API: support for saving taxonomy columns #353

Example: save a single-valued taxonomy field value

ctx = ClientContext(site_url).with_credentials(credentials)

tasks_list = ctx.web.lists.get_by_title("Tasks")
tax_field_value = TaxonomyFieldValue("{term-label}", "{term-guid}")
item_to_create = tasks_list.add_item({
    "Title": "New task",
    "{tex-column-name}": tax_field_value,
}).execute_query()

Example: save a multi-valued taxonomy field value

ctx = ClientContext(site_url).with_credentials(credentials)

tasks_list = ctx.web.lists.get_by_title("Tasks")
tax_field_value = TaxonomyFieldValue("{term-label}", "{term-guid}")
tax_field_values = TaxonomyFieldValueCollection([tax_field_value])
item_to_create = tasks_list.add_item({
    "Title": "New task",
    "{tex-column-name}": tax_field_values,
}).execute_query()

Office365-REST-Python-Client - v 2.3.3

Published by vgrem over 3 years ago

Changelog

  • #339: Introduced browser mode to imitate browser when obtaining the authentication cookies by @nsmcan
  • API improvements for Fluent interface
  • SharePoint Batching API improvements for error handling
Office365-REST-Python-Client - v 2.3.2

Published by vgrem over 3 years ago

Changelog

  • #320: escape XML characters in STS request by @andreas-j-hauser
  • #310: Revert ClientObject.get_property() semantics by @kraptor
  • SharePoint API improvements: #303 (addressing versions of ListItem), hubsite namespace, File/Folder copy/move operations
  • Graph client: initial support for batching
  • improved support for Calendar API

Support for batching for Graph client


def acquire_token_client_credentials():

    authority_url = 'https://login.microsoftonline.com/{tenant}'
    app = msal.ConfidentialClientApplication(
        authority=authority_url,
        client_id='{client-id}',
        client_credential='{client-secret}'
    )
    result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
    return result

client = GraphClient(acquire_token_client_credentials)

current_user = self.client.users['{user-principal-name}'].get()  # 1.1: construct query to retrieve user details
my_drive = self.client.users['{user-principal-name}'].drive.get()  # 1.2: construct query to retrieve user's drive
client.execute_batch()  # 2: submit a query to the server


Office365-REST-Python-Client - v 2.3.1

Published by vgrem almost 4 years ago

Changelog

Summary:

  • improved support for SharePoint API (fields, tenants namespaces)
  • bug fixes: #303 , #302 and #265

Improved support for SharePoint API

Here are a few examples which demonstrate how to create field and set values for a different field types:

Create a multi lookup field:

lookup_field = list.fields.add_lookup_field(title=lookup_field_name,
                                                                lookup_list_id=lookup_list.properties['Id'],
                                                                lookup_field_name='Title',
                                                                allow_multiple_values=True).execute_query()

Set a multi lookup field value

field_value = FieldMultiLookupValue()
field_value.add(FieldLookupValue(lookup_id))
updated = item_to_update.set_property(lookup_field_name, field_value).update().execute_query()

The list of methods (fields namespace):

  • FieldCollection.add_url_field(title)
  • FieldCollection.add_lookup_field(title, lookup_list_id, lookup_field_name, allow_multiple_values)
  • FieldCollection.add_choice_field(title, values, multiple_values)
  • FieldCollection.create_taxonomy_field(name, ssp_id, term_set_id, anchor_id,field_id, text_field_id, web_id, list_id)

The list of methods (tenant namespace):

  • Tenant.get_site_health_status(site_url)
Office365-REST-Python-Client - v 2.3.0 (with patches)

Published by vgrem almost 4 years ago

Changelog

  • requests_ntlm is included as an optional dependency
  • README.md broken links resolved
Office365-REST-Python-Client - v 2.3.0

Published by vgrem almost 4 years ago

Changelog

  • improvements for SAML-based claims authentication, kudos to @wreiner for the implementation and @nsmcan for the proposal #297, #272
  • support for # and % in SharePoint Online and OneDrive for Business by @kraptor #300
  • support for optional arguments for FileCollection.create_upload_session method by @beliaev-maksim #289
  • migration from adal library to msal as a mandatory dependency #296
  • improved support for sharepoint namespace, new types and methods (Tenant, ViewField, ContentType classes)
  • migration from Outlook API v1.0 to Microsoft Graph. Note: OutlookClient is decommissioned and no longer available
Office365-REST-Python-Client - v 2.2.2

Published by vgrem almost 4 years ago

Changelog

Office365-REST-Python-Client - v 2.2.1

Published by vgrem about 4 years ago

Changelog

Here is the comparison of two approaches, in the first example update operation is submitted to server per every list item, while in the second one multiple list item update operations are submitted via a since (batch) request:

list_tasks = ctx.web.lists.get_by_title("Tasks")
items = list_tasks.items.get().execute_query() #  
for task_id, item in enumerate(items):
    task_prefix = str(randint(0, 10000))
    item.set_property("Title", f"Task {task_prefix}")
    item.update()
    ctx.execute_query()  #  <- update operation is submitted to server per every  list item
list_tasks = ctx.web.lists.get_by_title("Tasks")
items = list_tasks.items.get().execute_query()   
for task_id, item in enumerate(items):
    task_prefix = str(randint(0, 10000))
    item.set_property("Title", f"Task {task_prefix}")
    item.update()
ctx.execute_batch()   # <- construct a single (batch) for all list items and submit to server
   list = client.web.lists.get_by_title(list_title)
   list.delete_object()
   client.execute_query()

list delete operation could be constructed and submitted to a server in a more compact manner:

   client.web.lists.get_by_title(list_title).delete_object().execute_query()
  • SharePoint API Changes namespace improvements (#259), here is the list of operations:

    • Site.get_changes
    • Web.get_changes
    • List.get_changes
    • ListItem.get_changes
  • SharePoint API RecycleBin entity class and operations

Office365-REST-Python-Client - v 2.2.0

Published by vgrem about 4 years ago

Changelog

Finally the initial support for SharePoint API Batch requests has been introduced. All insert/update/delete operations are supported.

The following example how current user and web objects could be retrieved by grouping two operations and submitting it as a single request to the server:

client = ClientContext(site_url).with_credentials(user_credentials)
current_user = client.web.currentUser
client.load(current_user)
current_web = client.web
client.load(current_web)
client.execute_batch()

which offers a new way of improving the performance.

Among another improvements and changes:

  • improved support for Office365 auth with ADFS by @liuliqiu

  • style enforcement (flake8), code formatting (isort) configuration by @domdinicola

  • ClientRuntimeContext.execute_query_retry method which implements Retry pattern

Office365-REST-Python-Client - v 2.1.10.1

Published by vgrem over 4 years ago

The list of changes:

  • #216 bug fixed. Credit goes to @liuliqiu
  • improved support for SharePoint API permissions and sharing namespaces
Office365-REST-Python-Client - v 2.1.10

Published by vgrem over 4 years ago

The list of changes

API support for Fluent interface

ctx = ClientContext(settings['url']).with_credentials(credentials)

target_web = ctx.web.load().execute_query()  #method chaining
print(target_web.url)

Support for addressing Web and File resources by absolute Url

abs_file_url = "https://{tenant}.sharepoint.com/sites/team/Shared Documents/sample.docx".format(tenant=tenant)
user_credentials = UserCredential(username, password)

with open(local_path, 'wb') as local_file:
    file = File.from_url(abs_file_url).with_credentials(user_credentials).download(local_file).execute_query()
print("'{0}' file has been downloaded".format(file.serverRelativeUrl))

Support for SharePoint Search API

According to Documentation

Search in SharePoint includes a Search REST service you can use to add search functionality to your client and mobile applications by
using any technology that supports REST web requests.

Example

The following example demonstrates how to construct a search for a documents (via Keyword Query Language syntax) and print file url (Path managed property)

from office365.runtime.auth.userCredential import UserCredential
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.search.searchRequest import SearchRequest
from office365.sharepoint.search.searchService import SearchService
from settings import settings


ctx = ClientContext.connect_with_credentials(site_url,
                                             UserCredential(username, password))

search = SearchService(ctx)
request = SearchRequest("IsDocument:1")
result = search.post_query(request)
ctx.execute_query()
relevant_results = result.PrimaryQueryResult.RelevantResults
for i in relevant_results['Table']['Rows']:
    cells = relevant_results['Table']['Rows'][i]['Cells']
    print(cells[6]['Value'])

Support for SharePoint TenantAdministration namespace

The following example demonstrates how to create a site collection via Tenant.CreateSite method:

admin_site_url = "https://{0}-admin.sharepoint.com/".format(tenant)
credentials = UserCredential(username, password)
client = ClientContext(admin_site_url).with_credentials(credentials)
tenant = Tenant(client)

props = SiteCreationProperties(target_site_url, user_principal_name)
site_props = tenant.ensure_site(props)
client.execute_query()

Improved support for SharePoint fields namespace

Creating list item and setting multi lookup field value:

create_info = {
            "Title": "New task"
        }
multi_lookup_value = FieldMultiLookupValue()
multi_lookup_value.add(FieldLookupValue(lookup_id))
new_item = self.target_list.add_item(create_info)
new_item.set_property("Predecessors", multi_lookup_value)
client.load(items)
client.execute_query()

Updating list item with multi choice field value:

multi_choice_value = FieldMultiChoiceValue(["In Progress"])
item_to_update.set_property("TaskStatuses", multi_choice_value)
item_to_update.update()
client.execute_query()

Bug fixes

  • #210: connect to Office 365 with federated accounts, credit goes to @liuliqiu

  • #206: SharePoint Session API upload

Office365-REST-Python-Client - v 2.1.9

Published by vgrem over 4 years ago

The list of changes

  • initial support for Microsoft Teams API
  • improved support for working with paged data
  • introduced support for certificate authentication for SharePoint API
  • improvements and model updates for SharePoint and OneDrive APIs

and more

Initial support for [Microsoft Teams API

The support for Microsoft Teams API has been introduced, the following example demonstrates how how create a new team under a group which corresponds to Create team endpoint

tenant_name = "contoso.onmicrosoft.com"
client = GraphClient(tenant_name, get_token)
new_team = client.groups[group_id].add_team()
client.execute_query()

where

def get_token(auth_ctx):
    """Acquire token via client credential flow (ADAL Python library is utilized)
    :type auth_ctx: adal.AuthenticationContext
    """
    token = auth_ctx.acquire_token_with_client_credentials(
        "https://graph.microsoft.com",
        client_id,
        client_secret)
    return token

Improved support for working with paged data

Here is an example which demonstrates how to retrieve data from a SharePoint list which contains more then 5k items:

def print_progress(items_read):
    print("Items read: {0}".format(items_read))


ctx = ClientContext.connect_with_credentials(site_url,
                                             ClientCredential(client_id,client_secret))

list_source = ctx.web.lists.get_by_title("Contacts_Large")
items = list_source.items
items.page_loaded += print_progress  # page load event
items.page_size = 400  # specify custom page size (default is 100)
ctx.load(items)
ctx.execute_query()

#print("Items count: {0}".format(len(items)))
for item in items:
    print("{0}".format(item.properties['Title']))

Support for certificate authentication for SharePoint API

The example demonstrates how to connect to SharePoint Online with certificate credentials:

ctx = ClientContext.connect_with_certificate(site_url,
                                             client_id,
                                             thumbprint,
                                             certificate_path)

current_web = ctx.web
ctx.load(current_web)
ctx.execute_query()
print("{0}".format(current_web.url))

Refer how-to page for a more details

Improvements and model updates for SharePoint and OneDrive APIs

In terms of file and folder operations the following methods have been introduced:

  • File.download(file_object) - download a file content into a file object (SharePoint API)
  • Folder.copyto(new_folder_url, overwrite) - copy a folder (SharePoint API)
  • Folder.moveto(new_folder_url, flags) move a folder (SharePoint API)
  • DriveItem.download(file_object) - downloads a file content into a file object (OneDrive API)
  • DriveItem.get_content() - downloads a file content (OneDrive API)