Office365-REST-Python-Client 2.5.2__py3-none-any.whl → 2.5.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. {Office365_REST_Python_Client-2.5.2.dist-info → Office365_REST_Python_Client-2.5.4.dist-info}/METADATA +18 -5
  2. {Office365_REST_Python_Client-2.5.2.dist-info → Office365_REST_Python_Client-2.5.4.dist-info}/RECORD +135 -131
  3. office365/base_item.py +12 -20
  4. office365/communications/presences/presence.py +18 -7
  5. office365/delta_path.py +1 -1
  6. office365/directory/administrative_unit.py +6 -7
  7. office365/directory/applications/application.py +15 -13
  8. office365/directory/applications/template.py +5 -8
  9. office365/directory/audit/signins/signin.py +8 -12
  10. office365/directory/authentication/methods/details.py +8 -6
  11. office365/directory/authentication/methods/email.py +4 -4
  12. office365/directory/groups/lifecycle_policy.py +8 -7
  13. office365/directory/identities/provider.py +5 -6
  14. office365/directory/internal/paths/me.py +1 -1
  15. office365/directory/permissions/email_identity.py +7 -0
  16. office365/directory/protection/riskyusers/history_item.py +4 -3
  17. office365/directory/rolemanagement/role.py +5 -4
  18. office365/directory/rolemanagement/template.py +2 -6
  19. office365/directory/rolemanagement/unified_role_assignment.py +5 -4
  20. office365/directory/rolemanagement/unified_role_definition.py +6 -4
  21. office365/directory/serviceprincipals/service_principal.py +11 -6
  22. office365/directory/users/user.py +8 -11
  23. office365/entity.py +2 -2
  24. office365/entity_collection.py +11 -4
  25. office365/intune/devices/enrollment/configuration.py +6 -4
  26. office365/intune/devices/managed.py +9 -12
  27. office365/onedrive/analytics/item_activity_stat.py +4 -3
  28. office365/onedrive/columns/definition.py +9 -9
  29. office365/onedrive/documentsets/version.py +1 -3
  30. office365/onedrive/driveitems/driveItem.py +36 -29
  31. office365/onedrive/internal/paths/children.py +2 -2
  32. office365/onedrive/internal/paths/root.py +1 -1
  33. office365/onedrive/internal/paths/shared.py +11 -6
  34. office365/onedrive/internal/paths/site.py +3 -3
  35. office365/onedrive/internal/paths/url.py +2 -2
  36. office365/onedrive/listitems/list_item.py +2 -0
  37. office365/onedrive/lists/list.py +7 -4
  38. office365/onedrive/permissions/collection.py +26 -6
  39. office365/onedrive/sharepoint.py +1 -0
  40. office365/onedrive/shares/collection.py +2 -5
  41. office365/onedrive/shares/drive_item.py +5 -1
  42. office365/onedrive/termstore/groups/collection.py +3 -8
  43. office365/onedrive/termstore/groups/group.py +8 -0
  44. office365/onedrive/termstore/sets/collection.py +2 -6
  45. office365/onedrive/termstore/sets/name.py +5 -0
  46. office365/onedrive/termstore/sets/set.py +7 -0
  47. office365/onedrive/termstore/store.py +10 -13
  48. office365/onedrive/versions/drive_item.py +6 -8
  49. office365/onedrive/workbooks/functions/result.py +1 -1
  50. office365/onedrive/workbooks/names/collection.py +26 -0
  51. office365/onedrive/workbooks/names/named_item.py +23 -6
  52. office365/onedrive/workbooks/ranges/range.py +61 -14
  53. office365/onedrive/workbooks/ranges/view.py +1 -0
  54. office365/onedrive/workbooks/tables/table.py +11 -8
  55. office365/onedrive/workbooks/workbook.py +7 -11
  56. office365/onedrive/workbooks/worksheets/worksheet.py +5 -3
  57. office365/onenote/pages/collection.py +3 -2
  58. office365/onenote/resources/resource.py +5 -4
  59. office365/onenote/sectiongroups/section_group.py +10 -7
  60. office365/outlook/calendar/calendar.py +1 -1
  61. office365/outlook/calendar/schedule/information.py +0 -1
  62. office365/outlook/contacts/contact.py +3 -9
  63. office365/outlook/contacts/folder.py +3 -0
  64. office365/outlook/item.py +3 -4
  65. office365/outlook/mail/messages/message.py +25 -18
  66. office365/outlook/mail/recipient.py +3 -1
  67. office365/runtime/auth/authentication_context.py +6 -4
  68. office365/runtime/auth/providers/acs_token_provider.py +21 -15
  69. office365/runtime/auth/providers/saml_token_provider.py +5 -2
  70. office365/runtime/auth/sts_profile.py +5 -2
  71. office365/runtime/client_object.py +3 -11
  72. office365/runtime/client_object_collection.py +22 -20
  73. office365/runtime/client_result.py +1 -3
  74. office365/runtime/client_value_collection.py +2 -6
  75. office365/runtime/odata/json_format.py +1 -5
  76. office365/runtime/odata/query_options.py +1 -3
  77. office365/runtime/odata/request.py +8 -13
  78. office365/runtime/odata/type.py +2 -0
  79. office365/runtime/paths/appid.py +1 -1
  80. office365/runtime/{odata/url_builder.py → paths/builder.py} +24 -9
  81. office365/runtime/paths/item.py +1 -1
  82. office365/runtime/paths/resource_path.py +12 -16
  83. office365/runtime/paths/service_operation.py +8 -7
  84. office365/runtime/paths/v3/__init__.py +0 -0
  85. office365/runtime/paths/{key.py → v3/entity.py} +5 -5
  86. office365/runtime/paths/v4/__init__.py +0 -0
  87. office365/runtime/paths/v4/entity.py +35 -0
  88. office365/sharepoint/client_context.py +17 -10
  89. office365/sharepoint/contenttypes/content_type.py +6 -0
  90. office365/sharepoint/documentmanagement/document_set.py +4 -6
  91. office365/sharepoint/entity_collection.py +9 -0
  92. office365/sharepoint/features/feature.py +6 -8
  93. office365/sharepoint/files/checked_out_file.py +4 -2
  94. office365/sharepoint/files/checked_out_file_collection.py +1 -1
  95. office365/sharepoint/files/collection.py +35 -3
  96. office365/sharepoint/files/file.py +35 -11
  97. office365/sharepoint/files/versions/collection.py +4 -0
  98. office365/sharepoint/files/versions/event.py +6 -3
  99. office365/sharepoint/files/versions/version.py +6 -4
  100. office365/sharepoint/folders/collection.py +2 -2
  101. office365/sharepoint/folders/folder.py +5 -11
  102. office365/sharepoint/internal/paths/static_operation.py +9 -0
  103. office365/sharepoint/internal/paths/web.py +20 -0
  104. office365/sharepoint/listitems/collection.py +4 -0
  105. office365/sharepoint/listitems/listitem.py +19 -30
  106. office365/sharepoint/lists/list.py +44 -60
  107. office365/sharepoint/portal/groups/service.py +12 -16
  108. office365/sharepoint/portal/groups/site_manager.py +0 -1
  109. office365/sharepoint/publishing/pages/metadata.py +7 -2
  110. office365/sharepoint/publishing/pages/metadata_collection.py +0 -1
  111. office365/sharepoint/publishing/pages/page.py +3 -6
  112. office365/sharepoint/publishing/pages/reposts/repost.py +5 -9
  113. office365/sharepoint/recyclebin/item.py +11 -9
  114. office365/sharepoint/sharing/links/share_response.py +3 -0
  115. office365/sharepoint/sharing/result.py +18 -41
  116. office365/sharepoint/sites/site.py +46 -68
  117. office365/sharepoint/taxonomy/item.py +4 -2
  118. office365/sharepoint/taxonomy/stores/store.py +2 -6
  119. office365/sharepoint/tenant/administration/internal/permission_grant.py +7 -0
  120. office365/sharepoint/tenant/administration/sites/properties.py +55 -44
  121. office365/sharepoint/tenant/administration/tenant.py +25 -40
  122. office365/sharepoint/usercustomactions/collection.py +0 -1
  123. office365/sharepoint/webs/collection.py +8 -0
  124. office365/sharepoint/webs/template_collection.py +2 -4
  125. office365/sharepoint/webs/web.py +27 -24
  126. office365/teams/apps/app.py +1 -0
  127. office365/teams/collection.py +12 -16
  128. office365/teams/members/conversation_collection.py +1 -3
  129. office365/teams/operations/async_operation.py +3 -5
  130. office365/teams/schedule/groups/group.py +3 -0
  131. office365/teams/team.py +1 -1
  132. office365/todo/attachments/base.py +7 -9
  133. office365/runtime/odata/path_builder.py +0 -23
  134. office365/runtime/paths/entity.py +0 -34
  135. office365/sharepoint/internal/key_value.py +0 -28
  136. {Office365_REST_Python_Client-2.5.2.dist-info → Office365_REST_Python_Client-2.5.4.dist-info}/LICENSE +0 -0
  137. {Office365_REST_Python_Client-2.5.2.dist-info → Office365_REST_Python_Client-2.5.4.dist-info}/WHEEL +0 -0
  138. {Office365_REST_Python_Client-2.5.2.dist-info → Office365_REST_Python_Client-2.5.4.dist-info}/top_level.txt +0 -0
