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.
- {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/METADATA +6 -6
- {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/RECORD +265 -259
- office365/base_item.py +12 -20
- office365/communications/onlinemeetings/collection.py +1 -1
- office365/communications/onlinemeetings/online_meeting.py +20 -35
- office365/communications/presences/presence.py +18 -7
- office365/delta_collection.py +10 -1
- office365/delta_path.py +1 -1
- office365/directory/administrative_unit.py +6 -7
- office365/directory/applications/application.py +24 -18
- office365/directory/applications/roles/assignment.py +13 -1
- office365/directory/applications/roles/collection.py +13 -0
- office365/directory/applications/roles/role.py +6 -1
- office365/directory/audit/directory.py +8 -7
- office365/directory/audit/log_root.py +3 -0
- office365/directory/audit/signins/signin.py +19 -29
- office365/directory/authentication/authentication.py +1 -0
- office365/directory/authentication/methods/details.py +8 -6
- office365/directory/authentication/methods/phone.py +3 -1
- office365/directory/extensions/extension_property.py +7 -9
- office365/directory/groups/collection.py +10 -3
- office365/directory/groups/group.py +19 -19
- office365/directory/groups/lifecycle_policy.py +8 -7
- office365/directory/identities/provider.py +5 -6
- office365/directory/insights/usage_details.py +8 -3
- office365/directory/internal/paths/me.py +1 -1
- office365/directory/invitations/collection.py +1 -1
- office365/directory/invitations/invitation.py +6 -6
- office365/directory/object_collection.py +2 -3
- office365/directory/permissions/email_identity.py +7 -0
- office365/directory/permissions/grants/resource_specific.py +10 -9
- office365/directory/permissions/identity.py +3 -0
- office365/directory/permissions/identity_set.py +3 -0
- office365/directory/policies/base.py +4 -4
- office365/directory/policies/root.py +6 -4
- office365/directory/protection/information.py +3 -3
- office365/directory/rolemanagement/application.py +2 -0
- office365/directory/rolemanagement/role.py +11 -10
- office365/directory/rolemanagement/template.py +9 -8
- office365/directory/rolemanagement/unified_role_assignment.py +5 -4
- office365/directory/rolemanagement/unified_role_definition.py +6 -4
- office365/directory/security/security.py +3 -0
- office365/directory/serviceprincipals/collection.py +20 -4
- office365/directory/serviceprincipals/service_principal.py +79 -12
- office365/directory/users/activities/activity.py +5 -4
- office365/directory/users/user.py +29 -34
- office365/entity.py +2 -2
- office365/entity_collection.py +12 -5
- office365/graph_client.py +90 -8
- office365/intune/audit/event.py +4 -3
- office365/intune/devices/enrollment/configuration.py +6 -4
- office365/intune/devices/managed.py +9 -12
- office365/onedrive/analytics/item_activity_stat.py +4 -3
- office365/onedrive/columns/column_link.py +4 -4
- office365/onedrive/columns/definition.py +29 -32
- office365/onedrive/columns/definition_collection.py +1 -1
- office365/onedrive/contenttypes/content_type.py +16 -18
- office365/onedrive/documentsets/version.py +7 -3
- office365/onedrive/driveitems/driveItem.py +48 -49
- office365/onedrive/drives/drive.py +7 -2
- office365/onedrive/internal/paths/children.py +2 -2
- office365/onedrive/internal/paths/root.py +1 -1
- office365/onedrive/internal/paths/shared.py +1 -1
- office365/onedrive/internal/paths/site.py +3 -3
- office365/onedrive/internal/paths/url.py +2 -2
- office365/onedrive/listitems/list_item.py +2 -0
- office365/onedrive/lists/list.py +7 -4
- office365/onedrive/permissions/collection.py +28 -7
- office365/onedrive/permissions/permission.py +5 -7
- office365/onedrive/permissions/sharing_link.py +1 -1
- office365/onedrive/sharepoint.py +1 -0
- office365/onedrive/shares/collection.py +2 -5
- office365/onedrive/shares/drive_item.py +4 -0
- office365/onedrive/sites/site.py +6 -0
- office365/onedrive/termstore/groups/collection.py +3 -8
- office365/onedrive/termstore/groups/group.py +8 -0
- office365/onedrive/termstore/sets/collection.py +2 -6
- office365/onedrive/termstore/sets/name.py +5 -0
- office365/onedrive/termstore/sets/set.py +7 -0
- office365/onedrive/termstore/store.py +10 -13
- office365/onedrive/versions/drive_item.py +3 -1
- office365/onedrive/workbooks/ranges/range.py +9 -13
- office365/onedrive/workbooks/ranges/view.py +1 -0
- office365/onedrive/workbooks/tables/rows/row.py +3 -0
- office365/onedrive/workbooks/tables/table.py +7 -4
- office365/onedrive/workbooks/worksheets/worksheet.py +12 -4
- office365/onenote/entity_hierarchy_model.py +4 -0
- office365/onenote/internal/multipart_page_query.py +4 -5
- office365/onenote/notebooks/notebook.py +4 -0
- office365/onenote/pages/collection.py +3 -2
- office365/onenote/resources/resource.py +5 -4
- office365/onenote/sectiongroups/section_group.py +10 -7
- office365/onenote/sections/section.py +1 -1
- office365/outlook/calendar/attendees/base.py +2 -1
- office365/outlook/calendar/calendar.py +18 -10
- office365/outlook/calendar/events/collection.py +0 -2
- office365/outlook/calendar/group.py +7 -8
- office365/outlook/calendar/meetingtimes/suggestion.py +8 -4
- office365/outlook/calendar/meetingtimes/time_slot.py +3 -0
- office365/outlook/calendar/permissions/collection.py +1 -1
- office365/outlook/calendar/rooms/__init__.py +0 -0
- office365/outlook/calendar/rooms/list.py +27 -0
- office365/outlook/calendar/rooms/room.py +8 -0
- office365/outlook/calendar/schedule/information.py +0 -1
- office365/outlook/contacts/collection.py +0 -8
- office365/outlook/contacts/contact.py +14 -14
- office365/outlook/contacts/folder.py +3 -0
- office365/outlook/mail/attachments/attachment.py +31 -31
- office365/outlook/mail/attachments/collection.py +34 -6
- office365/outlook/mail/conversation.py +6 -4
- office365/outlook/mail/folders/collection.py +0 -7
- office365/outlook/mail/folders/folder.py +50 -18
- office365/outlook/mail/messages/collection.py +0 -1
- office365/outlook/mail/messages/message.py +58 -68
- office365/outlook/mail/physical_address.py +11 -5
- office365/outlook/mail/recipient.py +3 -1
- office365/outlook/mail/recurrence_range.py +14 -6
- office365/outlook/user.py +1 -0
- office365/planner/planner.py +9 -12
- office365/planner/plans/collection.py +17 -18
- office365/planner/plans/container.py +11 -0
- office365/planner/plans/plan.py +21 -10
- office365/runtime/auth/authentication_context.py +3 -3
- office365/runtime/auth/providers/acs_token_provider.py +7 -9
- office365/runtime/auth/providers/saml_token_provider.py +5 -2
- office365/runtime/client_object.py +6 -15
- office365/runtime/client_object_collection.py +36 -35
- office365/runtime/client_result.py +6 -7
- office365/runtime/client_runtime_context.py +10 -16
- office365/runtime/client_value_collection.py +3 -10
- office365/runtime/compat.py +2 -0
- office365/runtime/odata/query_options.py +1 -3
- office365/runtime/odata/reader.py +1 -1
- office365/runtime/odata/request.py +2 -4
- office365/runtime/odata/type.py +17 -0
- office365/runtime/odata/v4/upload_session_request.py +27 -30
- office365/runtime/paths/appid.py +1 -1
- office365/runtime/{odata/url_builder.py → paths/builder.py} +24 -9
- office365/runtime/paths/item.py +3 -1
- office365/runtime/paths/resource_path.py +12 -16
- office365/runtime/paths/service_operation.py +8 -7
- office365/runtime/paths/v3/__init__.py +0 -0
- office365/runtime/paths/{key.py → v3/entity.py} +5 -5
- office365/runtime/paths/v4/__init__.py +0 -0
- office365/runtime/paths/{entity.py → v4/entity.py} +13 -11
- office365/runtime/queries/function.py +1 -1
- office365/runtime/types/event_handler.py +1 -3
- office365/search/entity.py +15 -8
- office365/search/external/external.py +1 -0
- office365/search/sort_property.py +3 -0
- office365/sharepoint/attachments/attachment.py +3 -1
- office365/sharepoint/attachments/collection.py +3 -0
- office365/sharepoint/changes/change.py +12 -1
- office365/sharepoint/changes/collection.py +1 -1
- office365/sharepoint/changes/list.py +3 -0
- office365/sharepoint/changes/token.py +4 -0
- office365/sharepoint/changes/type.py +23 -23
- office365/sharepoint/changes/web.py +7 -3
- office365/sharepoint/client_context.py +21 -18
- office365/sharepoint/clientsidecomponent/hostedapps/manager.py +3 -3
- office365/sharepoint/contenttypes/content_type.py +47 -56
- office365/sharepoint/contenttypes/content_type_id.py +1 -1
- office365/sharepoint/documentmanagement/document_id.py +2 -2
- office365/sharepoint/documentmanagement/document_set.py +6 -7
- office365/sharepoint/entity_collection.py +9 -0
- office365/sharepoint/features/feature.py +6 -8
- office365/sharepoint/fields/collection.py +6 -5
- office365/sharepoint/fields/field.py +28 -46
- office365/sharepoint/fields/related_field_collection.py +1 -1
- office365/sharepoint/fields/user_value.py +3 -3
- office365/sharepoint/files/checked_out_file.py +4 -2
- office365/sharepoint/files/checked_out_file_collection.py +1 -1
- office365/sharepoint/files/collection.py +84 -14
- office365/sharepoint/files/file.py +118 -110
- office365/sharepoint/files/versions/collection.py +5 -3
- office365/sharepoint/files/versions/event.py +6 -3
- office365/sharepoint/files/versions/version.py +31 -18
- office365/sharepoint/folders/collection.py +5 -10
- office365/sharepoint/folders/folder.py +41 -24
- office365/sharepoint/forms/collection.py +1 -1
- office365/sharepoint/forms/form.py +4 -4
- office365/sharepoint/internal/paths/static_operation.py +9 -0
- office365/sharepoint/internal/paths/web.py +20 -0
- office365/sharepoint/listitems/collection.py +4 -0
- office365/sharepoint/listitems/listitem.py +37 -38
- office365/sharepoint/listitems/versions/collection.py +1 -1
- office365/sharepoint/listitems/versions/version.py +18 -11
- office365/sharepoint/lists/collection.py +1 -2
- office365/sharepoint/lists/list.py +106 -153
- office365/sharepoint/marketplace/app_metadata_collection.py +3 -1
- office365/sharepoint/navigation/node.py +16 -15
- office365/sharepoint/navigation/node_collection.py +9 -3
- office365/sharepoint/permissions/base_permissions.py +11 -6
- office365/sharepoint/permissions/roles/assignments/collection.py +8 -12
- office365/sharepoint/permissions/roles/definitions/definition.py +3 -1
- office365/sharepoint/permissions/securable_object.py +38 -31
- office365/sharepoint/portal/groups/service.py +12 -16
- office365/sharepoint/portal/groups/site_manager.py +0 -1
- office365/sharepoint/principal/groups/group.py +24 -30
- office365/sharepoint/principal/principal.py +21 -19
- office365/sharepoint/principal/users/collection.py +5 -0
- office365/sharepoint/principal/users/user.py +20 -26
- office365/sharepoint/publishing/pages/collection.py +1 -4
- office365/sharepoint/publishing/pages/metadata.py +38 -51
- office365/sharepoint/publishing/pages/metadata_collection.py +5 -2
- office365/sharepoint/publishing/pages/page.py +12 -21
- office365/sharepoint/publishing/pages/reposts/repost.py +5 -9
- office365/sharepoint/publishing/pages/service.py +36 -49
- office365/sharepoint/pushnotifications/collection.py +3 -1
- office365/sharepoint/recyclebin/item.py +11 -9
- office365/sharepoint/recyclebin/item_collection.py +1 -1
- office365/sharepoint/search/service.py +8 -6
- office365/sharepoint/sharing/links/info.py +5 -2
- office365/sharepoint/sharing/links/share_response.py +3 -0
- office365/sharepoint/sharing/links/share_settings.py +3 -0
- office365/sharepoint/sharing/object_sharing_information.py +25 -19
- office365/sharepoint/sharing/object_sharing_information_user.py +10 -19
- office365/sharepoint/sharing/result.py +18 -41
- office365/sharepoint/sharing/role.py +20 -0
- office365/sharepoint/sharing/role_type.py +1 -0
- office365/sharepoint/sharing/user_sharing_result.py +12 -0
- office365/sharepoint/sites/language.py +6 -0
- office365/sharepoint/sites/language_collection.py +3 -0
- office365/sharepoint/sites/site.py +65 -86
- office365/sharepoint/storagemetrics/storage_metrics.py +5 -6
- office365/sharepoint/taxonomy/item.py +11 -10
- office365/sharepoint/taxonomy/stores/store.py +8 -8
- office365/sharepoint/taxonomy/terms/label.py +3 -0
- office365/sharepoint/taxonomy/terms/term.py +31 -0
- office365/sharepoint/tenant/administration/collaboration/insights_overview.py +10 -0
- office365/sharepoint/tenant/administration/hubsites/collection.py +1 -2
- office365/sharepoint/tenant/administration/hubsites/hub_site.py +20 -24
- office365/sharepoint/tenant/administration/internal/permission_grant.py +7 -0
- office365/sharepoint/tenant/administration/sites/properties.py +55 -44
- office365/sharepoint/tenant/administration/tenant.py +69 -69
- office365/sharepoint/types/resource_path.py +2 -2
- office365/sharepoint/ui/applicationpages/peoplepicker/query_parameters.py +1 -1
- office365/sharepoint/usercustomactions/collection.py +1 -2
- office365/sharepoint/userprofiles/my_site_links.py +4 -4
- office365/sharepoint/userprofiles/people_manager.py +1 -3
- office365/sharepoint/userprofiles/user_profile.py +9 -11
- office365/sharepoint/utilities/principal_info.py +12 -0
- office365/sharepoint/viva/employee_engagement.py +1 -1
- office365/sharepoint/webparts/definition_collection.py +1 -1
- office365/sharepoint/webs/collection.py +8 -0
- office365/sharepoint/webs/template_collection.py +3 -5
- office365/sharepoint/webs/web.py +75 -95
- office365/subscriptions/collection.py +1 -1
- office365/subscriptions/subscription.py +13 -11
- office365/teams/apps/app.py +1 -0
- office365/teams/channels/channel.py +1 -3
- office365/teams/collection.py +12 -16
- office365/teams/info.py +7 -4
- office365/teams/members/conversation_collection.py +1 -3
- office365/teams/operations/async_operation.py +3 -5
- office365/teams/schedule/groups/group.py +3 -0
- office365/teams/team.py +18 -20
- office365/todo/attachments/base.py +7 -9
- office365/todo/linked_resource.py +6 -6
- office365/todo/tasks/list.py +1 -0
- office365/todo/tasks/task.py +3 -0
- office365/onedrive/internal/queries/resumable_file_upload.py +0 -36
- office365/outlook/internal/queries/attachment_upload.py +0 -53
- office365/runtime/odata/path_builder.py +0 -23
- office365/sharepoint/internal/key_value.py +0 -28
- office365/sharepoint/internal/queries/create_file.py +0 -20
- office365/sharepoint/internal/queries/upload_session.py +0 -103
- {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/LICENSE +0 -0
- {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/WHEEL +0 -0
- {Office365_REST_Python_Client-2.5.1.dist-info → Office365_REST_Python_Client-2.5.3.dist-info}/top_level.txt +0 -0
- /office365/planner/plans/{plan_details.py → details.py} +0 -0
|
@@ -1,43 +1,42 @@
|
|
|
1
|
-
from office365.directory.
|
|
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,
|
|
12
|
-
|
|
13
|
-
Creates a new plannerPlan.
|
|
14
|
-
|
|
15
|
-
:param str
|
|
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
|
|
20
|
+
def _add(owner_id):
|
|
21
|
+
# type: (str) -> None
|
|
22
22
|
payload = {
|
|
23
23
|
"title": title,
|
|
24
|
-
"
|
|
25
|
-
"
|
|
24
|
+
"container": {
|
|
25
|
+
"url": "https://graph.microsoft.com/v1.0/groups/{0}".format(
|
|
26
26
|
owner_id
|
|
27
27
|
)
|
|
28
28
|
},
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
qry = CreateEntityQuery(self, payload, return_type)
|
|
31
|
+
self.context.add_query(qry)
|
|
31
32
|
|
|
32
|
-
if isinstance(
|
|
33
|
+
if isinstance(container, Group):
|
|
33
34
|
|
|
34
35
|
def _owner_loaded():
|
|
35
|
-
|
|
36
|
-
self.context.add_query(next_qry)
|
|
36
|
+
_add(container.id)
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
container.ensure_property("id", _owner_loaded)
|
|
39
39
|
else:
|
|
40
|
-
|
|
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
|
+
"""
|
office365/planner/plans/plan.py
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
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)
|
|
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
|
|
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[[
|
|
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(
|
|
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(
|
|
178
|
-
|
|
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
|
|
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=
|
|
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
|
-
|
|
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
|
-
|
|
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: (
|
|
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.
|
|
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) ->
|
|
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))
|
office365/runtime/compat.py
CHANGED
|
@@ -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(
|