diff --git a/examples/directory/applications/list_applications.py b/examples/directory/applications/list_applications.py
index b35f8477..f62ec0a8 100644
--- a/examples/directory/applications/list_applications.py
+++ b/examples/directory/applications/list_applications.py
@@ -1,12 +1,14 @@
"""
Get the list of applications in this organization
-https://learn.microsoft.com/en-us/graph/api/application-list?view=graph-rest-1.0&tabs=http
+https://learn.microsoft.com/en-us/graph/api/application-list?view=graph-rest-1.0
"""
from office365.graph_client import GraphClient
-from tests.graph_case import acquire_token_by_username_password
+from tests import test_client_id, test_password, test_tenant, test_username
-client = GraphClient(acquire_token_by_username_password)
+client = GraphClient.with_username_and_password(
+ test_tenant, test_client_id, test_username, test_password
+)
apps = client.applications.get().top(10).execute_query()
for app in apps:
print(app)
diff --git a/examples/directory/groups/create_with_team.py b/examples/directory/groups/create_with_team.py
index 0416d3b9..42068ce8 100644
--- a/examples/directory/groups/create_with_team.py
+++ b/examples/directory/groups/create_with_team.py
@@ -5,8 +5,13 @@
"""
from office365.graph_client import GraphClient
-from tests import create_unique_name
-from tests.graph_case import acquire_token_by_username_password
+from tests import (
+ create_unique_name,
+ test_client_id,
+ test_password,
+ test_tenant,
+ test_username,
+)
def print_failure(retry_number, ex):
@@ -16,7 +21,9 @@ def print_failure(retry_number, ex):
print(f"{retry_number}: Team creation still in progress, waiting...")
-client = GraphClient(acquire_token_by_username_password)
+client = GraphClient.with_username_and_password(
+ test_tenant, test_client_id, test_username, test_password
+)
group_name = create_unique_name("Flight")
group = client.groups.create_with_team(group_name).execute_query_retry(
max_retry=10, failure_callback=print_failure
diff --git a/examples/directory/groups/delete_batch.py b/examples/directory/groups/delete_batch.py
index 88ac3036..4f802436 100644
--- a/examples/directory/groups/delete_batch.py
+++ b/examples/directory/groups/delete_batch.py
@@ -1,13 +1,15 @@
"""
Delete groups in batch mode
-https://learn.microsoft.com/en-us/graph/api/group-delete?view=graph-rest-1.0&tabs=http
+https://learn.microsoft.com/en-us/graph/api/group-delete?view=graph-rest-1.0
"""
from office365.graph_client import GraphClient
-from tests.graph_case import acquire_token_by_username_password
+from tests import test_client_id, test_password, test_tenant, test_username
-client = GraphClient(acquire_token_by_username_password)
+client = GraphClient.with_username_and_password(
+ test_tenant, test_client_id, test_username, test_password
+)
result = client.groups.get_all().execute_query()
print("Total groups count (before): {0}".format(len(result)))
diff --git a/examples/directory/groups/delete_groups.py b/examples/directory/groups/delete_groups.py
index 65f727d8..6bef30df 100644
--- a/examples/directory/groups/delete_groups.py
+++ b/examples/directory/groups/delete_groups.py
@@ -6,12 +6,14 @@
- Group.delete_object() Microsoft 365 groups are moved to a temporary container and can be restored within 30 days
- Group.delete_object(permanent_delete=True) Microsoft 365 permanently deleted
-https://learn.microsoft.com/en-us/graph/api/group-delete?view=graph-rest-1.0&tabs=http
+https://learn.microsoft.com/en-us/graph/api/group-delete?view=graph-rest-1.0
"""
from office365.graph_client import GraphClient
-from tests.graph_case import acquire_token_by_username_password
+from tests import test_client_id, test_password, test_tenant, test_username
-client = GraphClient(acquire_token_by_username_password)
+client = GraphClient.with_username_and_password(
+ test_tenant, test_client_id, test_username, test_password
+)
groups = client.groups.get().top(10).execute_query()
deletedCount = 0
groups_count = len(groups)
@@ -19,7 +21,7 @@
cur_grp = groups[0]
print(
"({0} of {1}) Deleting {2} group ...".format(
- deletedCount + 1, groups_count, cur_grp.properties["displayName"]
+ deletedCount + 1, groups_count, cur_grp.display_name
)
)
cur_grp.delete_object(permanent_delete=True).execute_query()
diff --git a/examples/directory/users/import.py b/examples/directory/users/import.py
index 6b86ee63..099837ae 100644
--- a/examples/directory/users/import.py
+++ b/examples/directory/users/import.py
@@ -2,8 +2,13 @@
from office365.directory.users.profile import UserProfile
from office365.graph_client import GraphClient
-from tests import create_unique_name, test_tenant
-from tests.graph_case import acquire_token_by_username_password
+from tests import (
+ create_unique_name,
+ test_client_id,
+ test_password,
+ test_tenant,
+ test_username,
+)
def generate_user_profile():
@@ -23,7 +28,9 @@ def generate_user_profile():
return UserProfile(**user_json)
-client = GraphClient(acquire_token_by_username_password)
+client = GraphClient.with_username_and_password(
+ test_tenant, test_client_id, test_username, test_password
+)
for idx in range(0, 1):
user_profile = generate_user_profile()
diff --git a/examples/insights/list_used.py b/examples/insights/list_used.py
index b63834c1..8d8e09a1 100644
--- a/examples/insights/list_used.py
+++ b/examples/insights/list_used.py
@@ -5,9 +5,11 @@
"""
from office365.graph_client import GraphClient
-from tests.graph_case import acquire_token_by_username_password
+from tests import test_client_id, test_password, test_tenant, test_username
-client = GraphClient(acquire_token_by_username_password)
+client = GraphClient.with_username_and_password(
+ test_tenant, test_client_id, test_username, test_password
+)
result = client.me.insights.used.get().execute_query()
for item in result:
- print("Resource url: {0}".format(item.resource_reference))
+ print("Resource: {0}".format(item.resource_reference))
diff --git a/examples/onedrive/excel/list_worksheets.py b/examples/onedrive/excel/list_worksheets.py
index d08f2b27..e5c14979 100644
--- a/examples/onedrive/excel/list_worksheets.py
+++ b/examples/onedrive/excel/list_worksheets.py
@@ -7,9 +7,11 @@
import sys
from office365.graph_client import GraphClient
-from tests.graph_case import acquire_token_by_username_password
+from tests import test_client_id, test_password, test_tenant, test_username
-client = GraphClient(acquire_token_by_username_password)
+client = GraphClient.with_username_and_password(
+ test_tenant, test_client_id, test_username, test_password
+)
drive_item = client.me.drive.root.get_by_path("Financial Sample.xlsx")
worksheets = drive_item.workbook.worksheets.get().execute_query()
if len(worksheets) == 0:
diff --git a/examples/onedrive/files/create_sharing_link.py b/examples/onedrive/files/create_sharing_link.py
index 16074deb..4ade3b1a 100644
--- a/examples/onedrive/files/create_sharing_link.py
+++ b/examples/onedrive/files/create_sharing_link.py
@@ -5,13 +5,15 @@
The sharing link is configured to be read-only and usable by anyone with the link.
All existing permissions are removed when sharing for the first time if retainInheritedPermissions is false.
-https://learn.microsoft.com/en-us/graph/api/driveitem-createlink?view=graph-rest-1.0&tabs=http
+https://learn.microsoft.com/en-us/graph/api/driveitem-createlink?view=graph-rest-1.0
"""
from office365.graph_client import GraphClient
-from tests.graph_case import acquire_token_by_username_password
+from tests import test_client_id, test_password, test_tenant, test_username
-client = GraphClient(acquire_token_by_username_password)
+client = GraphClient.with_username_and_password(
+ test_tenant, test_client_id, test_username, test_password
+)
file_path = "Financial Sample.xlsx"
drive_item = client.me.drive.root.get_by_path(file_path)
permission = drive_item.create_link(
diff --git a/examples/onedrive/sites/get_by_url.py b/examples/onedrive/sites/get_by_url.py
index 998df41f..fdc51d84 100644
--- a/examples/onedrive/sites/get_by_url.py
+++ b/examples/onedrive/sites/get_by_url.py
@@ -1,12 +1,11 @@
"""
Get site by url
-https://learn.microsoft.com/en-us/graph/api/site-get?view=graph-rest-1.0&tabs=http
+https://learn.microsoft.com/en-us/graph/api/site-get?view=graph-rest-1.0
"""
from office365.graph_client import GraphClient
-from tests import test_team_site_url
-from tests.graph_case import acquire_token_by_client_credentials
+from tests import test_client_id, test_client_secret, test_team_site_url, test_tenant
-client = GraphClient(acquire_token_by_client_credentials)
+client = GraphClient.with_client_secret(test_tenant, test_client_id, test_client_secret)
site = client.sites.get_by_url(test_team_site_url).get().execute_query()
print("Site Id: {0}".format(site.id))
diff --git a/examples/onedrive/sites/grant_permission.py b/examples/onedrive/sites/grant_permission.py
index 26d45bbe..e68f90bd 100644
--- a/examples/onedrive/sites/grant_permission.py
+++ b/examples/onedrive/sites/grant_permission.py
@@ -5,13 +5,17 @@
"""
from office365.graph_client import GraphClient
-from tests import test_client_credentials, test_team_site_url
-from tests.graph_case import acquire_token_by_client_credentials
+from tests import (
+ test_client_id,
+ test_client_secret,
+ test_team_site_url,
+ test_tenant,
+)
-client = GraphClient(acquire_token_by_client_credentials)
+client = GraphClient.with_client_secret(test_tenant, test_client_id, test_client_secret)
print("Retrieving app...")
-app = client.applications.get_by_app_id(test_client_credentials.clientId)
+app = client.applications.get_by_app_id(test_client_id)
print("Granting an Application a permissions on Site...")
site = client.sites.get_by_url(test_team_site_url)
diff --git a/examples/onedrive/sites/search.py b/examples/onedrive/sites/search.py
index 9ce04088..aa115997 100644
--- a/examples/onedrive/sites/search.py
+++ b/examples/onedrive/sites/search.py
@@ -5,9 +5,9 @@
"""
from office365.graph_client import GraphClient
-from tests.graph_case import acquire_token_by_client_credentials
+from tests import test_client_id, test_client_secret, test_tenant
-client = GraphClient(acquire_token_by_client_credentials)
+client = GraphClient.with_client_secret(test_tenant, test_client_id, test_client_secret)
sites = client.sites.search("team").execute_query()
for site in sites:
print("Site url: {0}".format(site.web_url))
diff --git a/examples/onedrive/termstore/export_term_store.py b/examples/onedrive/termstore/export_term_store.py
index 0d15e493..cceb5b46 100644
--- a/examples/onedrive/termstore/export_term_store.py
+++ b/examples/onedrive/termstore/export_term_store.py
@@ -2,10 +2,9 @@
Demonstrates how to retrieve a flat list of all TermSet objects
"""
from office365.graph_client import GraphClient
-from tests import test_team_site_url
-from tests.graph_case import acquire_token_by_client_credentials
+from tests import test_client_id, test_client_secret, test_team_site_url, test_tenant
-client = GraphClient(acquire_token_by_client_credentials)
+client = GraphClient.with_client_secret(test_tenant, test_client_id, test_client_secret)
term_sets = (
client.sites.get_by_url(test_team_site_url)
.term_store.get_all_term_sets()
diff --git a/examples/outlook/messages/get_basic_props.py b/examples/outlook/messages/get_basic_props.py
index 0e923a34..b6a978d4 100644
--- a/examples/outlook/messages/get_basic_props.py
+++ b/examples/outlook/messages/get_basic_props.py
@@ -4,10 +4,14 @@
"""
from office365.graph_client import GraphClient
-from tests import test_user_principal_name
-from tests.graph_case import acquire_token_by_client_credentials
+from tests import (
+ test_client_id,
+ test_client_secret,
+ test_tenant,
+ test_user_principal_name,
+)
-client = GraphClient(acquire_token_by_client_credentials)
+client = GraphClient.with_client_secret(test_tenant, test_client_id, test_client_secret)
user = client.users[test_user_principal_name]
messages = user.messages.select(["id", "subject"]).top(10).get().execute_query()
for message in messages:
diff --git a/examples/sharepoint/sites/grant_app_access.py b/examples/sharepoint/sites/grant_app_access.py
index 7fa5e569..ab3c5e5a 100644
--- a/examples/sharepoint/sites/grant_app_access.py
+++ b/examples/sharepoint/sites/grant_app_access.py
@@ -6,12 +6,16 @@
"""
from office365.graph_client import GraphClient
-from tests import test_client_credentials, test_team_site_url
-from tests.graph_case import acquire_token_by_client_credentials
+from tests import (
+ test_client_id,
+ test_client_secret,
+ test_team_site_url,
+ test_tenant,
+)
-client = GraphClient(acquire_token_by_client_credentials)
+client = GraphClient.with_client_secret(test_tenant, test_client_id, test_client_secret)
site = client.sites.get_by_url(test_team_site_url)
-app = client.applications.get_by_app_id(test_client_credentials.clientId)
+app = client.applications.get_by_app_id(test_client_id)
roles = ["read", "write"]
print("Granting {0} permissions for application {1}".format(roles, app))
diff --git a/examples/sharepoint/users/add_to_web.py b/examples/sharepoint/users/add_to_web.py
new file mode 100644
index 00000000..87b236ed
--- /dev/null
+++ b/examples/sharepoint/users/add_to_web.py
@@ -0,0 +1,14 @@
+"""
+
+If the specified login name belongs to a valid user of the site, returns the User object corresponding to that user.
+
+If the specified login name belongs to a valid user outside of the site, adds the user to the site and
+returns the User object corresponding to that user.
+
+"""
+from office365.sharepoint.client_context import ClientContext
+from tests import test_admin_credentials, test_team_site_url, test_user_principal_name
+
+client = ClientContext(test_team_site_url).with_credentials(test_admin_credentials)
+target_user = client.web.ensure_user(test_user_principal_name).execute_query()
+print(target_user)
diff --git a/generator/import_metadata.py b/generator/import_metadata.py
index cddc3963..0bb39167 100644
--- a/generator/import_metadata.py
+++ b/generator/import_metadata.py
@@ -3,8 +3,13 @@
from office365.graph_client import GraphClient
from office365.sharepoint.client_context import ClientContext
-from tests import test_client_credentials, test_site_url
-from tests.graph_case import acquire_token_by_client_credentials
+from tests import (
+ test_client_credentials,
+ test_client_id,
+ test_client_secret,
+ test_site_url,
+ test_tenant,
+)
def export_to_file(path, content):
@@ -21,13 +26,13 @@ def export_to_file(path, content):
"--endpoint",
dest="endpoint",
help="Import metadata endpoint",
- default="microsoftgraph",
+ default="sharepoint",
)
parser.add_argument(
"-p",
"--path",
dest="path",
- default="./metadata/MicrosoftGraph.xml",
+ default="./metadata/SharePoint.xml",
help="Import metadata endpoint",
)
@@ -40,6 +45,8 @@ def export_to_file(path, content):
export_to_file(args.path, result.value)
elif args.endpoint == "microsoftgraph":
print("Importing Microsoft Graph model metadata...")
- client = GraphClient(acquire_token_by_client_credentials)
+ client = GraphClient.with_client_secret(
+ test_tenant, test_client_id, test_client_secret
+ )
result = client.get_metadata().execute_query()
export_to_file(args.path, result.value)
diff --git a/generator/metadata/MicrosoftGraph.xml b/generator/metadata/MicrosoftGraph.xml
index 91f88640..2360b55d 100644
--- a/generator/metadata/MicrosoftGraph.xml
+++ b/generator/metadata/MicrosoftGraph.xml
@@ -21380,6 +21380,7 @@
+
@@ -38239,6 +38240,7 @@
+
@@ -38351,6 +38353,7 @@
+
@@ -38862,6 +38865,7 @@
+
diff --git a/generator/metadata/SharePoint.xml b/generator/metadata/SharePoint.xml
index 8b418288..9d0bc485 100644
--- a/generator/metadata/SharePoint.xml
+++ b/generator/metadata/SharePoint.xml
@@ -168,6 +168,9 @@
+
+
+
@@ -200,6 +203,7 @@
+
@@ -256,6 +260,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -295,6 +318,7 @@
+
@@ -328,19 +352,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -367,6 +378,13 @@
+
+
+
+
+
+
+
@@ -412,6 +430,7 @@
+
@@ -608,6 +627,7 @@
+
@@ -780,6 +800,12 @@
+
+
+
+
+
+
@@ -1352,6 +1378,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1404,6 +1442,15 @@
+
+
+
+
+
+
+
+
+
@@ -1488,6 +1535,7 @@
+
@@ -2115,7 +2163,6 @@
-
@@ -2682,7 +2729,7 @@
-
+
@@ -2853,6 +2900,7 @@
+
@@ -4528,6 +4576,8 @@
+
+
@@ -4556,7 +4606,7 @@
-
+
@@ -8484,6 +8534,12 @@
+
+
+
+
+
+
@@ -8676,6 +8732,12 @@
+
+
+
+
+
+
@@ -8904,6 +8966,12 @@
+
+
+
+
+
+
@@ -9102,6 +9170,12 @@
+
+
+
+
+
+
@@ -9285,6 +9359,12 @@
+
+
+
+
+
+
@@ -9495,6 +9575,12 @@
+
+
+
+
+
+
@@ -10097,6 +10183,10 @@
+
+
+
+
@@ -10168,12 +10258,12 @@
-
+
-
+
@@ -10931,10 +11021,6 @@
-
-
-
-
@@ -10979,9 +11065,6 @@
-
-
-
@@ -11382,12 +11465,12 @@
-
-
+
+
-
-
-
+
+
+
@@ -11637,14 +11720,6 @@
-
-
-
-
-
-
-
-
@@ -12125,6 +12200,9 @@
+
+
+
@@ -12153,6 +12231,10 @@
+
+
+
+
@@ -12170,6 +12252,10 @@
+
+
+
+
@@ -12400,6 +12486,10 @@
+
+
+
+
@@ -12708,6 +12798,7 @@
+
@@ -12812,11 +12903,13 @@
+
+
@@ -13263,12 +13356,12 @@
-
-
-
+
+
+
@@ -13279,6 +13372,9 @@
+
+
+
@@ -14497,6 +14593,10 @@
+
+
+
+
@@ -14585,10 +14685,12 @@
+
+
@@ -15011,6 +15113,9 @@
+
+
+
@@ -15134,6 +15239,10 @@
+
+
+
+
@@ -15144,6 +15253,10 @@
+
+
+
+
@@ -16368,6 +16481,10 @@
+
+
+
+
@@ -16478,10 +16595,16 @@
+
+
+
+
+
+
@@ -16898,6 +17021,9 @@
+
+
+
@@ -17405,9 +17531,9 @@
-
-
-
+
+
+
@@ -19724,6 +19850,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -20015,6 +20165,9 @@
+
+
+
@@ -20702,13 +20855,19 @@
-
+
-
+
+
+
+
+
+
+
@@ -20837,6 +20996,9 @@
+
+
+
@@ -20987,6 +21149,9 @@
+
+
+
@@ -21053,6 +21218,9 @@
+
+
+
@@ -23547,7 +23715,7 @@
-
+
@@ -23913,6 +24081,12 @@
+
+
+
+
+
+
@@ -24120,24 +24294,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -24660,6 +24816,12 @@
+
+
+
+
+
+
@@ -24828,6 +24990,12 @@
+
+
+
+
+
+
@@ -24954,6 +25122,12 @@
+
+
+
+
+
+
@@ -25059,6 +25233,12 @@
+
+
+
+
+
+
@@ -25203,6 +25383,12 @@
+
+
+
+
+
+
@@ -25356,6 +25542,12 @@
+
+
+
+
+
+
@@ -25851,9 +26043,6 @@
-
-
-
@@ -26055,10 +26244,10 @@
-
+
-
+
@@ -26118,9 +26307,6 @@
-
-
-
@@ -26199,6 +26385,9 @@
+
+
+
@@ -26217,6 +26406,9 @@
+
+
+
@@ -26301,7 +26493,7 @@
-
+
@@ -26328,10 +26520,10 @@
-
+
-
+
@@ -26484,10 +26676,10 @@
-
+
-
+
@@ -26502,6 +26694,9 @@
+
+
+
@@ -26770,10 +26965,10 @@
-
+
-
+
@@ -26833,6 +27028,9 @@
+
+
+
@@ -26872,9 +27070,15 @@
+
+
+
+
+
+
@@ -27184,12 +27388,21 @@
+
+
+
+
+
+
+
+
+
@@ -27208,6 +27421,9 @@
+
+
+
@@ -27488,6 +27704,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -31590,11 +31816,17 @@
+
+
+
+
+
+
@@ -33877,6 +34109,7 @@
+
@@ -33898,12 +34131,14 @@
+
+
@@ -33974,6 +34209,7 @@
+
@@ -33986,6 +34222,7 @@
+
@@ -33996,6 +34233,7 @@
+
@@ -34234,11 +34472,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -34265,18 +34517,35 @@
-
+
+
-
-
+
+
-
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -34291,7 +34560,7 @@
-
+
@@ -34316,9 +34585,9 @@
-
-
-
+
+
+
@@ -34795,11 +35064,15 @@
+
+
+
+
@@ -34811,9 +35084,10 @@
+
+
-
@@ -34837,6 +35111,8 @@
+
+
@@ -34879,11 +35155,13 @@
+
+
@@ -34948,6 +35226,7 @@
+
@@ -35137,7 +35416,12 @@
+
+
+
+
+
@@ -35229,6 +35513,7 @@
+
@@ -35379,6 +35664,7 @@
+
@@ -35441,9 +35727,11 @@
+
+
@@ -35456,6 +35744,7 @@
+
@@ -36111,6 +36400,7 @@
+
@@ -36258,6 +36548,7 @@
+
@@ -36341,6 +36632,7 @@
+
@@ -36561,6 +36853,7 @@
+
@@ -36600,6 +36893,7 @@
+
@@ -36753,6 +37047,7 @@
+
@@ -36772,6 +37067,10 @@
+
+
+
+
@@ -36796,12 +37095,6 @@
-
-
-
-
-
-
@@ -36831,6 +37124,7 @@
+
@@ -36848,6 +37142,7 @@
+
@@ -36884,6 +37179,9 @@
+
+
+
@@ -38188,6 +38486,7 @@
+
@@ -38404,6 +38703,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -38916,12 +39230,6 @@
-
-
-
-
-
-
@@ -38947,6 +39255,7 @@
+
diff --git a/office365/directory/insights/resource_reference.py b/office365/directory/insights/resource_reference.py
index becdb554..0fcb914e 100644
--- a/office365/directory/insights/resource_reference.py
+++ b/office365/directory/insights/resource_reference.py
@@ -15,7 +15,7 @@ def __init__(self, _id=None, _type=None, web_url=None):
self.webUrl = web_url
def __str__(self):
- return self.type
+ return self.type or ""
def __repr__(self):
return "{0}:{1}".format(self.type, self.webUrl)
diff --git a/office365/onedrive/sitepages/canvas_layout.py b/office365/onedrive/sitepages/canvas_layout.py
new file mode 100644
index 00000000..de1abed9
--- /dev/null
+++ b/office365/onedrive/sitepages/canvas_layout.py
@@ -0,0 +1,5 @@
+from office365.entity import Entity
+
+
+class CanvasLayout(Entity):
+ """Represents the layout of the content in a given SharePoint page."""
diff --git a/office365/onedrive/sitepages/site_page.py b/office365/onedrive/sitepages/site_page.py
index cb5a7c7d..bbff3789 100644
--- a/office365/onedrive/sitepages/site_page.py
+++ b/office365/onedrive/sitepages/site_page.py
@@ -1,6 +1,108 @@
+from typing import Optional
+
+from office365.entity_collection import EntityCollection
from office365.onedrive.sitepages.base import BaseSitePage
+from office365.onedrive.sitepages.canvas_layout import CanvasLayout
+from office365.onedrive.sitepages.web_part import WebPart
+from office365.runtime.paths.resource_path import ResourcePath
+from office365.runtime.queries.function import FunctionQuery
+from office365.runtime.queries.service_operation import ServiceOperationQuery
class SitePage(BaseSitePage):
"""This resource represents a page in the sitePages list. It contains the title, layout, and a collection of
webParts."""
+
+ def get_web_parts_by_position(
+ self, webPartIndex, horizontalSectionId, isInVerticalSection, columnId
+ ):
+ """
+ Get a collection of webPart by providing webPartPosition information.
+
+ :param float webPartIndex: Index of the current WebPart. Represents the order of WebPart in this column or
+ section. Only works if either columnId or isInVerticalSection is provided.
+ :param float horizontalSectionId: Indicate the horizontal section where the WebPart located in.
+ :param bool isInVerticalSection: Indicate whether the WebPart located in the vertical section.
+ :param float columnId: Indicate the identifier of the column where the WebPart located in. Only works
+ if horizontalSectionId is provided.
+ """
+ params = {
+ "webPartIndex": webPartIndex,
+ "horizontalSectionId": horizontalSectionId,
+ "isInverticalSection": isInVerticalSection,
+ "columnId": columnId,
+ }
+ return_type = EntityCollection(
+ self.context, WebPart, ResourcePath("webParts", self.resource_path)
+ )
+ qry = FunctionQuery(self, "getWebPartsByPosition", params, return_type)
+ self.context.add_query(qry)
+ return return_type
+
+ def publish(self):
+ """
+ Publish the latest version of a sitePage resource, which makes the version of the page available to all users.
+ If the page is checked out, check in the page and publish it. If the page is checked out to the caller
+ of this API, the page is automatically checked in and then published.
+
+ If a page approval flow has been activated in the page library, the page is not published until the approval
+ flow is completed.
+ """
+ qry = ServiceOperationQuery(self, "publish")
+ self.context.add_query(qry)
+ return self
+
+ @property
+ def promotion_kind(self):
+ # type: () -> Optional[str]
+ """Indicates the promotion kind of the sitePage."""
+ return self.properties.get("promotionKind", None)
+
+ @property
+ def show_comments(self):
+ # type: () -> Optional[bool]
+ """Determines whether or not to show comments at the bottom of the page."""
+ return self.properties.get("showComments", None)
+
+ @property
+ def show_recommended_pages(self):
+ # type: () -> Optional[bool]
+ """Determines whether or not to show recommended pages at the bottom of the page."""
+ return self.properties.get("showRecommendedPages", None)
+
+ @property
+ def thumbnail_web_url(self):
+ # type: () -> Optional[str]
+ """Indicates the promotion kind of the sitePage."""
+ return self.properties.get("thumbnailWebUrl", None)
+
+ @property
+ def canvas_layout(self):
+ # type: () -> CanvasLayout
+ """The default termStore under this site."""
+ return self.properties.get(
+ "canvasLayout",
+ CanvasLayout(
+ self.context, ResourcePath("canvasLayout", self.resource_path)
+ ),
+ )
+
+ @property
+ def web_parts(self):
+ # type: () -> CanvasLayout
+ """Collection of webparts on the SharePoint page."""
+ return self.properties.get(
+ "webParts",
+ EntityCollection(
+ self.context, WebPart, ResourcePath("webParts", self.resource_path)
+ ),
+ )
+
+ def get_property(self, name, default_value=None):
+ if default_value is None:
+ property_mapping = {
+ "canvasLayout": self.canvas_layout,
+ "webParts": self.web_parts,
+ }
+ default_value = property_mapping.get(name, None)
+ return super(SitePage, self).get_property(name, default_value)
diff --git a/office365/onedrive/sitepages/web_part.py b/office365/onedrive/sitepages/web_part.py
new file mode 100644
index 00000000..3b19bdc0
--- /dev/null
+++ b/office365/onedrive/sitepages/web_part.py
@@ -0,0 +1,5 @@
+from office365.entity import Entity
+
+
+class WebPart(Entity):
+ """Represents a specific web part instance on a SharePoint page."""
diff --git a/office365/outlook/mail/conversation.py b/office365/outlook/mail/conversation.py
index 333990df..53fa06dd 100644
--- a/office365/outlook/mail/conversation.py
+++ b/office365/outlook/mail/conversation.py
@@ -49,9 +49,7 @@ def topic(self):
@property
def unique_senders(self):
- """
- All the users that sent a message to this Conversation.
- """
+ """All the users that sent a message to this Conversation."""
return self.properties.get("uniqueSenders", StringCollection())
@property