@@ -20,8 +20,12 @@ class WorkbookWorksheet(Entity):
20
20
  def __repr__(self):
21
21
  return self.name
22
22
 
23
+ def __str__(self):
24
+ return self.name
25
+
23
26
  @property
24
27
  def charts(self):
28
+ # type: () -> EntityCollection[WorkbookChart]
25
29
  """Returns collection of charts that are part of the worksheet"""
26
30
  return self.properties.get(
27
31
  "charts",
@@ -33,9 +37,7 @@ class WorkbookWorksheet(Entity):
33
37
  @property
34
38
  def name(self):
35
39
  # type: () -> Optional[str]
36
- """
37
- The display name of the worksheet.
38
- """
40
+ """The display name of the worksheet."""
39
41
  return self.properties.get("name", None)
40
42
 
41
43
  @property
@@ -1,3 +1,5 @@
1
+ from typing import IO
2
+
1
3
  from office365.entity_collection import EntityCollection
2
4
  from office365.onenote.internal.multipart_page_query import OneNotePageCreateQuery
3
5
  from office365.onenote.pages.page import OnenotePage
@@ -10,12 +12,11 @@ class OnenotePageCollection(EntityCollection[OnenotePage]):
10
12
  super(OnenotePageCollection, self).__init__(context, OnenotePage, resource_path)
11
13
 
12
14
  def add(self, presentation_file, attachment_files=None):
15
+ # type: (IO, dict) -> OnenotePage
13
16
  """
14
17
  Create a new OneNote page.
15
-
16
18
  :param typing.IO presentation_file: Presentation file
17
19
  :param dict or None attachment_files: Attachment files
18
- :rtype: OnenotePage
19
20
  """
20
21
  qry = OneNotePageCreateQuery(self, presentation_file, attachment_files)
21
22
  self.context.add_query(qry)
@@ -1,3 +1,5 @@
1
+ from typing import AnyStr, Optional
2
+
1
3
  from office365.onenote.entity_base_model import OnenoteEntityBaseModel
2
4
  from office365.runtime.client_result import ClientResult
3
5
  from office365.runtime.queries.function import FunctionQuery
@@ -7,6 +9,7 @@ class OnenoteResource(OnenoteEntityBaseModel):
7
9
  """An image or other file resource on a OneNote page."""
8
10
 
9
11
  def get_content(self):
12
+ # type: () -> ClientResult[AnyStr]
10
13
  """Retrieve the binary data of a file or image resource object."""
11
14
  return_type = ClientResult(self.context)
12
15
  qry = FunctionQuery(self, "content", None, return_type)
@@ -15,8 +18,6 @@ class OnenoteResource(OnenoteEntityBaseModel):
15
18
 
16
19
  @property
17
20
  def content_url(self):
18
- """The URL for downloading the content
19
-
20
- :rtype: str or None
21
- """
21
+ # type: () -> Optional[str]
22
+ """The URL for downloading the content"""
22
23
  return self.properties.get("contentUrl", None)
@@ -1,3 +1,5 @@
1
+ from typing import Optional
2
+
1
3
  from office365.entity_collection import EntityCollection
2
4
  from office365.onenote.entity_hierarchy_model import OnenoteEntityHierarchyModel
3
5
  from office365.onenote.notebooks.notebook import Notebook
@@ -10,22 +12,21 @@ class SectionGroup(OnenoteEntityHierarchyModel):
10
12
 
11
13
  @property
12
14
  def section_groups_url(self):
13
- """The URL for the sectionGroups navigation property, which returns all the section groups in the section group.
14
-
15
- :rtype: str or None
15
+ # type: () -> Optional[str]
16
+ """
17
+ The URL for the sectionGroups navigation property, which returns all the section groups in the section group.
16
18
  """
17
19
  return self.properties.get("sectionGroupsUrl", None)
18
20
 
19
21
  @property
20
22
  def sections_url(self):
21
- """The URL for the sections navigation property, which returns all the sections in the section group.
22
-
23
- :rtype: str or None
24
- """
23
+ # type: () -> Optional[str]
24
+ """The URL for the sections navigation property, which returns all the sections in the section group."""
25
25
  return self.properties.get("sectionsUrl", None)
26
26
 
27
27
  @property
28
28
  def parent_notebook(self):
29
+ # type: () -> Notebook
29
30
  """The notebook that contains the section group. Read-only."""
30
31
  return self.properties.get(
31
32
  "parentNotebook",
@@ -34,6 +35,7 @@ class SectionGroup(OnenoteEntityHierarchyModel):
34
35
 
35
36
  @property
36
37
  def sections(self):
38
+ # type: () -> EntityCollection[OnenoteSection]
37
39
  """The sections in the section group. Read-only. Nullable."""
38
40
  return self.properties.get(
39
41
  "sections",
@@ -46,6 +48,7 @@ class SectionGroup(OnenoteEntityHierarchyModel):
46
48
 
47
49
  @property
48
50
  def section_groups(self):
51
+ # type: () -> EntityCollection[SectionGroup]
49
52
  """Retrieve a list of onenoteSection objects from the specified notebook."""
50
53
  return self.properties.get(
51
54
  "sectionGroups",
@@ -28,7 +28,7 @@ class Calendar(Entity):
28
28
  """
29
29
 
30
30
  def __repr__(self):
31
- return self.name
31
+ return self.name or self.id or self.entity_type_name
32
32
 
33
33
  def allowed_calendar_sharing_roles(self, user):
34
34
  """
@@ -17,7 +17,6 @@ class ScheduleInformation(ClientValue):
17
17
  working_hours=WorkingHours(),
18
18
  ):
19
19
  """
20
-
21
20
  :param WorkingHours working_hours: The days of the week and hours in a specific time zone that the user works.
22
21
  These are set as part of the user's mailboxSettings.
23
22
  :param str error: Error information from attempting to get the availability of the user, distribution list,
@@ -45,25 +45,19 @@ class Contact(OutlookItem):
45
45
  @manager.setter
46
46
  def manager(self, value):
47
47
  # type: (str) -> None
48
- """
49
- Sets name of the contact's manager.
50
- """
48
+ """Sets name of the contact's manager."""
51
49
  self.set_property("manager", value)
52
50
 
53
51
  @property
54
52
  def mobile_phone(self):
55
53
  # type: () -> Optional[str]
56
- """
57
- The contact's mobile phone number.
58
- """
54
+ """The contact's mobile phone number."""
59
55
  return self.properties.get("mobilePhone", None)
60
56
 
61
57
  @mobile_phone.setter
62
58
  def mobile_phone(self, value):
63
59
  # type: (str) -> None
64
- """
65
- Sets contact's mobile phone number.
66
- """
60
+ """Sets contact's mobile phone number."""
67
61
  self.set_property("mobilePhone", value)
68
62
 
69
63
  @property
@@ -24,6 +24,7 @@ class ContactFolder(Entity):
24
24
 
25
25
  @property
26
26
  def child_folders(self):
27
+ # type: () -> EntityCollection["ContactFolder"]
27
28
  """The collection of child folders in the folder. Navigation property. Read-only. Nullable."""
28
29
  return self.properties.get(
29
30
  "childFolders",
@@ -36,6 +37,7 @@ class ContactFolder(Entity):
36
37
 
37
38
  @property
38
39
  def multi_value_extended_properties(self):
40
+ # type: () -> EntityCollection[MultiValueLegacyExtendedProperty]
39
41
  """The collection of multi-value extended properties defined for the Contact folder."""
40
42
  return self.properties.get(
41
43
  "multiValueExtendedProperties",
@@ -48,6 +50,7 @@ class ContactFolder(Entity):
48
50
 
49
51
  @property
50
52
  def single_value_extended_properties(self):
53
+ # type: () -> EntityCollection[SingleValueLegacyExtendedProperty]
51
54
  """The collection of single-value extended properties defined for the Contact folder."""
52
55
  return self.properties.get(
53
56
  "singleValueExtendedProperties",
office365/outlook/item.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import datetime
2
+ from typing import Optional
2
3
 
3
4
  from office365.entity import Entity
4
5
  from office365.runtime.types.collections import StringCollection
@@ -7,18 +8,16 @@ from office365.runtime.types.collections import StringCollection
7
8
  class OutlookItem(Entity):
8
9
  @property
9
10
  def change_key(self):
11
+ # type: () -> Optional[str]
10
12
  """
11
13
  Identifies the version of the item. Every time the item is changed, changeKey changes as well.
12
14
  This allows Exchange to apply changes to the correct version of the object.
13
- :rtype: str
14
15
  """
15
16
  return self.properties.get("ChangeKey", None)
16
17
 
17
18
  @property
18
19
  def categories(self):
19
- """
20
- The categories associated with the item
21
- """
20
+ """The categories associated with the item"""
22
21
  return self.properties.get("categories", StringCollection())
23
22
 
24
23
  @property
@@ -174,17 +174,30 @@ class Message(OutlookItem):
174
174
  self.context.add_query(qry)
175
175
  return self
176
176
 
177
- def move(self, destination_id):
177
+ def move(self, destination):
178
178
  """
179
179
  Move a message to another folder within the specified user's mailbox.
180
180
  This creates a new copy of the message in the destination folder and removes the original message.
181
181
 
182
- :param str destination_id: The destination folder ID, or a well-known folder name.
182
+ :param str or MailFolder destination: The destination folder ID, or a well-known folder name.
183
183
  For a list of supported well-known folder names, see mailFolder resource type.
184
184
  """
185
- payload = {"DestinationId": destination_id}
186
- qry = ServiceOperationQuery(self, "move", None, payload, None, None)
187
- self.context.add_query(qry)
185
+ from office365.outlook.mail.folders.folder import MailFolder
186
+
187
+ def _move(destination_id):
188
+ # type: (str) -> None
189
+ payload = {"DestinationId": destination_id}
190
+ qry = ServiceOperationQuery(self, "move", None, payload, None, None)
191
+ self.context.add_query(qry)
192
+
193
+ if isinstance(destination, MailFolder):
194
+
195
+ def _loaded():
196
+ _move(destination.id)
197
+
198
+ destination.ensure_property("id", _loaded)
199
+ else:
200
+ _move(destination)
188
201
  return self
189
202
 
190
203
  def forward(self, to_recipients, comment=""):
@@ -205,13 +218,12 @@ class Message(OutlookItem):
205
218
 
206
219
  @property
207
220
  def has_attachments(self):
221
+ # type: () -> Optional[bool]
208
222
  """
209
223
  Indicates whether the message has attachments. This property doesn't include inline attachments,
210
224
  so if a message contains only inline attachments, this property is false. To verify the existence
211
225
  of inline attachments, parse the body property to look for a src attribute,
212
226
  such as <IMG src="cid:image001.jpg@01D26CD8.6C05F070">.
213
-
214
- :rtype: bool or None
215
227
  """
216
228
  return self.properties.get("hasAttachments", None)
217
229
 
@@ -229,6 +241,7 @@ class Message(OutlookItem):
229
241
 
230
242
  @property
231
243
  def extensions(self):
244
+ # type: () -> EntityCollection[Extension]
232
245
  """The collection of open extensions defined for the message. Nullable."""
233
246
  return self.properties.get(
234
247
  "extensions",
@@ -253,24 +266,19 @@ class Message(OutlookItem):
253
266
  @property
254
267
  def body_preview(self):
255
268
  # type: () -> Optional[str]
256
- """
257
- The first 255 characters of the message body. It is in text format."""
269
+ """The first 255 characters of the message body. It is in text format."""
258
270
  return self.properties.get("bodyPreview", None)
259
271
 
260
272
  @property
261
273
  def conversation_id(self):
262
274
  # type: () -> Optional[str]
263
- """
264
- The ID of the conversation the email belongs to.
265
- """
275
+ """The ID of the conversation the email belongs to."""
266
276
  return self.properties.get("conversationId", None)
267
277
 
268
278
  @property
269
279
  def conversation_index(self):
270
280
  # type: () -> Optional[str]
271
- """
272
- Indicates the position of the message within the conversation.
273
- """
281
+ """Indicates the position of the message within the conversation."""
274
282
  return self.properties.get("conversationIndex", None)
275
283
 
276
284
  @property
@@ -292,9 +300,7 @@ class Message(OutlookItem):
292
300
  @property
293
301
  def importance(self):
294
302
  # type: () -> Optional[str]
295
- """
296
- The importance of the message.
297
- """
303
+ """The importance of the message."""
298
304
  return self.properties.get("importance", None)
299
305
 
300
306
  @property
@@ -308,6 +314,7 @@ class Message(OutlookItem):
308
314
 
309
315
  @property
310
316
  def internet_message_headers(self):
317
+ # type: () -> ClientValueCollection[InternetMessageHeader]
311
318
  """
312
319
  A collection of message headers defined by RFC5322. The set includes message headers indicating the network
313
320
  path taken by a message from the sender to the recipient. It can also contain custom message headers that
@@ -5,10 +5,12 @@ from office365.runtime.client_value import ClientValue
5
5
  class Recipient(ClientValue):
6
6
  """Represents information about a user in the sending or receiving end of an event, message or group post."""
7
7
 
8
- def __init__(self, email_address=EmailAddress()):
8
+ def __init__(self, email_address=None):
9
9
  """
10
10
  :param EmailAddress email_address: The recipient's email address.
11
11
  """
12
+ if email_address is None:
13
+ email_address = EmailAddress()
12
14
  super(Recipient, self).__init__()
13
15
  self.emailAddress = email_address
14
16
 
@@ -1,8 +1,8 @@
1
1
  import json
2
2
  import sys
3
- from typing import Any, Callable, TypedDict
3
+ from typing import Any, Callable
4
4
 
5
- from typing_extensions import Required
5
+ from typing_extensions import Required, TypedDict
6
6
 
7
7
  from office365.runtime.auth.client_credential import ClientCredential
8
8
  from office365.runtime.auth.providers.acs_token_provider import ACSTokenProvider
@@ -173,8 +173,9 @@ class AuthenticationContext(object):
173
173
  :param UserCredential or ClientCredential credentials:
174
174
  """
175
175
  if isinstance(credentials, ClientCredential):
176
+ environment = kwargs.get("environment")
176
177
  provider = ACSTokenProvider(
177
- self.url, credentials.clientId, credentials.clientSecret
178
+ self.url, credentials.clientId, credentials.clientSecret, environment
178
179
  )
179
180
  elif isinstance(credentials, UserCredential):
180
181
  allow_ntlm = kwargs.get("allow_ntlm", False)
@@ -184,8 +185,9 @@ class AuthenticationContext(object):
184
185
  provider = NtlmProvider(credentials.userName, credentials.password)
185
186
  else:
186
187
  browser_mode = kwargs.get("browser_mode", False)
188
+ environment = kwargs.get("environment")
187
189
  provider = SamlTokenProvider(
188
- self.url, credentials.userName, credentials.password, browser_mode
190
+ self.url, credentials.userName, credentials.password, browser_mode, environment
189
191
  )
190
192
  else:
191
193
  raise ValueError("Unknown credential type")
@@ -1,19 +1,24 @@
1
+ from typing import Optional
2
+
1
3
  import requests
2
4
 
3
5
  import office365.logger
4
6
  from office365.runtime.auth.authentication_provider import AuthenticationProvider
5
7
  from office365.runtime.auth.token_response import TokenResponse
6
8
  from office365.runtime.compat import urlparse
9
+ from office365.runtime.http.request_options import RequestOptions
7
10
 
8
11
 
9
12
  class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
10
- def __init__(self, url, client_id, client_secret):
13
+ def __init__(self, url, client_id, client_secret, environment='commercial'):
11
14
  """
12
15
  Provider to acquire the access token from a Microsoft Azure Access Control Service (ACS)
13
16
 
14
17
  :param str client_id: The OAuth client id of the calling application.
15
18
  :param str client_secret: Secret string that the application uses to prove its identity when requesting a token
16
19
  :param str url: SharePoint web or site url
20
+ :param str environment: The Office 365 Cloud Environment endpoint used for authentication
21
+ defaults to 'commercial'.
17
22
  """
18
23
  self.url = url
19
24
  self.redirect_url = None
@@ -22,11 +27,10 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
22
27
  self._client_id = client_id
23
28
  self._client_secret = client_secret
24
29
  self._cached_token = None
30
+ self._environment = environment
25
31
 
26
32
  def authenticate_request(self, request):
27
- """
28
- :type request: office365.runtime.http.request_options.RequestOptions
29
- """
33
+ # type: (RequestOptions) -> None
30
34
  self.ensure_app_only_access_token()
31
35
  request.set_header("Authorization", self._get_authorization_header())
32
36
 
@@ -36,9 +40,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
36
40
  return self._cached_token and self._cached_token.is_valid
37
41
 
38
42
  def get_app_only_access_token(self):
39
- """
40
- Retrieves an app-only access token from ACS
41
- """
43
+ """Retrieves an app-only access token from ACS"""
42
44
  try:
43
45
  realm = self._get_realm_from_target_url()
44
46
  url_info = urlparse(self.url)
@@ -63,7 +65,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
63
65
  self.SharePointPrincipal, target_host, target_realm
64
66
  )
65
67
  principal_id = self.get_formatted_principal(self._client_id, None, target_realm)
66
- sts_url = self.get_security_token_service_url(target_realm)
68
+ sts_url = self.get_security_token_service_url(target_realm, environment=self._environment)
67
69
  oauth2_request = {
68
70
  "grant_type": "client_credentials",
69
71
  "client_id": principal_id,
@@ -86,9 +88,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
86
88
 
87
89
  @staticmethod
88
90
  def process_realm_response(response):
89
- """
90
- :type response: requests.Response
91
- """
91
+ # type: (requests.Response) -> Optional[str]
92
92
  header_key = "WWW-Authenticate"
93
93
  if header_key in response.headers:
94
94
  auth_values = response.headers[header_key].split(",")
@@ -98,15 +98,21 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
98
98
 
99
99
  @staticmethod
100
100
  def get_formatted_principal(principal_name, host_name, realm):
101
+ # type: (str, Optional[str], str) -> str
101
102
  if host_name:
102
103
  return "{0}/{1}@{2}".format(principal_name, host_name, realm)
103
104
  return "{0}@{1}".format(principal_name, realm)
104
105
 
105
106
  @staticmethod
106
- def get_security_token_service_url(realm):
107
- return "https://accounts.accesscontrol.windows.net/{0}/tokens/OAuth/2".format(
108
- realm
109
- )
107
+ def get_security_token_service_url(realm, environment):
108
+ if environment == "GCCH":
109
+ return "https://login.microsoftonline.us/{0}/tokens/OAuth/2".format(
110
+ realm
111
+ )
112
+ else:
113
+ return "https://accounts.accesscontrol.windows.net/{0}/tokens/OAuth/2".format(
114
+ realm
115
+ )
110
116
 
111
117
  def _get_authorization_header(self):
112
118
  return "Bearer {0}".format(self._cached_token.accessToken)
@@ -40,7 +40,7 @@ def is_valid_auth_cookies(values):
40
40
 
41
41
 
42
42
  class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
43
- def __init__(self, url, username, password, browser_mode):
43
+ def __init__(self, url, username, password, browser_mode, environment='commercial'):
44
44
  """
45
45
  SAML Security Token Service provider (claims-based authentication)
46
46
 
@@ -48,11 +48,14 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
48
48
  :param str username: Typically a UPN in the form of an email address
49
49
  :param str password: The password
50
50
  :param bool browser_mode:
51
+ :param str environment: The Office 365 Cloud Environment endpoint used for authentication.
52
+ By default, this will be set to commercial ('commercial', 'GCCH')
51
53
  """
52
54
  # Security Token Service info
53
- self._sts_profile = STSProfile(resolve_base_url(url))
55
+ self._sts_profile = STSProfile(resolve_base_url(url), environment)
54
56
  # Obtain authentication cookies, using the browser mode
55
57
  self._browser_mode = browser_mode
58
+ self._environment = environment
56
59
  # Last occurred error
57
60
  self.error = ""
58
61
  self._username = username
@@ -4,13 +4,16 @@ from office365.runtime.compat import timezone, urlparse
4
4
 
5
5
 
6
6
  class STSProfile(object):
7
- def __init__(self, authority_url):
7
+ def __init__(self, authority_url, environment):
8
8
  """
9
9
 
10
10
  :type authority_url: str
11
11
  """
12
12
  self.authorityUrl = authority_url
13
- self.serviceUrl = "https://login.microsoftonline.com"
13
+ if environment == "GCCH":
14
+ self.serviceUrl = "https://login.microsoftonline.us"
15
+ else:
16
+ self.serviceUrl = "https://login.microsoftonline.com"
14
17
  self.securityTokenServicePath = "extSTS.srf"
15
18
  self.userRealmServicePath = "GetUserRealm.srf"
16
19
  self.tokenIssuer = "urn:federation:MicrosoftOnline"
@@ -90,7 +90,6 @@ class ClientObject(Generic[T]):
90
90
  def is_property_available(self, name):
91
91
  # type: (str) -> bool
92
92
  """Returns a Boolean value that indicates whether the specified property has been retrieved or set.
93
-
94
93
  :param str name: A property name
95
94
  """
96
95
  if name in self.properties:
@@ -116,7 +115,7 @@ class ClientObject(Generic[T]):
116
115
 
117
116
  def remove_from_parent_collection(self):
118
117
  if self._parent_collection is None:
119
- return
118
+ return self
120
119
  self._parent_collection.remove_child(self)
121
120
  return self
122
121
 
@@ -174,19 +173,12 @@ class ClientObject(Generic[T]):
174
173
 
175
174
  def ensure_property(self, name, action, *args, **kwargs):
176
175
  # type: (str, Callable[[], None], Any, Any) -> Self
177
- """
178
- Ensures if property is loaded
179
-
180
- :type action: () -> None
181
- :type name: str
182
- """
176
+ """Ensures if property is loaded"""
183
177
  return self.ensure_properties([name], action, *args, **kwargs)
184
178
 
185
179
  def ensure_properties(self, names, action, *args, **kwargs):
186
180
  # type: (List[str], Callable[[Any, Any], None], Any, Any) -> Self
187
- """
188
- Ensure if list of properties are retrieved from the server
189
- """
181
+ """Ensure if list of properties are retrieved from the server"""
190
182
  if self.property_ref_name is not None and self.property_ref_name not in names:
191
183
  names.append(self.property_ref_name)
192
184