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
|
@@ -27,16 +27,18 @@ from office365.sharepoint.sharing.object_sharing_information import ObjectSharin
|
|
|
27
27
|
from office365.sharepoint.sharing.user_role_assignment import UserRoleAssignment
|
|
28
28
|
from office365.sharepoint.sharing.user_sharing_result import UserSharingResult
|
|
29
29
|
from office365.sharepoint.storagemetrics.storage_metrics import StorageMetrics
|
|
30
|
+
from office365.sharepoint.thresholds import SAFE_PAGE_SIZE, Limits, limit
|
|
30
31
|
from office365.sharepoint.types.resource_path import ResourcePath as SPResPath
|
|
31
32
|
from office365.sharepoint.utilities.move_copy_options import MoveCopyOptions
|
|
32
33
|
from office365.sharepoint.utilities.move_copy_util import MoveCopyUtil
|
|
33
34
|
|
|
34
35
|
if TYPE_CHECKING:
|
|
36
|
+
from office365.runtime.converters.dataframe import DataFrameResult
|
|
35
37
|
from office365.sharepoint.files.collection import FileCollection
|
|
36
38
|
from office365.sharepoint.files.file import File
|
|
37
39
|
from office365.sharepoint.folders.collection import FolderCollection
|
|
38
40
|
|
|
39
|
-
_DEFAULT_CHUNK_SIZE =
|
|
41
|
+
_DEFAULT_CHUNK_SIZE = Limits.UPLOAD_SESSION_CHUNK.value # simple-upload threshold / upload-session chunk
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
class Folder(Entity):
|
|
@@ -192,18 +194,22 @@ class Folder(Entity):
|
|
|
192
194
|
self.context.add_query(placeholder).after_execute(lambda _: _get_folders(self))
|
|
193
195
|
return return_type
|
|
194
196
|
|
|
197
|
+
@limit(Limits.LIST_VIEW, arg="page_size")
|
|
195
198
|
def get_files(
|
|
196
199
|
self,
|
|
197
200
|
recursive: bool = False,
|
|
198
201
|
progress: Optional[Callable[[Progress[File]], None]] = None,
|
|
202
|
+
page_size: int = SAFE_PAGE_SIZE,
|
|
199
203
|
) -> FileCollection:
|
|
200
|
-
"""Retrieves files
|
|
204
|
+
"""Retrieves files (paged, so it works on folders with >5,000 items).
|
|
201
205
|
|
|
202
206
|
Args:
|
|
203
207
|
recursive (bool): Determines whether to enumerate folders recursively
|
|
204
|
-
progress: Optional hook invoked per scanned
|
|
208
|
+
progress: Optional hook invoked per scanned page with a
|
|
205
209
|
``Progress[File]`` snapshot (``done`` = files discovered so far;
|
|
206
|
-
``items`` = the files found in the
|
|
210
|
+
``items`` = the files found in the page just scanned).
|
|
211
|
+
page_size (int): Items per page (kept below the 5,000-item list view
|
|
212
|
+
threshold so large folders are read without being throttled).
|
|
207
213
|
|
|
208
214
|
The fluent ``.select([...])`` / ``.expand([...])`` applied to the returned
|
|
209
215
|
collection is honored on every per-folder file load.
|
|
@@ -216,21 +222,35 @@ class Folder(Entity):
|
|
|
216
222
|
return_type = FileCollection(self.context, resource_path, self)
|
|
217
223
|
|
|
218
224
|
def _get_files(parent: Folder) -> None:
|
|
219
|
-
def _on_files_loaded(col) -> None:
|
|
220
|
-
for file in col:
|
|
221
|
-
return_type.add_child(file)
|
|
222
|
-
if callable(progress):
|
|
223
|
-
progress(Progress(done=len(return_type), stage="scanning", items=list(col)))
|
|
224
|
-
if recursive:
|
|
225
|
-
subfolders = parent.folders
|
|
226
|
-
subfolders.get().after_execute(lambda _: [_get_files(folder) for folder in subfolders])
|
|
227
|
-
|
|
228
225
|
files = parent.files
|
|
229
226
|
return_type.query_options.apply_to(files)
|
|
230
227
|
if return_type.query_options.select:
|
|
231
228
|
fields = sorted({"Id", "Name", "ServerRelativeUrl"} | set(return_type.query_options.select))
|
|
232
229
|
files.select(fields)
|
|
233
|
-
|
|
230
|
+
seen = {"count": 0}
|
|
231
|
+
|
|
232
|
+
def _on_files_page(col: FileCollection) -> None:
|
|
233
|
+
new_files = list(col)[seen["count"] :]
|
|
234
|
+
seen["count"] = len(col)
|
|
235
|
+
for file in new_files:
|
|
236
|
+
return_type.add_child(file)
|
|
237
|
+
if callable(progress):
|
|
238
|
+
progress(Progress(done=len(return_type), stage="scanning", items=new_files))
|
|
239
|
+
if recursive and not col.has_next:
|
|
240
|
+
_scan_subfolders(parent)
|
|
241
|
+
|
|
242
|
+
files.get_all(page_size, page_loaded=_on_files_page)
|
|
243
|
+
|
|
244
|
+
def _scan_subfolders(parent: Folder) -> None:
|
|
245
|
+
subfolders = parent.folders
|
|
246
|
+
seen = {"count": 0}
|
|
247
|
+
|
|
248
|
+
def _on_folders_page(col: "FolderCollection") -> None:
|
|
249
|
+
for folder in list(col)[seen["count"] :]:
|
|
250
|
+
_get_files(folder)
|
|
251
|
+
seen["count"] = len(col)
|
|
252
|
+
|
|
253
|
+
subfolders.get_all(page_size, page_loaded=_on_folders_page)
|
|
234
254
|
|
|
235
255
|
placeholder = DeferredOperationQuery(self.context)
|
|
236
256
|
self.context.add_query(placeholder).after_execute(lambda _: _get_files(self))
|
|
@@ -443,6 +463,46 @@ class Folder(Entity):
|
|
|
443
463
|
folder = self.ensure_folder("/".join(parts[:-1]))
|
|
444
464
|
return folder.files.upload_content(content, parts[-1], chunk_size, progress)
|
|
445
465
|
|
|
466
|
+
def write_dataframe(
|
|
467
|
+
self,
|
|
468
|
+
relative_path: str,
|
|
469
|
+
df,
|
|
470
|
+
*,
|
|
471
|
+
format: str = "csv", # noqa: A002
|
|
472
|
+
index: bool = False,
|
|
473
|
+
**opts,
|
|
474
|
+
) -> File:
|
|
475
|
+
"""Serialize a pandas DataFrame and write it as a file (CSV/XLSX/...).
|
|
476
|
+
|
|
477
|
+
The DataFrame counterpart of :meth:`upload_file` — it writes the frame's
|
|
478
|
+
**content**, not metadata. CSV is written UTF-8 with a BOM
|
|
479
|
+
(``utf-8-sig``) so Excel opens it with the columns intact;
|
|
480
|
+
``format="xlsx"`` writes a worksheet (requires the ``[excel]`` extra).
|
|
481
|
+
The returned :class:`File` is deferred — the caller executes it.
|
|
482
|
+
|
|
483
|
+
Args:
|
|
484
|
+
relative_path: File name or path relative to this folder.
|
|
485
|
+
df: A pandas DataFrame.
|
|
486
|
+
format: ``"csv"`` (default), ``"xlsx"``/``"excel"``, ``"json"``, ...
|
|
487
|
+
index: Whether to write the DataFrame index (default False).
|
|
488
|
+
opts: Extra kwargs forwarded to the pandas writer.
|
|
489
|
+
"""
|
|
490
|
+
from office365.runtime.converters.dataframe import dataframe_to_bytes
|
|
491
|
+
|
|
492
|
+
return self.upload_file(relative_path, dataframe_to_bytes(df, format, index, **opts))
|
|
493
|
+
|
|
494
|
+
def read_dataframe(self, relative_path: str, *, format: str = "csv", **opts) -> "DataFrameResult": # noqa: A002
|
|
495
|
+
"""Read a file in this folder's **content** into a DataFrame (deferred result).
|
|
496
|
+
|
|
497
|
+
Parses the file content (CSV/XLSX/JSON/Parquet) — not metadata. Run with
|
|
498
|
+
``execute_query()`` and read ``.value``:
|
|
499
|
+
|
|
500
|
+
>>> df = folder.read_dataframe("stocks.csv").execute_query().value
|
|
501
|
+
"""
|
|
502
|
+
url = f"{self.server_relative_url}/{relative_path}".replace("//", "/")
|
|
503
|
+
file = self.context.web.get_file_by_server_relative_url(url)
|
|
504
|
+
return file.read_dataframe(format=format, **opts)
|
|
505
|
+
|
|
446
506
|
def update_document_sharing_info(
|
|
447
507
|
self,
|
|
448
508
|
user_role_assignments: List[UserRoleAssignment],
|
|
@@ -588,7 +648,12 @@ class Folder(Entity):
|
|
|
588
648
|
|
|
589
649
|
@property
|
|
590
650
|
def files(self) -> FileCollection:
|
|
591
|
-
"""Specifies the collection of files contained in the list folder.
|
|
651
|
+
"""Specifies the collection of files contained in the list folder.
|
|
652
|
+
|
|
653
|
+
A single-shot load (``ctx.load(folder, ["Files"])`` / ``.get()``) is trimmed
|
|
654
|
+
at the 5,000-item list view threshold; use :meth:`get_files` (paged) for
|
|
655
|
+
folders that may exceed it.
|
|
656
|
+
"""
|
|
592
657
|
from office365.sharepoint.files.collection import FileCollection
|
|
593
658
|
|
|
594
659
|
return self.properties.get(
|
|
@@ -597,7 +662,12 @@ class Folder(Entity):
|
|
|
597
662
|
|
|
598
663
|
@property
|
|
599
664
|
def folders(self) -> FolderCollection:
|
|
600
|
-
"""Specifies the collection of list folders contained within the list folder.
|
|
665
|
+
"""Specifies the collection of list folders contained within the list folder.
|
|
666
|
+
|
|
667
|
+
A single-shot load (``ctx.load(folder, ["Folders"])`` / ``.get()``) is
|
|
668
|
+
trimmed at the 5,000-item list view threshold; use ``folders.get_all(
|
|
669
|
+
page_size=2000)`` for folders that may exceed it.
|
|
670
|
+
"""
|
|
601
671
|
from office365.sharepoint.folders.collection import FolderCollection
|
|
602
672
|
|
|
603
673
|
return self.properties.get(
|
|
@@ -616,23 +686,23 @@ class Folder(Entity):
|
|
|
616
686
|
"""
|
|
617
687
|
return self.folders.ensure_by_path(relative_path)
|
|
618
688
|
|
|
619
|
-
def ensure_folders(self, relative_paths: Iterable[str]) -> Folder:
|
|
689
|
+
def ensure_folders(self, relative_paths: Iterable[str]) -> list[Folder]:
|
|
620
690
|
"""Ensure a set of nested folder paths under this folder — deduplicated.
|
|
621
691
|
|
|
622
692
|
Since :meth:`ensure_folder` already creates intermediate folders for a
|
|
623
693
|
nested path, only the *deepest* paths are ensured: a path that is an
|
|
624
694
|
ancestor of another is covered by it. All ensures are queued as one
|
|
625
695
|
deferred batch; the caller executes them in a single round-trip.
|
|
626
|
-
Returns ``self`` for chaining.
|
|
627
696
|
|
|
628
697
|
Args:
|
|
629
698
|
relative_paths (Iterable[str]): Paths relative to this folder.
|
|
699
|
+
|
|
700
|
+
Returns:
|
|
701
|
+
list[Folder]: The ensured folders.
|
|
630
702
|
"""
|
|
631
703
|
paths = sorted(set(relative_paths))
|
|
632
704
|
deepest = [path for path in paths if not any(other.startswith(f"{path}/") for other in paths if other != path)]
|
|
633
|
-
for path in deepest
|
|
634
|
-
self.ensure_folder(path)
|
|
635
|
-
return self
|
|
705
|
+
return [self.ensure_folder(path) for path in deepest]
|
|
636
706
|
|
|
637
707
|
@odata(name="ParentFolder")
|
|
638
708
|
@property
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from office365.sharepoint.entity import Entity
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class HtmlPage(Entity):
|
|
9
|
+
@property
|
|
10
|
+
def id_(self) -> Optional[int]:
|
|
11
|
+
"""Gets the Id property"""
|
|
12
|
+
return self.properties.get("Id", None)
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def entity_type_name(self) -> str:
|
|
16
|
+
return "SP.HtmlPages.HtmlPage"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from office365.runtime.paths.resource_path import ResourcePath
|
|
4
|
+
from office365.sharepoint.entity import Entity
|
|
5
|
+
from office365.sharepoint.entity_collection import EntityCollection
|
|
6
|
+
from office365.sharepoint.htmlpages.html_page import HtmlPage
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HtmlPageService(Entity):
|
|
10
|
+
@property
|
|
11
|
+
def pages(self) -> EntityCollection[HtmlPage]:
|
|
12
|
+
"""Gets the Pages property"""
|
|
13
|
+
return self.properties.get(
|
|
14
|
+
"Pages", EntityCollection[HtmlPage](self.context, HtmlPage, ResourcePath("Pages", self.resource_path))
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def entity_type_name(self) -> str:
|
|
19
|
+
return "SP.HtmlPages.HtmlPageService"
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from typing_extensions import Self
|
|
2
|
+
|
|
3
|
+
from office365.runtime.queries.service_operation import ServiceOperationQuery
|
|
1
4
|
from office365.sharepoint.entity import Entity
|
|
2
5
|
|
|
3
6
|
|
|
@@ -7,3 +10,9 @@ class IRMigration(Entity):
|
|
|
7
10
|
@property
|
|
8
11
|
def entity_type_name(self) -> str:
|
|
9
12
|
return "Microsoft.SharePoint.IR.IRMigration"
|
|
13
|
+
|
|
14
|
+
def delete_and_recreate_ir_list(self) -> Self:
|
|
15
|
+
"""DeleteAndRecreateIRList operation."""
|
|
16
|
+
qry = ServiceOperationQuery(self, "DeleteAndRecreateIRList", None, {}, None, None)
|
|
17
|
+
self.context.add_query(qry)
|
|
18
|
+
return self
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Typed CAML query builder.
|
|
2
|
+
|
|
3
|
+
Build CAML ``ViewXml`` from composable Python objects instead of raw strings::
|
|
4
|
+
|
|
5
|
+
from office365.sharepoint.listitems.caml import Caml, CamlQuery
|
|
6
|
+
|
|
7
|
+
query = (
|
|
8
|
+
CamlQuery.builder()
|
|
9
|
+
.where(Caml.text("Status").eq("Active"))
|
|
10
|
+
.order_by("Created", ascending=False)
|
|
11
|
+
.row_limit(2000)
|
|
12
|
+
.build()
|
|
13
|
+
)
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from office365.sharepoint.listitems.caml.builder import QueryBuilder
|
|
17
|
+
from office365.sharepoint.listitems.caml.expressions import Caml, CamlExpr, Field
|
|
18
|
+
from office365.sharepoint.listitems.caml.fields import FieldRef
|
|
19
|
+
from office365.sharepoint.listitems.caml.query import CamlQuery
|
|
20
|
+
from office365.sharepoint.listitems.caml.values import Value, ValueType
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"Caml",
|
|
24
|
+
"CamlExpr",
|
|
25
|
+
"CamlQuery",
|
|
26
|
+
"Field",
|
|
27
|
+
"FieldRef",
|
|
28
|
+
"QueryBuilder",
|
|
29
|
+
"Value",
|
|
30
|
+
"ValueType",
|
|
31
|
+
]
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Fluent builder for the CAML ``<View>`` document.
|
|
2
|
+
|
|
3
|
+
Assembles ``ViewFields``/``Where``/``GroupBy``/``OrderBy``/``RowLimit``/``Scope``
|
|
4
|
+
into a ``ViewXml`` string (or a :class:`CamlQuery`):
|
|
5
|
+
|
|
6
|
+
from office365.sharepoint.listitems.caml import Caml, CamlQuery
|
|
7
|
+
from office365.sharepoint.views.scope import ViewScope
|
|
8
|
+
|
|
9
|
+
query = (CamlQuery.builder()
|
|
10
|
+
.where(Caml.text("Status").eq("Active"))
|
|
11
|
+
.order_by("Created", ascending=False)
|
|
12
|
+
.row_limit(2000)
|
|
13
|
+
.scope(ViewScope.RecursiveAll)
|
|
14
|
+
.build())
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
20
|
+
from xml.sax.saxutils import quoteattr
|
|
21
|
+
|
|
22
|
+
from typing_extensions import Self
|
|
23
|
+
|
|
24
|
+
from office365.sharepoint.listitems.caml.expressions import And, CamlExpr, _as_field_ref, _fold
|
|
25
|
+
from office365.sharepoint.listitems.caml.fields import FieldRef
|
|
26
|
+
from office365.sharepoint.views.scope import ViewScope
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from office365.sharepoint.listitems.caml.query import CamlQuery
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class QueryBuilder:
|
|
33
|
+
"""Fluent builder that renders the CAML ``<View>`` element."""
|
|
34
|
+
|
|
35
|
+
def __init__(self) -> None:
|
|
36
|
+
self._where: Optional[CamlExpr] = None
|
|
37
|
+
self._order_by: list[FieldRef] = []
|
|
38
|
+
self._group_by: list[FieldRef] = []
|
|
39
|
+
self._view_fields: list[FieldRef] = []
|
|
40
|
+
self._row_limit: Optional[int] = None
|
|
41
|
+
self._paged = True
|
|
42
|
+
self._scope: ViewScope = ViewScope.DefaultValue
|
|
43
|
+
|
|
44
|
+
def where(self, *conditions: CamlExpr) -> Self:
|
|
45
|
+
"""Set the ``<Where>`` filter (multiple conditions are combined with ``<And>``)."""
|
|
46
|
+
if conditions:
|
|
47
|
+
self._where = _fold(And, conditions)
|
|
48
|
+
return self
|
|
49
|
+
|
|
50
|
+
def order_by(self, *fields: Any, ascending: bool = True) -> Self:
|
|
51
|
+
"""Add one or more ``<OrderBy>`` fields (call again to append)."""
|
|
52
|
+
for field in fields:
|
|
53
|
+
ref = _as_field_ref(field)
|
|
54
|
+
self._order_by.append(ref if ref.ascending is not None else ref._copy(ascending=ascending))
|
|
55
|
+
return self
|
|
56
|
+
|
|
57
|
+
def group_by(self, field: Any, *, collapse: bool = True) -> Self:
|
|
58
|
+
"""Add a ``<GroupBy>`` field."""
|
|
59
|
+
ref = _as_field_ref(field)
|
|
60
|
+
self._group_by.append(ref if ref.collapse is not None else ref._copy(collapse=collapse))
|
|
61
|
+
return self
|
|
62
|
+
|
|
63
|
+
def view_fields(self, *names: Any) -> Self:
|
|
64
|
+
"""Add ``<ViewFields>`` entries (a ``str``, ``Field`` or ``FieldRef``)."""
|
|
65
|
+
self._view_fields.extend(_as_field_ref(name) for name in names)
|
|
66
|
+
return self
|
|
67
|
+
|
|
68
|
+
def row_limit(self, top: int, *, paged: bool = True) -> Self:
|
|
69
|
+
"""Set ``<RowLimit>`` (``Paged="TRUE"`` by default)."""
|
|
70
|
+
self._row_limit = top
|
|
71
|
+
self._paged = paged
|
|
72
|
+
return self
|
|
73
|
+
|
|
74
|
+
def scope(self, scope: ViewScope) -> Self:
|
|
75
|
+
"""Set the ``Scope`` attribute of ``<View>``."""
|
|
76
|
+
self._scope = scope
|
|
77
|
+
return self
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def is_paged(self) -> bool:
|
|
81
|
+
"""Whether the query enables server-driven paging (``RowLimit Paged="TRUE"``)."""
|
|
82
|
+
return self._row_limit is not None and self._paged
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def field_refs(self) -> set[str]:
|
|
86
|
+
"""Fields the query filters or sorts on (``ViewFields`` are excluded)."""
|
|
87
|
+
names: set[str] = set()
|
|
88
|
+
if self._where is not None:
|
|
89
|
+
names |= self._where.field_refs
|
|
90
|
+
for ref in (*self._order_by, *self._group_by):
|
|
91
|
+
names.add(ref.name)
|
|
92
|
+
return names
|
|
93
|
+
|
|
94
|
+
def to_xml(self) -> str:
|
|
95
|
+
"""Render the CAML ``<View>`` document."""
|
|
96
|
+
scope = self._scope.value if isinstance(self._scope, ViewScope) else str(self._scope)
|
|
97
|
+
parts = [f"<View Scope={quoteattr(scope)}>"]
|
|
98
|
+
if self._view_fields:
|
|
99
|
+
parts.append("<ViewFields>" + "".join(ref.to_xml() for ref in self._view_fields) + "</ViewFields>")
|
|
100
|
+
query = self._query_xml()
|
|
101
|
+
if query:
|
|
102
|
+
parts.append(query)
|
|
103
|
+
if self._row_limit is not None:
|
|
104
|
+
paged = ' Paged="TRUE"' if self._paged else ""
|
|
105
|
+
parts.append(f"<RowLimit{paged}>{self._row_limit}</RowLimit>")
|
|
106
|
+
parts.append("</View>")
|
|
107
|
+
return "".join(parts)
|
|
108
|
+
|
|
109
|
+
def _query_xml(self) -> str:
|
|
110
|
+
query: list[str] = []
|
|
111
|
+
if self._where is not None:
|
|
112
|
+
query.append(f"<Where>{self._where.to_xml()}</Where>")
|
|
113
|
+
if self._group_by:
|
|
114
|
+
query.append("<GroupBy>" + "".join(ref.to_xml() for ref in self._group_by) + "</GroupBy>")
|
|
115
|
+
if self._order_by:
|
|
116
|
+
query.append("<OrderBy>" + "".join(ref.to_xml() for ref in self._order_by) + "</OrderBy>")
|
|
117
|
+
return "<Query>" + "".join(query) + "</Query>" if query else ""
|
|
118
|
+
|
|
119
|
+
def build(self) -> "CamlQuery":
|
|
120
|
+
"""Build a :class:`CamlQuery` (raw ``ViewXml`` + the expression AST)."""
|
|
121
|
+
from office365.sharepoint.listitems.caml.query import CamlQuery
|
|
122
|
+
|
|
123
|
+
query = CamlQuery()
|
|
124
|
+
query.ViewXml = self.to_xml()
|
|
125
|
+
query._expr = self
|
|
126
|
+
return query
|
|
127
|
+
|
|
128
|
+
def __repr__(self) -> str:
|
|
129
|
+
return self.to_xml()
|