Skip to content

Releases: vgrem/Office365-REST-Python-Client

v 2.3.16

19 Nov 19:34
Compare
Choose a tag to compare

Changelog

Create a new table example

from office365.graph_client import GraphClient
from office365.onedrive.workbooks.tables.rows.row import WorkbookTableRow

file_name = "Financial Sample.xlsx"
client = GraphClient(acquire_token)
workbook = client.me.drive.root.get_by_path(file_name).workbook
table = workbook.tables.add("A1:C10", True).execute_query()

List rows example

from office365.graph_client import GraphClient
from office365.onedrive.workbooks.tables.rows.row import WorkbookTableRow

file_name = "Financial Sample.xlsx"
client = GraphClient(acquire_token)
workbook = client.me.drive.root.get_by_path(file_name).workbook
table = workbook.worksheets["Sheet1"].tables["financials"].get().execute_query()
print(table.name)

# read table content
rows = table.rows.get().execute_query()
for r in rows:  # type: WorkbookTableRow
    print(r.values) 

v 2.3.15

28 Oct 17:03
Compare
Choose a tag to compare

Changelog

  • #569: fix for ClientRuntimeContext.execute_query_retry method by @jneuendorf
  • #584: escape password in _acquire_service_token_from_adfs-method by @chrisdecker1201
  • #568: support for passing private_key into with_client_certificate method
  • enhancements for SharePoint & OneDrive APIs

Enhancements for SharePoint & OneDrive APIs

Instantiate SharePoint client with certificate credentials

cert_path = 'selfsigncert.pem'
with open(cert_path, 'r') as f:
      private_key = open(cert_path).read()

cert_credentials = {
     'tenant': test_tenant,
     'client_id': '--client id--',
     'thumbprint': '--thumbprint--',
     'private_key': private_key
}
ctx = ClientContext(test_team_site_url).with_client_certificate(**cert_credentials)

Setting image field value

field_value = ImageFieldValue(image_url)
list_item.set_property(field_name, field_value).update().execute_query()

v 2.3.14

07 Sep 20:52
Compare
Choose a tag to compare

Changelog

Paged data retrieval enhancements, namely:

  1. introduction of ClientObjectCollection.get_all method to retrieve all the items in a collection, regardless of the size, for example:
def print_progress(items):
    """
    :type items: office365.sharepoint.listitems.collection.ListItemCollection
    """
    print("Items read: {0}".format(len(items)))

page_size = 500
ctx = ClientContext(site_url).with_credentials(client_credentials)
large_list = ctx.web.lists.get_by_title(list_title)

all_items = target_list.items.get_all(page_size, print_progress).execute_query()
  1. retrieving paged data via ClientObjectCollection.paged method
page_size = 500

ctx = ClientContext(site_url).with_credentials(client_credentials)
large_list = ctx.web.lists.get_by_title(list_title)
paged_items = large_list.items.paged(page_size, page_loaded=print_progress).get().execute_query()
    for index, item in enumerate(paged_items):  # type: int, ListItem
        print("{0}: {1}".format(index, item.id))

Bug fixes:

  • #541: client certificate auth fails when non root site is provided
  • #529: Python 2.7 compatibility fixes
  • #527: fix for Folder.copy_to_using_path method

v 2.3.13

21 Jun 17:32
Compare
Choose a tag to compare

Changelog

Bug fixes:

  • #524: determine and construct the list of properties (including navigation) to be retrieved of QueryOptions.build method, kudos to @jjloneman
  • #505: improved file addressing in SharePoint API by @fan-e-cae
  • better support for Sharing namespace in SharePoint API
  • introduced support for Site Designs and Site Scripts in SharePoint API

Example: Share an anonymous access link with view permissions to a file

ctx = ClientContext(site_url).with_credentials(credentials)
file = ctx.web.get_file_by_server_relative_url(file_url)
result = target_file.share_link(SharingLinkKind.AnonymousView).execute_query()

Example: create a new site script that apply a custom theme

ctx = ClientContext(site_url).with_credentials(credentials)
site_script = {
    "$schema": "schema.json",
    "actions": [
        {
            "verb": "applyTheme",
            "themeName": "Contoso Theme"
        }
    ],
    "bindata": {},
    "version": 1
}

result = SiteScriptUtility.create_site_script(ctx, "Contoso theme script", "", site_script).execute_query()

v 2.3.12

29 May 11:43
Compare
Choose a tag to compare

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()

v 2.3.11

20 Feb 22:09
Compare
Choose a tag to compare

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")

v 2.3.10

23 Jan 11:23
Compare
Choose a tag to compare

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()

v 2.3.9

07 Nov 14:24
Compare
Choose a tag to compare

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

v 2.3.8

05 Sep 12:38
Compare
Choose a tag to compare

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()

v 2.3.7

28 Aug 20:51
Compare
Choose a tag to compare

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