Office365-REST-Python-Client 3.1.0__py3-none-any.whl → 3.2.0__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/communications/callrecords/call_record.py +18 -0
- office365/communications/calls/call.py +3 -0
- office365/communications/presences/presence.py +3 -0
- office365/communications/quotas.py +66 -0
- office365/communications/virtualevents/virtual_event.py +3 -0
- office365/directory/domains/domain.py +3 -0
- office365/directory/licenses/subscribed_sku.py +3 -0
- office365/directory/objects/object.py +3 -0
- office365/directory/quotas.py +34 -0
- office365/entity_collection.py +2 -2
- office365/graph_client.py +46 -2
- office365/limits.py +66 -0
- office365/migration/__init__.py +6 -1
- office365/migration/adapters/__init__.py +14 -4
- office365/migration/adapters/filesystem.py +4 -1
- office365/migration/assessment/export.py +5 -5
- office365/migration/assessment/issue.py +19 -0
- office365/migration/assessment/report.py +11 -0
- office365/migration/assessment/scanners/base.py +37 -49
- office365/migration/base.py +33 -8
- office365/migration/checkpoint.py +1 -1
- office365/migration/outlook/assessor.py +4 -4
- office365/migration/package/__init__.py +82 -0
- office365/migration/package/builder.py +603 -0
- office365/migration/package/crypto.py +54 -0
- office365/migration/package/manifest_xml.py +495 -0
- office365/migration/package/staging.py +180 -0
- office365/migration/report.py +7 -2
- office365/migration/report_io.py +79 -0
- office365/migration/runner.py +117 -10
- office365/migration/server_job.py +126 -14
- office365/migration/session.py +132 -49
- office365/migration/settings.py +67 -0
- office365/migration/sharepoint/__init__.py +2 -0
- office365/migration/sharepoint/adapters.py +207 -41
- office365/migration/sharepoint/assessor.py +45 -9
- office365/migration/sharepoint/options.py +57 -0
- office365/migration/sharepoint/package_target.py +209 -0
- office365/migration/sharepoint/registry.py +22 -0
- office365/migration/sharepoint/resolvers.py +96 -0
- office365/migration/sharepoint/scanners/__init__.py +29 -0
- office365/migration/sharepoint/scanners/browser_file_handling.py +55 -0
- office365/migration/sharepoint/scanners/checked_out_files.py +57 -0
- office365/migration/sharepoint/scanners/file_versions.py +56 -0
- office365/migration/sharepoint/scanners/files.py +5 -2
- office365/migration/sharepoint/scanners/large_excel_files.py +56 -0
- office365/migration/sharepoint/scanners/large_lists.py +58 -0
- office365/migration/sharepoint/scanners/large_sites.py +4 -3
- office365/migration/sharepoint/scanners/long_onedrive_urls.py +52 -0
- office365/migration/sharepoint/scanners/lookup.py +38 -0
- office365/migration/sharepoint/scanners/paths.py +9 -4
- office365/migration/sharepoint/scanners/permissions.py +20 -2
- office365/migration/sharepoint/scanners/smat.py +51 -0
- office365/migration/sharepoint/scanners/summary.py +1 -0
- office365/migration/sharepoint/scanners/thicket_folders.py +38 -0
- office365/migration/sharepoint/scanners/unsupported_site_templates.py +90 -0
- office365/migration/sharepoint/tenant_assessor.py +5 -3
- office365/migration/sharepoint/transfer.py +4 -2
- office365/migration/tasks.py +121 -0
- office365/migration/validators.py +2 -19
- office365/onedrive/driveitems/driveItem.py +116 -12
- office365/onedrive/termstore/groups/collection.py +2 -9
- office365/onedrive/termstore/sets/collection.py +2 -9
- office365/onedrive/termstore/terms/collection.py +3 -10
- office365/onedrive/workbooks/workbook.py +7 -0
- office365/outlook/contacts/folders/collection.py +4 -13
- office365/runtime/auth/authentication_context.py +5 -0
- office365/runtime/client_object.py +18 -0
- office365/runtime/client_object_collection.py +75 -245
- office365/runtime/client_request.py +77 -1
- office365/runtime/client_request_exception.py +127 -39
- office365/runtime/client_runtime_context.py +79 -8
- office365/runtime/converters/csv_writer.py +10 -4
- office365/runtime/converters/dataframe.py +84 -4
- office365/runtime/converters/json_file.py +12 -3
- office365/runtime/converters/parquet.py +67 -0
- office365/runtime/converters/records.py +31 -12
- office365/runtime/converters/registry.py +185 -0
- office365/runtime/converters/scalars.py +31 -0
- office365/runtime/converters/sql.py +69 -0
- office365/runtime/converters/streamers.py +105 -0
- office365/runtime/converters/streams.py +42 -0
- office365/runtime/converters/upsert.py +101 -0
- office365/runtime/exceptions.py +105 -0
- office365/runtime/http/prefer.py +26 -0
- office365/runtime/http/throttling.py +258 -56
- office365/runtime/imports.py +571 -0
- office365/runtime/limits.py +455 -0
- office365/runtime/odata/request.py +11 -2
- office365/runtime/odata/type.py +1 -0
- office365/runtime/odata/v3/batch_request.py +4 -2
- office365/runtime/odata/v4/batch_request.py +22 -7
- office365/runtime/operations.py +29 -0
- office365/runtime/parallel.py +12 -14
- office365/runtime/paths/v4/entity.py +2 -2
- office365/runtime/queries/batch.py +18 -1
- office365/runtime/queries/get_or_create.py +109 -0
- office365/runtime/record_collection.py +443 -0
- office365/runtime/retry.py +92 -26
- office365/runtime/transport/base.py +6 -1
- office365/runtime/transport/requests_transport.py +4 -0
- office365/runtime/transport/throttled_transport.py +67 -0
- office365/runtime/verification.py +40 -0
- office365/sharepoint/activities/logger.py +118 -8
- office365/sharepoint/administration/analytics/usage_service.py +15 -7
- office365/sharepoint/administration/sitemove/service.py +791 -8
- office365/sharepoint/alerts/alert.py +79 -0
- office365/sharepoint/apps/app_collection.py +25 -0
- office365/sharepoint/apps/launcher.py +16 -0
- office365/sharepoint/authpolicy/tenant/compliancereport.py +5 -0
- office365/sharepoint/businessdata/app_bdc_catalog.py +135 -0
- office365/sharepoint/businessdata/entityfieldvaluedictionary.py +65 -0
- office365/sharepoint/businessdata/entityidentifier.py +23 -0
- office365/sharepoint/businessdata/entityinstance.py +52 -0
- office365/sharepoint/businessdata/entityview.py +31 -0
- office365/sharepoint/businessdata/externalsubscriptionstore.py +9 -0
- office365/sharepoint/businessdata/typedescriptor.py +37 -0
- office365/sharepoint/client_context.py +40 -23
- office365/sharepoint/clientsidecomponent/hostedapps/app.py +21 -0
- office365/sharepoint/clientsidecomponent/hostedapps/manager.py +16 -0
- office365/sharepoint/comments/comment.py +84 -2
- office365/sharepoint/contentcenter/machinelearning/models/model.py +0 -23
- office365/sharepoint/contentcenter/machinelearning/publications/publication.py +0 -9
- office365/sharepoint/contentcenter/machinelearning/samples/sample.py +0 -14
- office365/sharepoint/contentcenter/machinelearning/workitems/item.py +0 -80
- office365/sharepoint/contentsolution/template_api.py +148 -0
- office365/sharepoint/contenttypes/collection.py +32 -10
- office365/sharepoint/convergence/addnoliveblobsinodcservicestateapi.py +9 -0
- office365/sharepoint/convergence/consumer_permissions.py +15 -0
- office365/sharepoint/convergence/migration_complete_state_api.py +25 -0
- office365/sharepoint/convergence/odcmetadatacleanedupapi.py +9 -0
- office365/sharepoint/documentmanagement/document_id.py +12 -0
- office365/sharepoint/entity.py +11 -2
- office365/sharepoint/entity_collection.py +2 -2
- office365/sharepoint/exceptions.py +194 -0
- office365/sharepoint/fields/builtin_field_id.py +45 -34
- office365/sharepoint/fields/builtin_field_name.py +123 -0
- office365/sharepoint/fields/coercion.py +131 -0
- office365/sharepoint/fields/collection.py +54 -37
- office365/sharepoint/fields/field.py +17 -0
- office365/sharepoint/fields/name.py +46 -2
- office365/sharepoint/files/collection.py +7 -1
- office365/sharepoint/files/file.py +54 -8
- office365/sharepoint/files/versions/version.py +38 -13
- office365/sharepoint/folders/collection.py +4 -0
- office365/sharepoint/folders/folder.py +91 -21
- office365/sharepoint/htmlpages/html_page.py +16 -0
- office365/sharepoint/htmlpages/html_page_service.py +19 -0
- office365/sharepoint/ir/migration.py +9 -0
- office365/sharepoint/listitems/caml/__init__.py +31 -0
- office365/sharepoint/listitems/caml/builder.py +129 -0
- office365/sharepoint/listitems/caml/expressions.py +424 -0
- office365/sharepoint/listitems/caml/fields.py +68 -0
- office365/sharepoint/listitems/caml/guard.py +63 -0
- office365/sharepoint/listitems/caml/query.py +71 -2
- office365/sharepoint/listitems/caml/values.py +113 -0
- office365/sharepoint/listitems/collection.py +21 -20
- office365/sharepoint/listitems/upsert.py +75 -0
- office365/sharepoint/lists/collection.py +29 -22
- office365/sharepoint/lists/exporter.py +4 -3
- office365/sharepoint/lists/list.py +397 -39
- office365/sharepoint/lists/smart_wiki_library_utility.py +58 -0
- office365/sharepoint/logger/export.py +12 -0
- office365/sharepoint/marketplace/app_metadata.py +97 -1
- office365/sharepoint/marketplace/appstatequeryjobdefinition.py +9 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/carddesigns/card_designs.py +35 -0
- office365/sharepoint/marketplace/sitecollection/appcatalog/allowed_item.py +5 -0
- office365/sharepoint/marketplace/tenant/appcatalog/accessor.py +107 -30
- office365/sharepoint/microfeed/data.py +0 -6
- office365/sharepoint/microservice/manager.py +61 -0
- office365/sharepoint/migrationcenter/common/task.py +193 -4
- office365/sharepoint/migrationcenter/common/task_entity_data.py +1 -1
- office365/sharepoint/migrationcenter/deploy_status.py +13 -0
- office365/sharepoint/migrationcenter/service/properties.py +20 -0
- office365/sharepoint/migrationcenter/service/storage.py +34 -0
- office365/sharepoint/migrationcenter/spflight.py +13 -0
- office365/sharepoint/migrationcenter/urlparseresult.py +77 -0
- office365/sharepoint/multigeo/service/spmultigeoproxy.py +13 -0
- office365/sharepoint/navigation/servicerest.py +127 -0
- office365/sharepoint/oauth/authentication.py +13 -0
- office365/sharepoint/portal/theme_manager.py +120 -8
- office365/sharepoint/principal/users/user.py +10 -0
- office365/sharepoint/publishing/campaign/campaign.py +36 -1
- office365/sharepoint/publishing/feedvideopage.py +0 -7
- office365/sharepoint/publishing/pages/3d/page.py +0 -6
- office365/sharepoint/publishing/pages/page.py +0 -117
- office365/sharepoint/publishing/pages/reposts/repost.py +0 -7
- office365/sharepoint/publishing/pages/topics/topic.py +0 -7
- office365/sharepoint/publishing/subtitlefile.py +0 -40
- office365/sharepoint/quotamanagement/consumer/consumer_quota_info_api.py +14 -0
- office365/sharepoint/quotamanagement/consumer/non_quota_backfill_api.py +23 -0
- office365/sharepoint/quotamanagement/consumer/nonquotamigrationapi.py +9 -0
- office365/sharepoint/quotamanagement/consumer/quotamigrationapi.py +13 -0
- office365/sharepoint/request.py +57 -16
- office365/sharepoint/search/administration/document_crawl_log.py +24 -7
- office365/sharepoint/search/administration/providers/crawl_versions_info.py +29 -0
- office365/sharepoint/search/administration/providers/recycle_bin_info.py +23 -0
- office365/sharepoint/search/administration/providers/site_content_processing_info.py +67 -0
- office365/sharepoint/sites/site.py +976 -65
- office365/sharepoint/sites/siteprovisioninginfoprovider.py +13 -0
- office365/sharepoint/tenant/administration/datagovernance/insight_client.py +292 -23
- office365/sharepoint/tenant/administration/ddiadapter.py +97 -0
- office365/sharepoint/tenant/administration/internal/aad/collection.py +20 -0
- office365/sharepoint/tenant/administration/internal/aad/permission_grant.py +0 -19
- office365/sharepoint/tenant/administration/internal/appservice/permission_request.py +72 -1
- office365/sharepoint/tenant/administration/internal/appservice/principal.py +1 -3
- office365/sharepoint/tenant/administration/odb_license_enforcement_service.py +26 -0
- office365/sharepoint/tenant/administration/sites/properties.py +564 -6
- office365/sharepoint/tenant/administration/spdatagovernancesarrestapiclient.py +60 -1
- office365/sharepoint/tenant/insights/reports/manager.py +24 -12
- office365/sharepoint/tenant/management/office365_tenant.py +451 -2
- office365/sharepoint/tenantadministration/catalog_management_collection.py +69 -0
- office365/sharepoint/tenantadministration/catalog_management_custom_properties_collection.py +237 -0
- office365/sharepoint/tenantadministration/catalog_management_restricted_content_discovery_collection.py +56 -0
- office365/sharepoint/tenantadministration/sp_data_governance_client_exception.py +7 -0
- office365/sharepoint/thresholds.py +529 -0
- office365/sharepoint/translation/jobs/job.py +72 -2
- office365/sharepoint/translation/jobs/status.py +47 -9
- office365/sharepoint/translation/sync_translator.py +15 -2
- office365/sharepoint/utilities/move_copy_util.py +2 -1
- office365/sharepoint/viva/connections/page.py +27 -0
- office365/sharepoint/viva/home.py +38 -0
- office365/sharepoint/viva/learningmanager.py +9 -0
- office365/sharepoint/viva/vivaresources.py +60 -0
- office365/sharepoint/webhooks/subscription.py +0 -11
- office365/sharepoint/webparts/definitions/definition.py +13 -0
- office365/sharepoint/webparts/limited_manager.py +29 -7
- office365/sharepoint/webs/context_web_information.py +14 -9
- office365/sharepoint/webs/templates/__init__.py +11 -0
- office365/sharepoint/webs/templates/type.py +74 -15
- office365/sharepoint/workflow/definition.py +6 -0
- office365/sharepoint/workflow/deployment_service.py +155 -0
- office365/sharepoint/workflow/instances/service.py +33 -0
- office365/sharepoint/workflow/interopservice.py +68 -0
- office365/sharepoint/workflow/messagingservice.py +24 -0
- office365/sharepoint/workflow/servicesmanager.py +41 -2
- office365/sharepoint/workflow/subscriptions/service.py +67 -0
- office365/sharepoint/workflow/subscriptions/subscription.py +31 -0
- office365/sharepoint/workflow/task.py +425 -0
- office365_rest_python_client-3.2.0.dist-info/METADATA +605 -0
- {office365_rest_python_client-3.1.0.dist-info → office365_rest_python_client-3.2.0.dist-info}/RECORD +242 -185
- office365/migration/_util.py +0 -73
- office365/sharepoint/listitems/caml/types.py +0 -70
- office365_rest_python_client-3.1.0.dist-info/METADATA +0 -475
- {office365_rest_python_client-3.1.0.dist-info → office365_rest_python_client-3.2.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Typed CAML ``<Value>`` nodes.
|
|
2
|
+
|
|
3
|
+
A :class:`Value` renders a ``<Value Type='...'>...</Value>`` element, inferring
|
|
4
|
+
the OData value type from the Python value (``str`` -> ``Text``, ``int`` ->
|
|
5
|
+
``Integer``, ``bool`` -> ``Boolean``, ``datetime`` -> ``DateTime``) unless an
|
|
6
|
+
explicit type is given. Special values (``Now``/``Today``/``Month``/``UserID``/
|
|
7
|
+
``ListProperty``) render a child element instead of literal text.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from datetime import date, datetime
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Any, Optional
|
|
15
|
+
from xml.sax.saxutils import escape, quoteattr
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ValueType(str, Enum):
|
|
19
|
+
"""The ``Type`` attribute of a CAML ``<Value>`` element."""
|
|
20
|
+
|
|
21
|
+
Text = "Text"
|
|
22
|
+
Note = "Note"
|
|
23
|
+
Integer = "Integer"
|
|
24
|
+
Counter = "Counter"
|
|
25
|
+
Number = "Number"
|
|
26
|
+
Currency = "Currency"
|
|
27
|
+
DateTime = "DateTime"
|
|
28
|
+
Boolean = "Boolean"
|
|
29
|
+
Lookup = "Lookup"
|
|
30
|
+
User = "User"
|
|
31
|
+
Choice = "Choice"
|
|
32
|
+
URL = "URL"
|
|
33
|
+
Guid = "Guid"
|
|
34
|
+
Calculated = "Calculated"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def infer_value_type(value: Any) -> ValueType:
|
|
38
|
+
"""Infer the CAML ``ValueType`` from a Python value."""
|
|
39
|
+
if isinstance(value, bool): # bool before int (bool is an int subclass)
|
|
40
|
+
return ValueType.Boolean
|
|
41
|
+
if isinstance(value, int):
|
|
42
|
+
return ValueType.Integer
|
|
43
|
+
if isinstance(value, float):
|
|
44
|
+
return ValueType.Number
|
|
45
|
+
if isinstance(value, (datetime, date)):
|
|
46
|
+
return ValueType.DateTime
|
|
47
|
+
return ValueType.Text
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class Value:
|
|
51
|
+
"""A CAML ``<Value>`` element."""
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
value: Any = None,
|
|
56
|
+
*,
|
|
57
|
+
type: Optional[ValueType | str] = None, # noqa: A002
|
|
58
|
+
include_time_value: bool = False,
|
|
59
|
+
lookup_id: bool = False,
|
|
60
|
+
child: Optional[str] = None,
|
|
61
|
+
) -> None:
|
|
62
|
+
self._value = value
|
|
63
|
+
self._type = ValueType(type) if isinstance(type, str) else type
|
|
64
|
+
self._include_time_value = include_time_value
|
|
65
|
+
self._lookup_id = lookup_id
|
|
66
|
+
self._child = child # raw child XML (e.g. "<Now/>")
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def value_type(self) -> ValueType:
|
|
70
|
+
"""The resolved ``ValueType`` (explicit type, else inferred)."""
|
|
71
|
+
return self._type or infer_value_type(self._value)
|
|
72
|
+
|
|
73
|
+
def to_xml(self) -> str:
|
|
74
|
+
attrs = [f"Type={quoteattr(self.value_type.value)}"]
|
|
75
|
+
if self._include_time_value:
|
|
76
|
+
attrs.append('IncludeTimeValue="TRUE"')
|
|
77
|
+
if self._lookup_id:
|
|
78
|
+
attrs.append('LookupId="TRUE"')
|
|
79
|
+
inner = self._child if self._child is not None else escape(self._format(self._value))
|
|
80
|
+
return f"<Value {' '.join(attrs)}>{inner}</Value>"
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def _format(value: Any) -> str:
|
|
84
|
+
if isinstance(value, bool):
|
|
85
|
+
return "1" if value else "0"
|
|
86
|
+
if isinstance(value, (datetime, date)):
|
|
87
|
+
return value.isoformat()
|
|
88
|
+
return str(value)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def now() -> Value:
|
|
92
|
+
"""A ``<Value Type='DateTime'><Now/></Value>`` node."""
|
|
93
|
+
return Value(type=ValueType.DateTime, child="<Now/>")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def today() -> Value:
|
|
97
|
+
"""A ``<Value Type='DateTime'><Today/></Value>`` node."""
|
|
98
|
+
return Value(type=ValueType.DateTime, child="<Today/>")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def month() -> Value:
|
|
102
|
+
"""A ``<Value Type='Integer'><Month/></Value>`` node."""
|
|
103
|
+
return Value(type=ValueType.Integer, child="<Month/>")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def user_id() -> Value:
|
|
107
|
+
"""A ``<Value Type='Integer'><UserID/></Value>`` node."""
|
|
108
|
+
return Value(type=ValueType.Integer, child="<UserID/>")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def list_property(name: str) -> Value:
|
|
112
|
+
"""A ``<Value><ListProperty Name='...'/></Value>`` node."""
|
|
113
|
+
return Value(child=f"<ListProperty Name={quoteattr(name)}/>")
|
|
@@ -7,51 +7,52 @@ from typing_extensions import Self
|
|
|
7
7
|
from office365.runtime.paths.service_operation import ServiceOperationPath
|
|
8
8
|
from office365.sharepoint.entity_collection import EntityCollection
|
|
9
9
|
from office365.sharepoint.listitems.listitem import ListItem
|
|
10
|
+
from office365.sharepoint.thresholds import LIST_VIEW_THRESHOLD
|
|
10
11
|
|
|
11
12
|
if TYPE_CHECKING:
|
|
13
|
+
from office365.runtime.converters.upsert import UpsertTarget
|
|
12
14
|
from office365.runtime.operations import ProgressCallback
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
class ListItemCollection(EntityCollection[ListItem]):
|
|
16
18
|
"""List Item collection"""
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
_list_view_threshold = LIST_VIEW_THRESHOLD
|
|
21
|
+
_truncation_hint = "page it with List.get_items(query, page_size=2000) or items.get_all(page_size=2000)"
|
|
20
22
|
|
|
21
|
-
def
|
|
23
|
+
def __init__(self, context, resource_path=None, parent=None):
|
|
24
|
+
super().__init__(context, ListItem, resource_path, parent)
|
|
25
|
+
|
|
26
|
+
def queue_records(self, records, progress: "ProgressCallback | None" = None) -> Self:
|
|
22
27
|
"""Queue an item create per record.
|
|
23
28
|
|
|
24
29
|
List item columns are defined per list at runtime, not on the ``ListItem``
|
|
25
30
|
class, so every record key is forwarded to the server (no unknown-column
|
|
26
31
|
filtering). Deferred — run the creates with ``execute_query()``.
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
records: Plain dict records to import.
|
|
30
|
-
progress: Optional hook invoked per queued create as it completes
|
|
31
|
-
during ``execute_query()``.
|
|
32
|
-
|
|
33
|
-
Returns:
|
|
34
|
-
Self: The item collection, for method chaining.
|
|
35
32
|
"""
|
|
36
33
|
from office365.runtime.converters.csv_reader import coerce_records
|
|
37
34
|
|
|
38
35
|
return self._import_records(coerce_records(self._item_type, records, allow_unknown=True), progress=progress)
|
|
39
36
|
|
|
40
|
-
def
|
|
41
|
-
"""
|
|
37
|
+
def upsert_target(self, *, key_field: str = "MigrationKey", enforce_unique: bool = False) -> "UpsertTarget":
|
|
38
|
+
"""The keyed skip/upsert target for this list (see ``from_records(key=...)``)."""
|
|
39
|
+
from office365.sharepoint.listitems.upsert import ListItemUpsertTarget
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
return ListItemUpsertTarget(self, key_field=key_field, enforce_unique=enforce_unique)
|
|
42
|
+
|
|
43
|
+
def _key_column(self, column: str) -> str:
|
|
44
|
+
"""List-item record keys are field internal names (``Name`` -> ``Name_``)."""
|
|
45
|
+
from office365.sharepoint.fields.name import internal_field_name
|
|
46
|
+
|
|
47
|
+
return internal_field_name(column)
|
|
48
|
+
|
|
49
|
+
def get_by_id(self, item_id: int) -> ListItem:
|
|
50
|
+
"""Returns the list item with the specified list item identifier."""
|
|
46
51
|
return ListItem(self.context, ServiceOperationPath("GetById", [item_id], self.resource_path))
|
|
47
52
|
|
|
48
53
|
def get_by_string_id(self, s_id: str) -> ListItem:
|
|
49
54
|
"""Returns the list item with either the specified list item identifier or the specified identifier
|
|
50
55
|
for an instance of an external content type.
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
s_id (str): Specifies the list item identifier, or if the list is an external list, specifies the identifier
|
|
54
|
-
for an instance of an external content type as specified in[MS-ECTPWPS] section 3.1.4.1.2.1.
|
|
55
56
|
"""
|
|
56
57
|
return ListItem(
|
|
57
58
|
self.context,
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""SharePoint list-item :class:`UpsertTarget` — the destination side of keyed imports.
|
|
2
|
+
|
|
3
|
+
Keeps the SharePoint-specific pieces (ensure the key column, load existing keys,
|
|
4
|
+
create/update items) out of the runtime upsert core, so the same
|
|
5
|
+
:func:`~office365.runtime.converters.upsert.keyed_queue` drives list imports and
|
|
6
|
+
the migration toolkit.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import TYPE_CHECKING, Any, Mapping, cast
|
|
12
|
+
|
|
13
|
+
from office365.runtime.paths.v3.entity import EntityPath
|
|
14
|
+
from office365.sharepoint.fields.type import FieldType
|
|
15
|
+
from office365.sharepoint.listitems.listitem import ListItem
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from office365.sharepoint.listitems.collection import ListItemCollection
|
|
19
|
+
from office365.sharepoint.lists.list import List
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ListItemUpsertTarget:
|
|
23
|
+
"""Keyed skip/upsert target backed by a :class:`ListItemCollection`."""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
collection: "ListItemCollection",
|
|
28
|
+
*,
|
|
29
|
+
key_field: str = "MigrationKey",
|
|
30
|
+
enforce_unique: bool = False,
|
|
31
|
+
) -> None:
|
|
32
|
+
self._collection = collection
|
|
33
|
+
self._key_field = key_field
|
|
34
|
+
self._enforce_unique = enforce_unique
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def key_field(self) -> str:
|
|
38
|
+
return self._key_field
|
|
39
|
+
|
|
40
|
+
def ensure_key_field(self) -> None:
|
|
41
|
+
"""Queue the key column (Text, optionally unique+indexed) if missing."""
|
|
42
|
+
from office365.sharepoint.fields.creation_information import FieldCreationInformation
|
|
43
|
+
|
|
44
|
+
parent = cast("List", self._collection.parent)
|
|
45
|
+
if parent is None:
|
|
46
|
+
return
|
|
47
|
+
field = parent.fields.ensure(FieldCreationInformation(Title=self._key_field, FieldTypeKind=FieldType.Text))
|
|
48
|
+
if self._enforce_unique:
|
|
49
|
+
field.set_property("EnforceUniqueValues", True)
|
|
50
|
+
field.set_property("Indexed", True)
|
|
51
|
+
field.update()
|
|
52
|
+
|
|
53
|
+
def load_keys(self) -> Mapping[str, Any]:
|
|
54
|
+
"""Return the existing ``{key: item_id}`` map (paged; key + ``Id`` only)."""
|
|
55
|
+
loaded = self._collection.select([self._key_field, "Id"]).get_all().execute_query()
|
|
56
|
+
keys: dict[str, Any] = {}
|
|
57
|
+
for item in loaded:
|
|
58
|
+
value = item.properties.get(self._key_field)
|
|
59
|
+
item_id = item.id
|
|
60
|
+
if value is not None and item_id is not None:
|
|
61
|
+
keys[str(value)] = item_id
|
|
62
|
+
return keys
|
|
63
|
+
|
|
64
|
+
def create_records(self, records: list[dict]) -> None:
|
|
65
|
+
self._collection.queue_records(records)
|
|
66
|
+
|
|
67
|
+
def update_record(self, item_id: Any, record: dict) -> None:
|
|
68
|
+
item = ListItem(
|
|
69
|
+
self._collection.context,
|
|
70
|
+
EntityPath(item_id, self._collection.resource_path),
|
|
71
|
+
parent_list=self._collection.parent,
|
|
72
|
+
)
|
|
73
|
+
for name, value in record.items():
|
|
74
|
+
item.set_property(name, value, persist_changes=True)
|
|
75
|
+
item.update()
|
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING, Optional
|
|
4
4
|
|
|
5
|
-
from office365.runtime.client_request_exception import ClientRequestException, DuplicatedObjectException
|
|
6
5
|
from office365.runtime.paths.resource_path import ResourcePath
|
|
7
6
|
from office365.runtime.paths.service_operation import ServiceOperationPath
|
|
8
7
|
from office365.runtime.paths.v3.entity import EntityPath
|
|
@@ -73,39 +72,47 @@ class ListCollection(EntityCollection[List]):
|
|
|
73
72
|
)
|
|
74
73
|
|
|
75
74
|
def ensure_list(
|
|
76
|
-
self,
|
|
75
|
+
self,
|
|
76
|
+
title: str,
|
|
77
|
+
description: str | None = None,
|
|
78
|
+
template_type: ListTemplateType = ListTemplateType.GenericList,
|
|
79
|
+
allow_content_types: bool = False,
|
|
80
|
+
*,
|
|
81
|
+
on_conflict: str = "skip",
|
|
77
82
|
) -> List:
|
|
78
83
|
"""Gets the list with the given title, or creates it if it does not exist.
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
existing list is loaded instead and its properties are copied into the
|
|
83
|
-
returned object. All other errors propagate.
|
|
84
|
-
|
|
85
|
-
The result is deferred: resolve it with ``execute_query()`` before use,
|
|
86
|
-
e.g.::
|
|
87
|
-
|
|
88
|
-
>>> lst = ctx.web.lists.ensure_list("My List").execute_query()
|
|
85
|
+
Idempotent (deferred — resolve with ``execute_query()``). With
|
|
86
|
+
``on_conflict="update"`` the existing list's description is reconciled.
|
|
89
87
|
|
|
90
88
|
Args:
|
|
91
89
|
title: Title of the list to get or create
|
|
92
90
|
description: Description of the list to get or create
|
|
93
91
|
template_type: Type of list to get or create
|
|
92
|
+
allow_content_types: Whether to enable content types
|
|
93
|
+
on_conflict: ``"skip"`` (default) or ``"update"``.
|
|
94
94
|
|
|
95
95
|
Returns:
|
|
96
96
|
List: The existing or newly created list
|
|
97
97
|
"""
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def
|
|
101
|
-
if not
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
98
|
+
from office365.runtime.queries.get_or_create import create_or_get
|
|
99
|
+
|
|
100
|
+
def _reconcile(lst: List) -> None:
|
|
101
|
+
if description is not None and lst.properties.get("Description") != description:
|
|
102
|
+
lst.set_property("Description", description)
|
|
103
|
+
lst.update()
|
|
104
|
+
|
|
105
|
+
return create_or_get(
|
|
106
|
+
create=lambda: self.add_list(
|
|
107
|
+
title=title,
|
|
108
|
+
description=description,
|
|
109
|
+
template_type=template_type,
|
|
110
|
+
allow_content_types=allow_content_types,
|
|
111
|
+
),
|
|
112
|
+
find=lambda: self.get_by_title(title).get(),
|
|
113
|
+
on_conflict=on_conflict,
|
|
114
|
+
reconcile=_reconcile,
|
|
115
|
+
)
|
|
109
116
|
|
|
110
117
|
def ensure_client_rendered_site_pages_library(self) -> List:
|
|
111
118
|
"""
|
|
@@ -5,6 +5,7 @@ from dataclasses import dataclass
|
|
|
5
5
|
from typing import IO, TYPE_CHECKING, Callable, Optional, Union
|
|
6
6
|
|
|
7
7
|
from office365.runtime.client_result import ClientResult
|
|
8
|
+
from office365.sharepoint.fields.builtin_field_name import SPBuiltInFieldName
|
|
8
9
|
from office365.sharepoint.files.system_object_type import FileSystemObjectType
|
|
9
10
|
from office365.sharepoint.listitems.collection import ListItemCollection
|
|
10
11
|
from office365.sharepoint.listitems.listitem import ListItem
|
|
@@ -72,9 +73,9 @@ class ListExporter:
|
|
|
72
73
|
[
|
|
73
74
|
"*",
|
|
74
75
|
"Id",
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
SPBuiltInFieldName.FileRef,
|
|
77
|
+
SPBuiltInFieldName.FileDirRef,
|
|
78
|
+
SPBuiltInFieldName.FileLeafRef,
|
|
78
79
|
"FileSystemObjectType",
|
|
79
80
|
]
|
|
80
81
|
)
|