Office365-REST-Python-Client 2.5.1__py3-none-any.whl → 2.5.3__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 (271) hide show
  1. {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/METADATA +6 -6
  2. {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/RECORD +265 -259
  3. office365/base_item.py +12 -20
  4. office365/communications/onlinemeetings/collection.py +1 -1
  5. office365/communications/onlinemeetings/online_meeting.py +20 -35
  6. office365/communications/presences/presence.py +18 -7
  7. office365/delta_collection.py +10 -1
  8. office365/delta_path.py +1 -1
  9. office365/directory/administrative_unit.py +6 -7
  10. office365/directory/applications/application.py +24 -18
  11. office365/directory/applications/roles/assignment.py +13 -1
  12. office365/directory/applications/roles/collection.py +13 -0
  13. office365/directory/applications/roles/role.py +6 -1
  14. office365/directory/audit/directory.py +8 -7
  15. office365/directory/audit/log_root.py +3 -0
  16. office365/directory/audit/signins/signin.py +19 -29
  17. office365/directory/authentication/authentication.py +1 -0
  18. office365/directory/authentication/methods/details.py +8 -6
  19. office365/directory/authentication/methods/phone.py +3 -1
  20. office365/directory/extensions/extension_property.py +7 -9
  21. office365/directory/groups/collection.py +10 -3
  22. office365/directory/groups/group.py +19 -19
  23. office365/directory/groups/lifecycle_policy.py +8 -7
  24. office365/directory/identities/provider.py +5 -6
  25. office365/directory/insights/usage_details.py +8 -3
  26. office365/directory/internal/paths/me.py +1 -1
  27. office365/directory/invitations/collection.py +1 -1
  28. office365/directory/invitations/invitation.py +6 -6
  29. office365/directory/object_collection.py +2 -3
  30. office365/directory/permissions/email_identity.py +7 -0
  31. office365/directory/permissions/grants/resource_specific.py +10 -9
  32. office365/directory/permissions/identity.py +3 -0
  33. office365/directory/permissions/identity_set.py +3 -0
  34. office365/directory/policies/base.py +4 -4
  35. office365/directory/policies/root.py +6 -4
  36. office365/directory/protection/information.py +3 -3
  37. office365/directory/rolemanagement/application.py +2 -0
  38. office365/directory/rolemanagement/role.py +11 -10
  39. office365/directory/rolemanagement/template.py +9 -8
  40. office365/directory/rolemanagement/unified_role_assignment.py +5 -4
  41. office365/directory/rolemanagement/unified_role_definition.py +6 -4
  42. office365/directory/security/security.py +3 -0
  43. office365/directory/serviceprincipals/collection.py +20 -4
  44. office365/directory/serviceprincipals/service_principal.py +79 -12
  45. office365/directory/users/activities/activity.py +5 -4
  46. office365/directory/users/user.py +29 -34
  47. office365/entity.py +2 -2
  48. office365/entity_collection.py +12 -5
  49. office365/graph_client.py +90 -8
  50. office365/intune/audit/event.py +4 -3
  51. office365/intune/devices/enrollment/configuration.py +6 -4
  52. office365/intune/devices/managed.py +9 -12
  53. office365/onedrive/analytics/item_activity_stat.py +4 -3
  54. office365/onedrive/columns/column_link.py +4 -4
  55. office365/onedrive/columns/definition.py +29 -32
  56. office365/onedrive/columns/definition_collection.py +1 -1
  57. office365/onedrive/contenttypes/content_type.py +16 -18
  58. office365/onedrive/documentsets/version.py +7 -3
  59. office365/onedrive/driveitems/driveItem.py +48 -49
  60. office365/onedrive/drives/drive.py +7 -2
  61. office365/onedrive/internal/paths/children.py +2 -2
  62. office365/onedrive/internal/paths/root.py +1 -1
  63. office365/onedrive/internal/paths/shared.py +1 -1
  64. office365/onedrive/internal/paths/site.py +3 -3
  65. office365/onedrive/internal/paths/url.py +2 -2
  66. office365/onedrive/listitems/list_item.py +2 -0
  67. office365/onedrive/lists/list.py +7 -4
  68. office365/onedrive/permissions/collection.py +28 -7
  69. office365/onedrive/permissions/permission.py +5 -7
  70. office365/onedrive/permissions/sharing_link.py +1 -1
  71. office365/onedrive/sharepoint.py +1 -0
  72. office365/onedrive/shares/collection.py +2 -5
  73. office365/onedrive/shares/drive_item.py +4 -0
  74. office365/onedrive/sites/site.py +6 -0
  75. office365/onedrive/termstore/groups/collection.py +3 -8
  76. office365/onedrive/termstore/groups/group.py +8 -0
  77. office365/onedrive/termstore/sets/collection.py +2 -6
  78. office365/onedrive/termstore/sets/name.py +5 -0
  79. office365/onedrive/termstore/sets/set.py +7 -0
  80. office365/onedrive/termstore/store.py +10 -13
  81. office365/onedrive/versions/drive_item.py +3 -1
  82. office365/onedrive/workbooks/ranges/range.py +9 -13
  83. office365/onedrive/workbooks/ranges/view.py +1 -0
  84. office365/onedrive/workbooks/tables/rows/row.py +3 -0
  85. office365/onedrive/workbooks/tables/table.py +7 -4
  86. office365/onedrive/workbooks/worksheets/worksheet.py +12 -4
  87. office365/onenote/entity_hierarchy_model.py +4 -0
  88. office365/onenote/internal/multipart_page_query.py +4 -5
  89. office365/onenote/notebooks/notebook.py +4 -0
  90. office365/onenote/pages/collection.py +3 -2
  91. office365/onenote/resources/resource.py +5 -4
  92. office365/onenote/sectiongroups/section_group.py +10 -7
  93. office365/onenote/sections/section.py +1 -1
  94. office365/outlook/calendar/attendees/base.py +2 -1
  95. office365/outlook/calendar/calendar.py +18 -10
  96. office365/outlook/calendar/events/collection.py +0 -2
  97. office365/outlook/calendar/group.py +7 -8
  98. office365/outlook/calendar/meetingtimes/suggestion.py +8 -4
  99. office365/outlook/calendar/meetingtimes/time_slot.py +3 -0
  100. office365/outlook/calendar/permissions/collection.py +1 -1
  101. office365/outlook/calendar/rooms/__init__.py +0 -0
  102. office365/outlook/calendar/rooms/list.py +27 -0
  103. office365/outlook/calendar/rooms/room.py +8 -0
  104. office365/outlook/calendar/schedule/information.py +0 -1
  105. office365/outlook/contacts/collection.py +0 -8
  106. office365/outlook/contacts/contact.py +14 -14
  107. office365/outlook/contacts/folder.py +3 -0
  108. office365/outlook/mail/attachments/attachment.py +31 -31
  109. office365/outlook/mail/attachments/collection.py +34 -6
  110. office365/outlook/mail/conversation.py +6 -4
  111. office365/outlook/mail/folders/collection.py +0 -7
  112. office365/outlook/mail/folders/folder.py +50 -18
  113. office365/outlook/mail/messages/collection.py +0 -1
  114. office365/outlook/mail/messages/message.py +58 -68
  115. office365/outlook/mail/physical_address.py +11 -5
  116. office365/outlook/mail/recipient.py +3 -1
  117. office365/outlook/mail/recurrence_range.py +14 -6
  118. office365/outlook/user.py +1 -0
  119. office365/planner/planner.py +9 -12
  120. office365/planner/plans/collection.py +17 -18
  121. office365/planner/plans/container.py +11 -0
  122. office365/planner/plans/plan.py +21 -10
  123. office365/runtime/auth/authentication_context.py +3 -3
  124. office365/runtime/auth/providers/acs_token_provider.py +7 -9
  125. office365/runtime/auth/providers/saml_token_provider.py +5 -2
  126. office365/runtime/client_object.py +6 -15
  127. office365/runtime/client_object_collection.py +36 -35
  128. office365/runtime/client_result.py +6 -7
  129. office365/runtime/client_runtime_context.py +10 -16
  130. office365/runtime/client_value_collection.py +3 -10
  131. office365/runtime/compat.py +2 -0
  132. office365/runtime/odata/query_options.py +1 -3
  133. office365/runtime/odata/reader.py +1 -1
  134. office365/runtime/odata/request.py +2 -4
  135. office365/runtime/odata/type.py +17 -0
  136. office365/runtime/odata/v4/upload_session_request.py +27 -30
  137. office365/runtime/paths/appid.py +1 -1
  138. office365/runtime/{odata/url_builder.py → paths/builder.py} +24 -9
  139. office365/runtime/paths/item.py +3 -1
  140. office365/runtime/paths/resource_path.py +12 -16
  141. office365/runtime/paths/service_operation.py +8 -7
  142. office365/runtime/paths/v3/__init__.py +0 -0
  143. office365/runtime/paths/{key.py → v3/entity.py} +5 -5
  144. office365/runtime/paths/v4/__init__.py +0 -0
  145. office365/runtime/paths/{entity.py → v4/entity.py} +13 -11
  146. office365/runtime/queries/function.py +1 -1
  147. office365/runtime/types/event_handler.py +1 -3
  148. office365/search/entity.py +15 -8
  149. office365/search/external/external.py +1 -0
  150. office365/search/sort_property.py +3 -0
  151. office365/sharepoint/attachments/attachment.py +3 -1
  152. office365/sharepoint/attachments/collection.py +3 -0
  153. office365/sharepoint/changes/change.py +12 -1
  154. office365/sharepoint/changes/collection.py +1 -1
  155. office365/sharepoint/changes/list.py +3 -0
  156. office365/sharepoint/changes/token.py +4 -0
  157. office365/sharepoint/changes/type.py +23 -23
  158. office365/sharepoint/changes/web.py +7 -3
  159. office365/sharepoint/client_context.py +21 -18
  160. office365/sharepoint/clientsidecomponent/hostedapps/manager.py +3 -3
  161. office365/sharepoint/contenttypes/content_type.py +47 -56
  162. office365/sharepoint/contenttypes/content_type_id.py +1 -1
  163. office365/sharepoint/documentmanagement/document_id.py +2 -2
  164. office365/sharepoint/documentmanagement/document_set.py +6 -7
  165. office365/sharepoint/entity_collection.py +9 -0
  166. office365/sharepoint/features/feature.py +6 -8
  167. office365/sharepoint/fields/collection.py +6 -5
  168. office365/sharepoint/fields/field.py +28 -46
  169. office365/sharepoint/fields/related_field_collection.py +1 -1
  170. office365/sharepoint/fields/user_value.py +3 -3
  171. office365/sharepoint/files/checked_out_file.py +4 -2
  172. office365/sharepoint/files/checked_out_file_collection.py +1 -1
  173. office365/sharepoint/files/collection.py +84 -14
  174. office365/sharepoint/files/file.py +118 -110
  175. office365/sharepoint/files/versions/collection.py +5 -3
  176. office365/sharepoint/files/versions/event.py +6 -3
  177. office365/sharepoint/files/versions/version.py +31 -18
  178. office365/sharepoint/folders/collection.py +5 -10
  179. office365/sharepoint/folders/folder.py +41 -24
  180. office365/sharepoint/forms/collection.py +1 -1
  181. office365/sharepoint/forms/form.py +4 -4
  182. office365/sharepoint/internal/paths/static_operation.py +9 -0
  183. office365/sharepoint/internal/paths/web.py +20 -0
  184. office365/sharepoint/listitems/collection.py +4 -0
  185. office365/sharepoint/listitems/listitem.py +37 -38
  186. office365/sharepoint/listitems/versions/collection.py +1 -1
  187. office365/sharepoint/listitems/versions/version.py +18 -11
  188. office365/sharepoint/lists/collection.py +1 -2
  189. office365/sharepoint/lists/list.py +106 -153
  190. office365/sharepoint/marketplace/app_metadata_collection.py +3 -1
  191. office365/sharepoint/navigation/node.py +16 -15
  192. office365/sharepoint/navigation/node_collection.py +9 -3
  193. office365/sharepoint/permissions/base_permissions.py +11 -6
  194. office365/sharepoint/permissions/roles/assignments/collection.py +8 -12
  195. office365/sharepoint/permissions/roles/definitions/definition.py +3 -1
  196. office365/sharepoint/permissions/securable_object.py +38 -31
  197. office365/sharepoint/portal/groups/service.py +12 -16
  198. office365/sharepoint/portal/groups/site_manager.py +0 -1
  199. office365/sharepoint/principal/groups/group.py +24 -30
  200. office365/sharepoint/principal/principal.py +21 -19
  201. office365/sharepoint/principal/users/collection.py +5 -0
  202. office365/sharepoint/principal/users/user.py +20 -26
  203. office365/sharepoint/publishing/pages/collection.py +1 -4
  204. office365/sharepoint/publishing/pages/metadata.py +38 -51
  205. office365/sharepoint/publishing/pages/metadata_collection.py +5 -2
  206. office365/sharepoint/publishing/pages/page.py +12 -21
  207. office365/sharepoint/publishing/pages/reposts/repost.py +5 -9
  208. office365/sharepoint/publishing/pages/service.py +36 -49
  209. office365/sharepoint/pushnotifications/collection.py +3 -1
  210. office365/sharepoint/recyclebin/item.py +11 -9
  211. office365/sharepoint/recyclebin/item_collection.py +1 -1
  212. office365/sharepoint/search/service.py +8 -6
  213. office365/sharepoint/sharing/links/info.py +5 -2
  214. office365/sharepoint/sharing/links/share_response.py +3 -0
  215. office365/sharepoint/sharing/links/share_settings.py +3 -0
  216. office365/sharepoint/sharing/object_sharing_information.py +25 -19
  217. office365/sharepoint/sharing/object_sharing_information_user.py +10 -19
  218. office365/sharepoint/sharing/result.py +18 -41
  219. office365/sharepoint/sharing/role.py +20 -0
  220. office365/sharepoint/sharing/role_type.py +1 -0
  221. office365/sharepoint/sharing/user_sharing_result.py +12 -0
  222. office365/sharepoint/sites/language.py +6 -0
  223. office365/sharepoint/sites/language_collection.py +3 -0
  224. office365/sharepoint/sites/site.py +65 -86
  225. office365/sharepoint/storagemetrics/storage_metrics.py +5 -6
  226. office365/sharepoint/taxonomy/item.py +11 -10
  227. office365/sharepoint/taxonomy/stores/store.py +8 -8
  228. office365/sharepoint/taxonomy/terms/label.py +3 -0
  229. office365/sharepoint/taxonomy/terms/term.py +31 -0
  230. office365/sharepoint/tenant/administration/collaboration/insights_overview.py +10 -0
  231. office365/sharepoint/tenant/administration/hubsites/collection.py +1 -2
  232. office365/sharepoint/tenant/administration/hubsites/hub_site.py +20 -24
  233. office365/sharepoint/tenant/administration/internal/permission_grant.py +7 -0
  234. office365/sharepoint/tenant/administration/sites/properties.py +55 -44
  235. office365/sharepoint/tenant/administration/tenant.py +69 -69
  236. office365/sharepoint/types/resource_path.py +2 -2
  237. office365/sharepoint/ui/applicationpages/peoplepicker/query_parameters.py +1 -1
  238. office365/sharepoint/usercustomactions/collection.py +1 -2
  239. office365/sharepoint/userprofiles/my_site_links.py +4 -4
  240. office365/sharepoint/userprofiles/people_manager.py +1 -3
  241. office365/sharepoint/userprofiles/user_profile.py +9 -11
  242. office365/sharepoint/utilities/principal_info.py +12 -0
  243. office365/sharepoint/viva/employee_engagement.py +1 -1
  244. office365/sharepoint/webparts/definition_collection.py +1 -1
  245. office365/sharepoint/webs/collection.py +8 -0
  246. office365/sharepoint/webs/template_collection.py +3 -5
  247. office365/sharepoint/webs/web.py +75 -95
  248. office365/subscriptions/collection.py +1 -1
  249. office365/subscriptions/subscription.py +13 -11
  250. office365/teams/apps/app.py +1 -0
  251. office365/teams/channels/channel.py +1 -3
  252. office365/teams/collection.py +12 -16
  253. office365/teams/info.py +7 -4
  254. office365/teams/members/conversation_collection.py +1 -3
  255. office365/teams/operations/async_operation.py +3 -5
  256. office365/teams/schedule/groups/group.py +3 -0
  257. office365/teams/team.py +18 -20
  258. office365/todo/attachments/base.py +7 -9
  259. office365/todo/linked_resource.py +6 -6
  260. office365/todo/tasks/list.py +1 -0
  261. office365/todo/tasks/task.py +3 -0
  262. office365/onedrive/internal/queries/resumable_file_upload.py +0 -36
  263. office365/outlook/internal/queries/attachment_upload.py +0 -53
  264. office365/runtime/odata/path_builder.py +0 -23
  265. office365/sharepoint/internal/key_value.py +0 -28
  266. office365/sharepoint/internal/queries/create_file.py +0 -20
  267. office365/sharepoint/internal/queries/upload_session.py +0 -103
  268. {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/LICENSE +0 -0
  269. {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/WHEEL +0 -0
  270. {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/top_level.txt +0 -0
  271. /office365/planner/plans/{plan_details.py → details.py} +0 -0
@@ -1,43 +1,42 @@
1
- from office365.directory.users.user import User
1
+ from office365.directory.groups.group import Group
2
2
  from office365.entity_collection import EntityCollection
3
3
  from office365.planner.plans.plan import PlannerPlan
4
4
  from office365.runtime.queries.create_entity import CreateEntityQuery
5
5
 
6
6
 
7
- class PlannerPlanCollection(EntityCollection):
7
+ class PlannerPlanCollection(EntityCollection[PlannerPlan]):
8
8
  def __init__(self, context, resource_path=None):
9
9
  super(PlannerPlanCollection, self).__init__(context, PlannerPlan, resource_path)
10
10
 
11
- def add(self, title, owner=None):
12
- """
13
- Creates a new plannerPlan.
14
-
15
- :param str title: Planner name
16
- :param str or office365.directory.users.user.User owner: Planner owner
11
+ def add(self, title, container):
12
+ # type: (str, str|Group) -> PlannerPlan
13
+ """Creates a new plannerPlan.
14
+ :param str title: Plan title
15
+ :param str or Group container: Identifies the container of the plan.
17
16
  """
18
17
  return_type = PlannerPlan(self.context)
19
18
  self.add_child(return_type)
20
19
 
21
- def _create_query(owner_id):
20
+ def _add(owner_id):
21
+ # type: (str) -> None
22
22
  payload = {
23
23
  "title": title,
24
- "owner": {
25
- "@odata.id": "https://graph.microsoft.com/v1.0/users/{0}".format(
24
+ "container": {
25
+ "url": "https://graph.microsoft.com/v1.0/groups/{0}".format(
26
26
  owner_id
27
27
  )
28
28
  },
29
29
  }
30
- return CreateEntityQuery(self, payload, return_type)
30
+ qry = CreateEntityQuery(self, payload, return_type)
31
+ self.context.add_query(qry)
31
32
 
32
- if isinstance(owner, User):
33
+ if isinstance(container, Group):
33
34
 
34
35
  def _owner_loaded():
35
- next_qry = _create_query(owner.id)
36
- self.context.add_query(next_qry)
36
+ _add(container.id)
37
37
 
38
- owner.ensure_property("id", _owner_loaded)
38
+ container.ensure_property("id", _owner_loaded)
39
39
  else:
40
- qry = _create_query(owner)
41
- self.context.add_query(qry)
40
+ _add(container)
42
41
 
43
42
  return return_type
@@ -0,0 +1,11 @@
1
+ from office365.runtime.client_value import ClientValue
2
+
3
+
4
+ class PlannerPlanContainer(ClientValue):
5
+ """
6
+ Represents a container for a plannerPlan. The container is a resource that specifies authorization rules and the
7
+ lifetime of the plan. This means that only the people who are authorized to work with the resource containing
8
+ the plan will be able to work with the plan and the tasks within it. When the containing resource is deleted,
9
+ the contained plans are also deleted. The properties of the plannerPlanContainer cannot be changed after the plan
10
+ is created.
11
+ """
@@ -1,8 +1,11 @@
1
+ from typing import Optional
2
+
1
3
  from office365.directory.permissions.identity_set import IdentitySet
2
4
  from office365.entity import Entity
3
5
  from office365.entity_collection import EntityCollection
4
6
  from office365.planner.buckets.bucket import PlannerBucket
5
- from office365.planner.plans.plan_details import PlannerPlanDetails
7
+ from office365.planner.plans.container import PlannerPlanContainer
8
+ from office365.planner.plans.details import PlannerPlanDetails
6
9
  from office365.planner.tasks.task import PlannerTask
7
10
  from office365.runtime.paths.resource_path import ResourcePath
8
11
 
@@ -14,8 +17,20 @@ class PlannerPlan(Entity):
14
17
  For more information about the relationships between groups, plans, and tasks, see Planner.
15
18
  """
16
19
 
20
+ def __str__(self):
21
+ return self.title
22
+
23
+ def __repr__(self):
24
+ return self.id or self.entity_type_name
25
+
26
+ @property
27
+ def container(self):
28
+ """Identity of the user, device, or application which created the plan."""
29
+ return self.properties.get("container", PlannerPlanContainer())
30
+
17
31
  @property
18
32
  def title(self):
33
+ # type: () -> Optional[str]
19
34
  """Required. Title of the plan."""
20
35
  return self.properties.get("title", None)
21
36
 
@@ -26,9 +41,8 @@ class PlannerPlan(Entity):
26
41
 
27
42
  @property
28
43
  def buckets(self):
29
- """
30
- Read-only. Nullable. Collection of buckets in the plan.
31
- """
44
+ # type: () -> EntityCollection[PlannerBucket]
45
+ """Collection of buckets in the plan."""
32
46
  return self.properties.get(
33
47
  "buckets",
34
48
  EntityCollection(
@@ -38,9 +52,7 @@ class PlannerPlan(Entity):
38
52
 
39
53
  @property
40
54
  def details(self):
41
- """
42
- Read-only. Nullable. Additional details about the plan.
43
- """
55
+ """Additional details about the plan."""
44
56
  return self.properties.get(
45
57
  "details",
46
58
  PlannerPlanDetails(
@@ -50,9 +62,8 @@ class PlannerPlan(Entity):
50
62
 
51
63
  @property
52
64
  def tasks(self):
53
- """
54
- Read-only. Nullable. Collection of tasks in the plan.
55
- """
65
+ # type: () -> EntityCollection[PlannerTask]
66
+ """Collection of tasks in the plan."""
56
67
  return self.properties.get(
57
68
  "tasks",
58
69
  EntityCollection(
@@ -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
@@ -65,7 +65,7 @@ class AuthenticationContext(object):
65
65
  "Private key is missing. Use either 'cert_path' or 'private_key' to pass the value"
66
66
  )
67
67
  elif cert_path is not None:
68
- with open(cert_path, "r") as f:
68
+ with open(cert_path, "r", encoding="utf8") as f:
69
69
  private_key = f.read()
70
70
 
71
71
  def _acquire_token():
@@ -1,9 +1,12 @@
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):
@@ -24,9 +27,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
24
27
  self._cached_token = None
25
28
 
26
29
  def authenticate_request(self, request):
27
- """
28
- :type request: office365.runtime.http.request_options.RequestOptions
29
- """
30
+ # type: (RequestOptions) -> None
30
31
  self.ensure_app_only_access_token()
31
32
  request.set_header("Authorization", self._get_authorization_header())
32
33
 
@@ -36,9 +37,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
36
37
  return self._cached_token and self._cached_token.is_valid
37
38
 
38
39
  def get_app_only_access_token(self):
39
- """
40
- Retrieves an app-only access token from ACS
41
- """
40
+ """Retrieves an app-only access token from ACS"""
42
41
  try:
43
42
  realm = self._get_realm_from_target_url()
44
43
  url_info = urlparse(self.url)
@@ -86,9 +85,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
86
85
 
87
86
  @staticmethod
88
87
  def process_realm_response(response):
89
- """
90
- :type response: requests.Response
91
- """
88
+ # type: (requests.Response) -> Optional[str]
92
89
  header_key = "WWW-Authenticate"
93
90
  if header_key in response.headers:
94
91
  auth_values = response.headers[header_key].split(",")
@@ -98,6 +95,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
98
95
 
99
96
  @staticmethod
100
97
  def get_formatted_principal(principal_name, host_name, realm):
98
+ # type: (str, Optional[str], str) -> str
101
99
  if host_name:
102
100
  return "{0}/{1}@{2}".format(principal_name, host_name, realm)
103
101
  return "{0}@{1}".format(principal_name, realm)
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  import uuid
3
- import xml.dom.minidom as minidom
3
+ from xml.dom import minidom
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  import requests
@@ -314,7 +314,10 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
314
314
  """Construct the request body to acquire security token from STS endpoint"""
315
315
  logger = SamlTokenProvider.logger()
316
316
  logger.debug_secrets("params: %s", params)
317
- f = open(os.path.join(os.path.dirname(__file__), "templates", template_name))
317
+ f = open(
318
+ os.path.join(os.path.dirname(__file__), "templates", template_name),
319
+ encoding="utf8",
320
+ )
318
321
  try:
319
322
  data = f.read()
320
323
  for key in params:
@@ -74,6 +74,7 @@ class ClientObject(Generic[T]):
74
74
  return self
75
75
 
76
76
  def after_execute(self, action, *args, **kwargs):
77
+ # type: (Callable[[Self, Any, Any], None], Any, Any) -> Self
77
78
  """
78
79
  Attach an event handler to client object which gets triggered after query is submitted to server
79
80
  """
@@ -89,7 +90,6 @@ class ClientObject(Generic[T]):
89
90
  def is_property_available(self, name):
90
91
  # type: (str) -> bool
91
92
  """Returns a Boolean value that indicates whether the specified property has been retrieved or set.
92
-
93
93
  :param str name: A property name
94
94
  """
95
95
  if name in self.properties:
@@ -115,7 +115,7 @@ class ClientObject(Generic[T]):
115
115
 
116
116
  def remove_from_parent_collection(self):
117
117
  if self._parent_collection is None:
118
- return
118
+ return self
119
119
  self._parent_collection.remove_child(self)
120
120
  return self
121
121
 
@@ -149,9 +149,7 @@ class ClientObject(Generic[T]):
149
149
  self._ser_property_names.append(name)
150
150
 
151
151
  typed_value = self.get_property(name)
152
- if isinstance(typed_value, ClientObject) or isinstance(
153
- typed_value, ClientValue
154
- ):
152
+ if isinstance(typed_value, (ClientObject, ClientValue)):
155
153
  if isinstance(value, list):
156
154
  [
157
155
  typed_value.set_property(i, v, persist_changes)
@@ -175,19 +173,12 @@ class ClientObject(Generic[T]):
175
173
 
176
174
  def ensure_property(self, name, action, *args, **kwargs):
177
175
  # type: (str, Callable[[], None], Any, Any) -> Self
178
- """
179
- Ensures if property is loaded
180
-
181
- :type action: () -> None
182
- :type name: str
183
- """
176
+ """Ensures if property is loaded"""
184
177
  return self.ensure_properties([name], action, *args, **kwargs)
185
178
 
186
179
  def ensure_properties(self, names, action, *args, **kwargs):
187
180
  # type: (List[str], Callable[[Any, Any], None], Any, Any) -> Self
188
- """
189
- Ensure if list of properties are retrieved from the server
190
- """
181
+ """Ensure if list of properties are retrieved from the server"""
191
182
  if self.property_ref_name is not None and self.property_ref_name not in names:
192
183
  names.append(self.property_ref_name)
193
184
 
@@ -260,7 +251,7 @@ class ClientObject(Generic[T]):
260
251
  k: self.get_property(k) for k in self._properties if k in ser_prop_names
261
252
  }
262
253
  for k, v in json.items():
263
- if isinstance(v, ClientObject) or isinstance(v, ClientValue):
254
+ if isinstance(v, (ClientObject, ClientValue)):
264
255
  json[k] = v.to_json(json_format)
265
256
 
266
257
  if json and include_control_info:
@@ -1,4 +1,4 @@
1
- from typing import Callable, Generic, Iterator, List, Optional, Type, TypeVar
1
+ from typing import Any, Callable, Generic, Iterator, List, Optional, Type, TypeVar
2
2
 
3
3
  from typing_extensions import Self
4
4
 
@@ -40,6 +40,8 @@ class ClientObjectCollection(ClientObject, Generic[T]):
40
40
  raise AttributeError(
41
41
  "No class model for entity type '{0}' was found".format(self._item_type)
42
42
  )
43
+ if resource_path is None:
44
+ resource_path = ResourcePath(None, self.resource_path)
43
45
  client_object = self._item_type(
44
46
  context=self.context, resource_path=resource_path
45
47
  ) # type: T
@@ -66,11 +68,7 @@ class ClientObjectCollection(ClientObject, Generic[T]):
66
68
 
67
69
  def add_child(self, client_object):
68
70
  # type: (T) -> Self
69
- """
70
- Adds client object into collection
71
-
72
- :type client_object: ClientObject
73
- """
71
+ """Adds client object into collection"""
74
72
  client_object._parent_collection = self
75
73
  self._data.append(client_object)
76
74
  return self
@@ -112,7 +110,6 @@ class ClientObjectCollection(ClientObject, Generic[T]):
112
110
  # type: (str) -> Self
113
111
  """
114
112
  Allows clients to filter a collection of resources that are addressed by a request URL
115
-
116
113
  :param str expression: Filter expression, for example: 'Id eq 123'
117
114
  """
118
115
  self.query_options.filter = expression
@@ -136,17 +133,13 @@ class ClientObjectCollection(ClientObject, Generic[T]):
136
133
 
137
134
  def top(self, value):
138
135
  # type: (int) -> Self
139
- """
140
- Specifies the number of items in the queried collection to be included in the result
141
- """
136
+ """Specifies the number of items in the queried collection to be included in the result"""
142
137
  self.query_options.top = value
143
138
  return self
144
139
 
145
140
  def paged(self, page_size=None, page_loaded=None):
146
- # type: (int, Callable[["ClientObjectCollection"], None]) -> Self
147
- """
148
- Retrieves via server-driven paging mode
149
- """
141
+ # type: (int, Callable[[Self], None]) -> Self
142
+ """Retrieves via server-driven paging mode"""
150
143
  self._paged_mode = True
151
144
  if callable(page_loaded):
152
145
  self._page_loaded += page_loaded
@@ -154,10 +147,17 @@ class ClientObjectCollection(ClientObject, Generic[T]):
154
147
  self.top(page_size)
155
148
  return self
156
149
 
150
+ def after_execute(self, action, *args, **kwargs):
151
+ # type: (Callable[[Self, Any, Any], None], Any, Any) -> Self
152
+ super(ClientObjectCollection, self).after_execute(action, *args, **kwargs)
153
+ self._page_loaded += action
154
+ return self
155
+
157
156
  def get(self):
158
157
  # type: () -> Self
159
158
 
160
- def _loaded(items):
159
+ def _loaded(col):
160
+ # type: (Self) -> None
161
161
  self._page_loaded.notify(self)
162
162
 
163
163
  self.context.load(self, after_loaded=_loaded)
@@ -165,17 +165,13 @@ class ClientObjectCollection(ClientObject, Generic[T]):
165
165
 
166
166
  def get_all(self, page_size=None, page_loaded=None):
167
167
  # type: (int, Callable[[Self], None]) -> Self
168
- """
169
- Gets all the items in a collection, regardless of the size.
168
+ """Gets all the items in a collection, regardless of the size."""
170
169
 
171
- :type self: T
172
- :param int page_size: Page size
173
- :param (T) -> None page_loaded: Page loaded event
174
- """
175
170
  self.paged(page_size, page_loaded)
176
171
 
177
- def _page_loaded(items):
178
- self._page_loaded.notify(self)
172
+ def _page_loaded(col):
173
+ # type: (Self) -> None
174
+ self._page_loaded.notify(col)
179
175
  if self.has_next:
180
176
  self._get_next(after_loaded=_page_loaded)
181
177
 
@@ -186,38 +182,37 @@ class ClientObjectCollection(ClientObject, Generic[T]):
186
182
  # type: (Optional[EventHandler]) -> Self
187
183
  """
188
184
  Submit a request to retrieve next collection of items
189
-
190
185
  :param (ClientObjectCollection) -> None after_loaded: Page loaded event
191
186
  """
192
187
 
193
- def _construct_next_query(request):
188
+ def _construct_request(request):
194
189
  # type: (RequestOptions) -> None
195
190
  request.url = self._next_request_url
196
191
 
197
192
  self.context.load(
198
- self, before_loaded=_construct_next_query, after_loaded=after_loaded
193
+ self, before_loaded=_construct_request, after_loaded=after_loaded
199
194
  )
200
195
  return self
201
196
 
202
197
  def first(self, expression):
203
198
  # type: (str) -> T
204
199
  """Return the first Entity instance that matches current query
205
-
206
200
  :param str expression: Filter expression
207
201
  """
208
202
  return_type = self.create_typed_object()
209
203
  self.add_child(return_type)
210
- key = return_type.property_ref_name
211
204
 
212
205
  def _after_loaded(col):
213
206
  # type: (ClientObjectCollection) -> None
214
207
  if len(col) < 1:
215
208
  message = "Not found for filter: {0}".format(self.query_options.filter)
216
209
  raise ValueError(message)
217
- return_type.set_property(key, col[0].get_property(key))
210
+ [
211
+ return_type.set_property(k, v, False)
212
+ for k, v in col[0].properties.items()
213
+ ]
218
214
 
219
- self.filter(expression).top(1)
220
- self.context.load(self, [key], after_loaded=_after_loaded)
215
+ self.get().filter(expression).top(1).after_execute(_after_loaded)
221
216
  return return_type
222
217
 
223
218
  def single(self, expression):
@@ -229,7 +224,6 @@ class ClientObjectCollection(ClientObject, Generic[T]):
229
224
  """
230
225
  return_type = self.create_typed_object()
231
226
  self.add_child(return_type)
232
- key = return_type.property_ref_name
233
227
 
234
228
  def _after_loaded(col):
235
229
  # type: (ClientObjectCollection) -> None
@@ -239,10 +233,12 @@ class ClientObjectCollection(ClientObject, Generic[T]):
239
233
  elif len(col) > 1:
240
234
  message = "Ambiguous match found for filter: {0}".format(expression)
241
235
  raise ValueError(message)
242
- return_type.set_property(key, col[0].get_property(key), False)
236
+ [
237
+ return_type.set_property(k, v, False)
238
+ for k, v in col[0].properties.items()
239
+ ]
243
240
 
244
- self.filter(expression).top(2)
245
- self.context.load(self, after_loaded=_after_loaded)
241
+ self.get().filter(expression).top(2).after_execute(_after_loaded)
246
242
  return return_type
247
243
 
248
244
  @property
@@ -256,6 +252,11 @@ class ClientObjectCollection(ClientObject, Generic[T]):
256
252
  """"""
257
253
  return self._next_request_url is not None
258
254
 
255
+ @property
256
+ def current_page(self):
257
+ # type: () -> List[T]
258
+ return self._data[self._current_pos :]
259
+
259
260
  @property
260
261
  def entity_type_name(self):
261
262
  # type: () -> str
@@ -1,11 +1,11 @@
1
1
  import copy
2
- from typing import TYPE_CHECKING, Generic, Optional, TypeVar
2
+ from typing import TYPE_CHECKING, Any, Callable, Generic, Optional, TypeVar
3
3
 
4
4
  from typing_extensions import Self
5
5
 
6
6
  if TYPE_CHECKING:
7
- from office365.runtime.client_runtime_context import ClientRuntimeContext
8
- from office365.runtime.client_value import ClientValue
7
+ from office365.runtime.client_runtime_context import ClientRuntimeContext # noqa
8
+ from office365.runtime.client_value import ClientValue # noqa
9
9
 
10
10
  T = TypeVar("T")
11
11
 
@@ -28,6 +28,7 @@ class ClientResult(Generic[T]):
28
28
  return self
29
29
 
30
30
  def after_execute(self, action, *args, **kwargs):
31
+ # type: (Callable[[Self], None], Any, Any) -> Self
31
32
  """
32
33
  Attach an event handler which is triggered after query is submitted to server
33
34
  :param (ClientResult) -> None action: Event handler
@@ -37,7 +38,7 @@ class ClientResult(Generic[T]):
37
38
 
38
39
  def set_property(self, key, value, persist_changes=False):
39
40
  # type: (str, T, bool) -> Self
40
- from office365.runtime.client_value import ClientValue
41
+ from office365.runtime.client_value import ClientValue # noqa
41
42
 
42
43
  if isinstance(self._value, ClientValue):
43
44
  self._value.set_property(key, value, persist_changes)
@@ -58,9 +59,7 @@ class ClientResult(Generic[T]):
58
59
  def execute_query_retry(
59
60
  self, max_retry=5, timeout_secs=5, success_callback=None, failure_callback=None
60
61
  ):
61
- """
62
- Executes the current set of data retrieval queries and method invocations and retries it if needed.
63
- """
62
+ """Executes the current set of data retrieval queries and method invocations and retries it if needed."""
64
63
  self._context.execute_query_retry(
65
64
  max_retry=max_retry,
66
65
  timeout_secs=timeout_secs,
@@ -5,9 +5,6 @@ from typing import TYPE_CHECKING, Any, AnyStr, Callable, List
5
5
  import requests
6
6
  from typing_extensions import Self
7
7
 
8
- if TYPE_CHECKING:
9
- from office365.runtime.client_object import ClientObject
10
-
11
8
  from office365.runtime.client_request import ClientRequest
12
9
  from office365.runtime.client_request_exception import ClientRequestException
13
10
  from office365.runtime.client_result import ClientResult
@@ -16,6 +13,9 @@ from office365.runtime.http.request_options import RequestOptions
16
13
  from office365.runtime.queries.client_query import ClientQuery
17
14
  from office365.runtime.queries.read_entity import ReadEntityQuery
18
15
 
16
+ if TYPE_CHECKING:
17
+ from office365.runtime.client_object import T
18
+
19
19
 
20
20
  class ClientRuntimeContext(object):
21
21
  def __init__(self):
@@ -88,17 +88,18 @@ class ClientRuntimeContext(object):
88
88
  before_loaded=None,
89
89
  after_loaded=None,
90
90
  ):
91
- # type: (ClientObject, List[str], Callable[[RequestOptions], None], Callable[[ClientObject], None]) -> Self
91
+ # type: (T, List[str], Callable[[RequestOptions], None], Callable[[T], None]) -> Self
92
92
  """Prepare retrieval query"""
93
93
  qry = ReadEntityQuery(client_object, properties_to_retrieve)
94
94
  self.add_query(qry)
95
95
  if callable(before_loaded):
96
- self.before_execute(before_loaded)
96
+ self.before_query_execute(before_loaded)
97
97
  if callable(after_loaded):
98
98
  self.after_query_execute(after_loaded, client_object)
99
99
  return self
100
100
 
101
101
  def before_query_execute(self, action, once=True, *args, **kwargs):
102
+ # type: (Callable[[RequestOptions, Any, Any], None], bool, Any, Any) -> Self
102
103
  """
103
104
  Attach an event handler which is triggered before query is submitted to server
104
105
 
@@ -110,10 +111,7 @@ class ClientRuntimeContext(object):
110
111
  query = self._queries[-1]
111
112
 
112
113
  def _prepare_request(request):
113
- """
114
- :type request: office365.runtime.http.request_options.RequestOptions
115
- """
116
-
114
+ # type: (RequestOptions) -> None
117
115
  if self.current_query.id == query.id:
118
116
  if once:
119
117
  self.pending_request().beforeExecute -= _prepare_request
@@ -123,9 +121,9 @@ class ClientRuntimeContext(object):
123
121
  return self
124
122
 
125
123
  def before_execute(self, action, once=True, *args, **kwargs):
124
+ # type: (Callable[[RequestOptions, Any, Any], None], bool, Any, Any) -> Self
126
125
  """
127
126
  Attach an event handler which is triggered before request is submitted to server
128
-
129
127
  :param (office365.runtime.http.request_options.RequestOptions, any) -> None action:
130
128
  :param bool once: Flag which determines whether action is executed once or multiple times
131
129
  """
@@ -141,9 +139,7 @@ class ClientRuntimeContext(object):
141
139
 
142
140
  def after_query_execute(self, action, *args, **kwargs):
143
141
  # type: (Callable[[Any, Any], None], Any, Any) -> Self
144
- """
145
- Attach an event handler which is triggered after query is submitted to server
146
- """
142
+ """Attach an event handler which is triggered after query is submitted to server"""
147
143
  if len(self._queries) == 0:
148
144
  return
149
145
  query = self._queries[-1]
@@ -165,9 +161,7 @@ class ClientRuntimeContext(object):
165
161
 
166
162
  def after_execute(self, action, once=True, *args, **kwargs):
167
163
  # type: (Callable[[requests.Response, Any, Any], None], bool, Any, Any) -> Self
168
- """
169
- Attach an event handler which is triggered after request is submitted to server
170
- """
164
+ """Attach an event handler which is triggered after request is submitted to server"""
171
165
 
172
166
  def _process_response(response):
173
167
  # type: (requests.Response) -> None
@@ -39,14 +39,9 @@ class ClientValueCollection(ClientValue, Generic[T]):
39
39
  def __repr__(self):
40
40
  return repr(self._data)
41
41
 
42
- def __str__(self):
43
- return ",".join(self._data)
44
-
45
42
  def to_json(self, json_format=None):
46
- # type: (ODataJsonFormat) -> dict
47
- """
48
- Serializes a client value's collection
49
- """
43
+ # type: (ODataJsonFormat) -> list
44
+ """Serializes a client value's collection"""
50
45
  json = [v for v in self]
51
46
  for i, v in enumerate(json):
52
47
  if isinstance(v, ClientValue):
@@ -84,7 +79,5 @@ class ClientValueCollection(ClientValue, Generic[T]):
84
79
 
85
80
  @property
86
81
  def entity_type_name(self):
87
- """
88
- Returns server type name of value's collection
89
- """
82
+ """Returns server type name of value's collection"""
90
83
  return "Collection({0})".format(ODataType.resolve_type(self._item_type))
@@ -1,3 +1,5 @@
1
+ # ruff: noqa
2
+ # pylint: skip-file
1
3
  import sys
2
4
 
3
5
  # -------
@@ -90,9 +90,7 @@ class QueryOptions(object):
90
90
  self.custom = {}
91
91
 
92
92
  def to_url(self):
93
- """Convert query options to url
94
- :return: str
95
- """
93
+ """Convert query options to url"""
96
94
  return "&".join(["$%s=%s" % (key, value) for (key, value) in self])
97
95
 
98
96
  def __iter__(self):
@@ -19,7 +19,7 @@ class ODataReader(object):
19
19
  def format_file(self):
20
20
  import xml.dom.minidom
21
21
 
22
- with open(self._metadata_path, "r") as in_file:
22
+ with open(self._metadata_path, "r", encoding="utf8") as in_file:
23
23
  metadata_content = in_file.read()
24
24
 
25
25
  formatted_metadata_content = xml.dom.minidom.parseString(