diff --git a/examples/sharepoint/folders/get_system_metadata.py b/examples/sharepoint/folders/get_system_metadata.py
index dbd976a5..46e6dd82 100644
--- a/examples/sharepoint/folders/get_system_metadata.py
+++ b/examples/sharepoint/folders/get_system_metadata.py
@@ -6,16 +6,15 @@
from tests import test_client_credentials, test_team_site_url
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
-folder_url = "Shared Documents/Archive"
-
+list_title = "Docs"
+folder_path = "Archive" # folder relative path
folder_item = (
- ctx.web.get_folder_by_server_relative_url(folder_url)
- .list_item_all_fields.get()
- .execute_query()
-)
-author = (
- ctx.web.site_users.get_by_id(folder_item.get_property("AuthorId"))
+ ctx.web.lists.get_by_title(list_title)
+ .get_item_by_url(folder_path)
+ .select(["Author/Title"])
+ .expand(["Author"])
.get()
.execute_query()
)
-print(author)
+
+print(folder_item.properties.get("Author"))
diff --git a/examples/sharepoint/lists/assessment/broken_tax_field_value.py b/examples/sharepoint/lists/assessment/broken_tax_field_value.py
new file mode 100644
index 00000000..9a0009c5
--- /dev/null
+++ b/examples/sharepoint/lists/assessment/broken_tax_field_value.py
@@ -0,0 +1,24 @@
+"""
+Demonstrates how to perform list/library assessment if taxonomy field value association is broken
+to term set or not.
+
+To prevent this exception to occur:
+'-2146232832, Microsoft.SharePoint.SPFieldValidationException', 'The given guid does not exist in the term store'
+"""
+from office365.runtime.client_request_exception import ClientRequestException
+from office365.sharepoint.client_context import ClientContext
+from office365.sharepoint.taxonomy.field import TaxonomyField
+from tests import test_client_credentials, test_team_site_url
+
+ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
+lib = ctx.web.default_document_library()
+fields = lib.fields.get().execute_query()
+for field in fields:
+ if not isinstance(field, TaxonomyField):
+ continue
+ try:
+ items = lib.items.select([field.internal_name]).top(1).get().execute_query()
+ print(field.internal_name)
+ except ClientRequestException:
+ print(field.is_term_set_valid)
+ print("Error: {0}".format(field.internal_name))
diff --git a/generator/metadata/SharePoint.xml b/generator/metadata/SharePoint.xml
index c9b1d714..1288095a 100644
--- a/generator/metadata/SharePoint.xml
+++ b/generator/metadata/SharePoint.xml
@@ -8226,6 +8226,9 @@
+
+
+
@@ -10619,6 +10622,9 @@
+
+
+
@@ -14006,7 +14012,6 @@
-
@@ -15990,6 +15995,10 @@
+
+
+
+
@@ -19424,6 +19433,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -19562,6 +19583,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -25251,6 +25299,9 @@
+
+
+
@@ -30776,6 +30827,11 @@
+
+
+
+
+
@@ -30845,6 +30901,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -35608,6 +35675,7 @@
+
@@ -38100,12 +38168,6 @@
-
-
-
-
-
-
@@ -38175,10 +38237,6 @@
-
-
-
-
@@ -38235,15 +38293,6 @@
-
-
-
-
-
-
-
-
-
@@ -38260,10 +38309,6 @@
-
-
-
-
diff --git a/office365/onedrive/permissions/collection.py b/office365/onedrive/permissions/collection.py
index ec4ea5ae..f4524664 100644
--- a/office365/onedrive/permissions/collection.py
+++ b/office365/onedrive/permissions/collection.py
@@ -71,9 +71,7 @@ def _add():
def delete(self, roles, identity):
# type: (list[str], Application|User|Group|Device) -> Permission
- """
- Deletes the permission.
- """
+ """Deletes the permission."""
def _delete(col):
pass
@@ -85,9 +83,7 @@ def _identity_loaded():
return self
def delete_all(self):
- """
- Remove all access to resource
- """
+ """Remove all access to resource"""
def _after_loaded(return_type):
# type: (PermissionCollection) -> None
diff --git a/office365/runtime/client_object.py b/office365/runtime/client_object.py
index 6eb4e04c..08f4003c 100644
--- a/office365/runtime/client_object.py
+++ b/office365/runtime/client_object.py
@@ -90,7 +90,6 @@ def get(self):
def is_property_available(self, name):
# type: (str) -> bool
"""Returns a Boolean value that indicates whether the specified property has been retrieved or set.
-
:param str name: A property name
"""
if name in self.properties:
@@ -116,7 +115,7 @@ def select(self, names):
def remove_from_parent_collection(self):
if self._parent_collection is None:
- return
+ return self
self._parent_collection.remove_child(self)
return self
diff --git a/office365/runtime/client_object_collection.py b/office365/runtime/client_object_collection.py
index db3ea9d4..3e340f9f 100644
--- a/office365/runtime/client_object_collection.py
+++ b/office365/runtime/client_object_collection.py
@@ -1,4 +1,4 @@
-from typing import Callable, Generic, Iterator, List, Optional, Type, TypeVar
+from typing import Any, Callable, Generic, Iterator, List, Optional, Type, TypeVar
from typing_extensions import Self
@@ -110,7 +110,6 @@ def filter(self, expression):
# type: (str) -> Self
"""
Allows clients to filter a collection of resources that are addressed by a request URL
-
:param str expression: Filter expression, for example: 'Id eq 123'
"""
self.query_options.filter = expression
@@ -134,17 +133,13 @@ def skip(self, value):
def top(self, value):
# type: (int) -> Self
- """
- Specifies the number of items in the queried collection to be included in the result
- """
+ """Specifies the number of items in the queried collection to be included in the result"""
self.query_options.top = value
return self
def paged(self, page_size=None, page_loaded=None):
# type: (int, Callable[[Self], None]) -> Self
- """
- Retrieves via server-driven paging mode
- """
+ """Retrieves via server-driven paging mode"""
self._paged_mode = True
if callable(page_loaded):
self._page_loaded += page_loaded
@@ -152,6 +147,12 @@ def paged(self, page_size=None, page_loaded=None):
self.top(page_size)
return self
+ def after_execute(self, action, *args, **kwargs):
+ # type: (Callable[[Self, Any, Any], None], Any, Any) -> Self
+ super(ClientObjectCollection, self).after_execute(action, *args, **kwargs)
+ self._page_loaded += action
+ return self
+
def get(self):
# type: () -> Self
@@ -196,22 +197,22 @@ def _construct_request(request):
def first(self, expression):
# type: (str) -> T
"""Return the first Entity instance that matches current query
-
:param str expression: Filter expression
"""
return_type = self.create_typed_object()
self.add_child(return_type)
- key = return_type.property_ref_name
def _after_loaded(col):
# type: (ClientObjectCollection) -> None
if len(col) < 1:
message = "Not found for filter: {0}".format(self.query_options.filter)
raise ValueError(message)
- return_type.set_property(key, col[0].get_property(key))
+ [
+ return_type.set_property(k, v, False)
+ for k, v in col[0].properties.items()
+ ]
- self.filter(expression).top(1)
- self.context.load(self, [key], after_loaded=_after_loaded)
+ self.get().filter(expression).top(1).after_execute(_after_loaded)
return return_type
def single(self, expression):
@@ -237,8 +238,7 @@ def _after_loaded(col):
for k, v in col[0].properties.items()
]
- self.filter(expression).top(2)
- self.context.load(self, after_loaded=_after_loaded)
+ self.get().filter(expression).top(2).after_execute(_after_loaded)
return return_type
@property
diff --git a/office365/runtime/client_result.py b/office365/runtime/client_result.py
index c00a8452..5a44ddbe 100644
--- a/office365/runtime/client_result.py
+++ b/office365/runtime/client_result.py
@@ -59,9 +59,7 @@ def execute_query(self):
def execute_query_retry(
self, max_retry=5, timeout_secs=5, success_callback=None, failure_callback=None
):
- """
- Executes the current set of data retrieval queries and method invocations and retries it if needed.
- """
+ """Executes the current set of data retrieval queries and method invocations and retries it if needed."""
self._context.execute_query_retry(
max_retry=max_retry,
timeout_secs=timeout_secs,
diff --git a/office365/runtime/odata/type.py b/office365/runtime/odata/type.py
index 52d3d55f..16548e3e 100644
--- a/office365/runtime/odata/type.py
+++ b/office365/runtime/odata/type.py
@@ -64,6 +64,8 @@ def try_parse_datetime(value):
"""
if value is None:
return None
+ elif isinstance(value, datetime.datetime):
+ return value
known_formats = [
"%Y-%m-%dT%H:%M:%SZ",
diff --git a/office365/sharepoint/files/checked_out_file_collection.py b/office365/sharepoint/files/checked_out_file_collection.py
index 4439fd0f..fab30e55 100644
--- a/office365/sharepoint/files/checked_out_file_collection.py
+++ b/office365/sharepoint/files/checked_out_file_collection.py
@@ -3,7 +3,7 @@
from office365.sharepoint.files.checked_out_file import CheckedOutFile
-class CheckedOutFileCollection(EntityCollection):
+class CheckedOutFileCollection(EntityCollection[CheckedOutFile]):
def __init__(self, context, resource_path=None):
super(CheckedOutFileCollection, self).__init__(
context, CheckedOutFile, resource_path
diff --git a/office365/sharepoint/files/collection.py b/office365/sharepoint/files/collection.py
index fc2f5744..b63456ab 100644
--- a/office365/sharepoint/files/collection.py
+++ b/office365/sharepoint/files/collection.py
@@ -1,24 +1,31 @@
import hashlib
import os
import uuid
-from typing import IO, Callable
+from typing import IO, TYPE_CHECKING, Callable
from office365.runtime.client_result import ClientResult
+from office365.runtime.paths.resource_path import ResourcePath
from office365.runtime.paths.service_operation import ServiceOperationPath
from office365.runtime.queries.service_operation import ServiceOperationQuery
+from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.entity_collection import EntityCollection
from office365.sharepoint.files.creation_information import FileCreationInformation
from office365.sharepoint.files.file import File
from office365.sharepoint.types.resource_path import ResourcePath as SPResPath
+if TYPE_CHECKING:
+ from office365.sharepoint.folders.folder import Folder
+
class FileCollection(EntityCollection[File]):
"""Represents a collection of File resources."""
def __init__(self, context, resource_path=None, parent=None):
+ # type: (ClientContext, ResourcePath, Folder) -> None
super(FileCollection, self).__init__(context, File, resource_path, parent)
def upload(self, path_or_file):
+ # type: (str|IO) -> File
"""Uploads a file into folder.
Note: This method only supports files up to 4MB in size!
@@ -136,7 +143,7 @@ def add_template_file(self, url_of_file, template_file_type):
return_type = File(self.context)
self.add_child(return_type)
- def _parent_folder_loaded():
+ def _add_template_file():
params = {
"urlOfFile": str(
SPResPath.create_relative(
@@ -150,17 +157,24 @@ def _parent_folder_loaded():
)
self.context.add_query(qry)
- self.parent.ensure_property("ServerRelativeUrl", _parent_folder_loaded)
+ self.parent.ensure_property("ServerRelativeUrl", _add_template_file)
return return_type
def get_by_url(self, url):
+ # type: (str) -> File
"""Retrieve File object by url"""
return File(
self.context, ServiceOperationPath("GetByUrl", [url], self.resource_path)
)
def get_by_id(self, _id):
+ # type: (int) -> File
"""Gets the File with the specified ID."""
return File(
self.context, ServiceOperationPath("getById", [_id], self.resource_path)
)
+
+ @property
+ def parent(self):
+ # type: () -> Folder
+ return self._parent
diff --git a/office365/sharepoint/files/versions/event.py b/office365/sharepoint/files/versions/event.py
index c1e060db..60f30163 100644
--- a/office365/sharepoint/files/versions/event.py
+++ b/office365/sharepoint/files/versions/event.py
@@ -1,3 +1,5 @@
+from typing import Optional
+
from office365.runtime.client_value_collection import ClientValueCollection
from office365.sharepoint.entity import Entity
from office365.sharepoint.sharing.shared_with_user import SharedWithUser
@@ -8,14 +10,14 @@ class FileVersionEvent(Entity):
@property
def event_type(self):
+ # type: () -> Optional[str]
"""Returns the type of the event."""
return self.properties.get("EventType", None)
@property
def editor(self):
- """Returns the name of the user who initiated the event.
- :rtype: str or None
- """
+ # type: () -> Optional[str]
+ """Returns the name of the user who initiated the event."""
return self.properties.get("Editor", None)
@property
@@ -25,6 +27,7 @@ def shared_by_user(self):
@property
def shared_with_users(self):
+ # type: () -> ClientValueCollection[SharedWithUser]
"""Returns the array of users that have been shared in sharing action for the change log."""
return self.properties.get(
"SharedWithUsers", ClientValueCollection(SharedWithUser)
diff --git a/office365/sharepoint/files/versions/version.py b/office365/sharepoint/files/versions/version.py
index 595b339f..682479bf 100644
--- a/office365/sharepoint/files/versions/version.py
+++ b/office365/sharepoint/files/versions/version.py
@@ -104,8 +104,8 @@ def get_property(self, name, default_value=None):
def set_property(self, key, value, persist_changes=True):
super(FileVersion, self).set_property(key, value, persist_changes)
- if self._resource_path is None:
- if key == self.property_ref_name:
+ if key.lower() == self.property_ref_name.lower():
+ if self._resource_path is None:
self._resource_path = KeyPath(
value, self.parent_collection.resource_path
)
diff --git a/office365/sharepoint/folders/folder.py b/office365/sharepoint/folders/folder.py
index 91bc6d6b..543ccee4 100644
--- a/office365/sharepoint/folders/folder.py
+++ b/office365/sharepoint/folders/folder.py
@@ -39,7 +39,6 @@ def __repr__(self):
def from_url(abs_url):
"""
Addresses a Folder by absolute url
-
:type abs_url: str
"""
from office365.sharepoint.client_context import ClientContext
@@ -151,9 +150,7 @@ def _update_folder(url):
self.set_property("ServerRelativePath", url)
def _move_to_using_path(destination_folder):
- """
- :type destination_folder: Folder
- """
+ # type: ("Folder") -> None
destination_url = "/".join(
[str(destination_folder.server_relative_path), self.name]
)
@@ -515,9 +512,7 @@ def name(self):
@property
def is_wopi_enabled(self):
# type: () -> Optional[bool]
- """
- Indicates whether the folder is enabled for WOPI default action.
- """
+ """Indicates whether the folder is enabled for WOPI default action."""
return self.properties.get("IsWOPIEnabled", None)
@property
@@ -571,9 +566,7 @@ def time_created(self):
@property
def serverRelativeUrl(self):
# type: () -> Optional[str]
- """
- Gets the server-relative URL of the list folder.
- """
+ """Gets the server-relative URL of the list folder."""
return self.properties.get("ServerRelativeUrl", None)
@property
diff --git a/office365/sharepoint/listitems/collection.py b/office365/sharepoint/listitems/collection.py
index 167f47d1..507bd9fa 100644
--- a/office365/sharepoint/listitems/collection.py
+++ b/office365/sharepoint/listitems/collection.py
@@ -31,3 +31,7 @@ def get_by_string_id(self, s_id):
self.context,
ServiceOperationPath("GetByStringId", {"sId": s_id}, self.resource_path),
)
+
+ def get_by_url(self, url):
+ """Returns the list item with the specified site or server relative url."""
+ return self.single("FileRef eq '{0}'".format(url))
diff --git a/office365/sharepoint/listitems/listitem.py b/office365/sharepoint/listitems/listitem.py
index 00b6212c..d31c8bd6 100644
--- a/office365/sharepoint/listitems/listitem.py
+++ b/office365/sharepoint/listitems/listitem.py
@@ -241,9 +241,7 @@ def _property_resolved():
return return_type
def unshare(self):
- """
- Unshare a ListItem (file or folder facet)
- """
+ """Unshare a ListItem (file or folder facet)"""
return_type = SharingResult(self.context)
def _property_resolved():
@@ -372,10 +370,8 @@ def parse_and_set_field_value(self, field_name, value):
@property
def display_name(self):
- """Specifies the display name of the list item.
-
- :rtype: str or None
- """
+ # type: () -> Optional[str]
+ """Specifies the display name of the list item."""
return self.properties.get("DisplayName", None)
@property
@@ -441,34 +437,26 @@ def effective_base_permissions(self):
@property
def field_values(self):
+ # type: () -> Optional[dict]
"""Gets a collection of key/value pairs containing the names and values for the fields of the list item."""
return self.properties.get("FieldValues", None)
@property
def comments_disabled(self):
- """
- Indicates whether comments for this item are disabled or not.
-
- :rtype: bool or None
- """
+ # type: () -> Optional[bool]
+ """Indicates whether comments for this item are disabled or not."""
return self.properties.get("CommentsDisabled", None)
@property
def file_system_object_type(self):
- """
- Gets a value that specifies whether the list item is a file or a list folder.
-
- :rtype: str or None
- """
+ # type: () -> Optional[str]
+ """Gets a value that specifies whether the list item is a file or a list folder"""
return self.properties.get("FileSystemObjectType", None)
@property
def id(self):
- """
- Gets a value that specifies the list item identifier.
-
- :rtype: int
- """
+ # type: () -> Optional[int]
+ """Gets a value that specifies the list item identifier."""
return self.properties.get("Id", None)
@property
@@ -477,6 +465,7 @@ def compliance_info(self):
@property
def comments_disabled_scope(self):
+ # type: () -> Optional[str]
"""Indicates at what scope comments are disabled."""
return self.properties.get("CommentsDisabledScope", None)
@@ -502,9 +491,7 @@ def field_values_as_html(self):
@property
def liked_by_information(self):
- """
- Gets a value that specifies the list item identifier.
- """
+ """Gets a value that specifies the list item identifier."""
return self.properties.get(
"LikedByInformation",
LikedByInformation(
@@ -570,17 +557,17 @@ def set_property(self, name, value, persist_changes=True):
super(ListItem, self).set_property(name, value, persist_changes)
# fallback: create a new resource path
- if self._resource_path is None and self.parent_collection is not None:
- if name == "Id":
+ if name == "Id":
+ if self._resource_path is None and self.parent_collection is not None:
self._resource_path = KeyPath(
value, self.parent_collection.resource_path
)
return self
def _set_taxonomy_field_value(self, name, value):
+ # type: (str, TaxonomyFieldValueCollection) -> None
"""
Sets taxonomy field value
-
:param str name: Taxonomy field name
:param TaxonomyFieldValueCollection value: Taxonomy field value
"""
diff --git a/office365/sharepoint/lists/list.py b/office365/sharepoint/lists/list.py
index 4017cce5..dfa0e988 100644
--- a/office365/sharepoint/lists/list.py
+++ b/office365/sharepoint/lists/list.py
@@ -1,5 +1,6 @@
+import os
from datetime import datetime
-from typing import Optional
+from typing import AnyStr, Optional
from office365.runtime.client_result import ClientResult
from office365.runtime.client_value_collection import ClientValueCollection
@@ -7,6 +8,7 @@
from office365.runtime.paths.service_operation import ServiceOperationPath
from office365.runtime.queries.service_operation import ServiceOperationQuery
from office365.sharepoint.changes.collection import ChangeCollection
+from office365.sharepoint.changes.log_item_query import ChangeLogItemQuery
from office365.sharepoint.changes.query import ChangeQuery
from office365.sharepoint.changes.token import ChangeToken
from office365.sharepoint.contenttypes.collection import ContentTypeCollection
@@ -133,9 +135,7 @@ def get_bloom_filter(self, start_item_id=None):
return return_type
def get_metadata_navigation_settings(self):
- """
- Retrieves the configured metadata navigation settings for the list.
- """
+ """Retrieves the configured metadata navigation settings for the list."""
from office365.sharepoint.navigation.metadata_settings import (
MetadataNavigationSettings,
)
@@ -153,12 +153,10 @@ def _loaded():
return return_type
def get_sharing_settings(self):
- """
- Retrieves a sharing settings for a List
- """
+ """Retrieves a sharing settings for a List"""
return_type = ObjectSharingSettings(self.context)
- def _list_loaded():
+ def _get_sharing_settings():
from office365.sharepoint.webs.web import Web
list_abs_path = SPResPath.create_absolute(
@@ -168,7 +166,7 @@ def _list_loaded():
self.context, str(list_abs_path), return_type=return_type
)
- self.ensure_property("RootFolder", _list_loaded)
+ self.ensure_property("RootFolder", _get_sharing_settings)
return return_type
def get_site_script(self, options=None):
@@ -190,9 +188,7 @@ def _list_loaded():
return return_type
def get_all_rules(self):
- """
- Retrieves rules of a List
- """
+ """Retrieves rules of a List"""
return_type = ClientResult(self.context, ClientValueCollection(SPListRule))
qry = ServiceOperationQuery(self, "GetAllRules", None, None, None, return_type)
self.context.add_query(qry)
@@ -390,11 +386,10 @@ def get_lookup_field_choices(self, target_field_name, paging_info=None):
return return_type
def get_list_item_changes_since_token(self, query):
+ # type: (ChangeLogItemQuery) -> ClientResult[AnyStr]
"""
Returns the changes made to the list since the date and time specified in the change token defined
by the query input parameter.
-
- :type query: office365.sharepoint.changes.log_item_query.ChangeLogItemQuery
"""
return_type = ClientResult(self.context, bytes())
payload = {"query": query}
@@ -437,7 +432,6 @@ def save_as_template(self, file_name, name, description, save_data):
:param str description: A string that contains the description for the list template.
:param str name: A string that contains the title for the list template.
:param str file_name: A string that contains the file name for the list template with an .stp extension.
- :return:
"""
payload = {
"strFileName": file_name,
@@ -460,11 +454,10 @@ def get_item_by_unique_id(self, unique_id):
)
def get_web_dav_url(self, source_url):
+ # type: (str) -> ClientResult[str]
"""
Gets the trusted URL for opening the folder in Explorer view.
-
:param str source_url: The URL of the current folder the user is in.
- :return: ClientResult
"""
return_type = ClientResult(self.context, str())
@@ -476,10 +469,8 @@ def get_web_dav_url(self, source_url):
return return_type
def get_items(self, caml_query=None):
- """Returns a collection of items from the list based on the specified query.
-
- :type caml_query: CamlQuery
- """
+ # type: (CamlQuery) -> ListItemCollection
+ """Returns a collection of items from the list based on the specified query."""
if not caml_query:
caml_query = CamlQuery.create_all_items_query()
return_type = ListItemCollection(self.context, self.items.resource_path)
@@ -585,14 +576,29 @@ def add_validate_update_item(self, create_info, form_values=None):
return return_type
def get_item_by_id(self, item_id):
- """Returns the list item with the specified list item identifier.
- :type item_id: int
- """
+ # type: (int) -> ListItem
+ """Returns the list item with the specified list item identifier."""
return ListItem(
self.context,
ServiceOperationPath("getItemById", [item_id], self.resource_path),
)
+ def get_item_by_url(self, url):
+ # type: (str) -> ListItem
+ """Returns the list item with the specified site or server relative url."""
+ return_type = ListItem(self.context)
+ self.items.add_child(return_type)
+
+ def _after_loaded(item):
+ [return_type.set_property(k, v, False) for k, v in item.properties.items()]
+
+ def _get_item_by_url():
+ path = os.path.join(self.root_folder.serverRelativeUrl, url)
+ self.items.get_by_url(path).after_execute(_after_loaded, execute_first=True)
+
+ self.ensure_property("RootFolder", _get_item_by_url)
+ return return_type
+
def get_view(self, view_id):
"""Returns the list view with the specified view identifier.
:type view_id: str
@@ -629,10 +635,9 @@ def get_checked_out_files(self):
return return_type
def reserve_list_item_id(self):
- """
- Reserves the returned list item identifier for the idempotent creation of a list item.
- """
- return_type = ClientResult(self.context, int()) # type: ClientResult[int]
+ # type: () -> ClientResult[int]
+ """Reserves the returned list item identifier for the idempotent creation of a list item."""
+ return_type = ClientResult(self.context, int())
qry = ServiceOperationQuery(
self, "ReserveListItemId", None, None, None, return_type
)
@@ -672,8 +677,7 @@ def get_special_folder_url(self, folder_type, force_create, existing_folder_guid
@property
def id(self):
# type: () -> Optional[str]
- """
- Gets a value that specifies the list identifier."""
+ """Gets a value that specifies the list identifier."""
return self.properties.get("Id", None)
@property
@@ -691,25 +695,19 @@ def author(self):
@property
def allow_content_types(self):
# type: () -> Optional[bool]
- """
- Specifies whether the list supports content types.
- """
+ """Specifies whether the list supports content types."""
return self.properties.get("AllowContentTypes", None)
@property
def allow_deletion(self):
# type: () -> Optional[bool]
- """
- Specifies whether the list could be deleted.
- """
+ """Specifies whether the list could be deleted."""
return self.properties.get("AllowDeletion", None)
@property
def base_template(self):
# type: () -> Optional[int]
- """
- Specifies the list server template of the list.
- """
+ """Specifies the list server template of the list."""
return self.properties.get("BaseTemplate", None)
@property
@@ -740,16 +738,12 @@ def created(self):
@property
def default_display_form_url(self):
# type: () -> Optional[str]
- """
- Specifies the location of the default display form for the list.
- """
+ """Specifies the location of the default display form for the list."""
return self.properties.get("DefaultDisplayFormUrl", None)
@property
def default_view_path(self):
- """
- Specifies the server-relative URL of the default view for the list.
- """
+ """Specifies the server-relative URL of the default view for the list."""
return self.properties.get("DefaultViewPath", SPResPath())
@property
@@ -803,9 +797,7 @@ def data_source(self):
@property
def default_edit_form_url(self):
# type: () -> Optional[str]
- """
- Gets a value that specifies the URL of the edit form to use for list items in the list.
- """
+ """Gets a value that specifies the URL of the edit form to use for list items in the list."""
return self.properties.get("DefaultEditFormUrl", None)
@property
@@ -871,9 +863,7 @@ def enable_attachments(self):
@property
def enable_folder_creation(self):
# type: () -> Optional[bool]
- """
- Specifies whether new list folders can be added to the list.
- """
+ """Specifies whether new list folders can be added to the list."""
return self.properties.get("EnableFolderCreation", None)
@enable_folder_creation.setter
@@ -884,17 +874,13 @@ def enable_folder_creation(self, value):
@property
def enable_minor_versions(self):
# type: () -> Optional[bool]
- """
- Specifies whether minor versions are enabled for the list.
- """
+ """Specifies whether minor versions are enabled for the list."""
return self.properties.get("EnableMinorVersions", None)
@property
def enable_moderation(self):
# type: () -> Optional[bool]
- """
- Specifies whether content approval is enabled for the list.
- """
+ """Specifies whether content approval is enabled for the list."""
return self.properties.get("EnableModeration", None)
@property
@@ -905,9 +891,7 @@ def enable_request_sign_off(self):
@property
def enable_versioning(self):
# type: () -> Optional[bool]
- """
- Specifies whether content approval is enabled for the list.
- """
+ """Specifies whether content approval is enabled for the list."""
return self.properties.get("EnableVersioning", None)
@property
diff --git a/office365/sharepoint/tenant/administration/internal/permission_grant.py b/office365/sharepoint/tenant/administration/internal/permission_grant.py
new file mode 100644
index 00000000..c0bc861b
--- /dev/null
+++ b/office365/sharepoint/tenant/administration/internal/permission_grant.py
@@ -0,0 +1,7 @@
+from office365.sharepoint.entity import Entity
+
+
+class SPO3rdPartyAADPermissionGrant(Entity):
+ @property
+ def entity_type_name(self):
+ return "Microsoft.Online.SharePoint.TenantAdministration.Internal.SPO3rdPartyAADPermissionGrant"
diff --git a/tests/sharepoint/test_file.py b/tests/sharepoint/test_file.py
index 0823f41b..3c2183f2 100644
--- a/tests/sharepoint/test_file.py
+++ b/tests/sharepoint/test_file.py
@@ -83,8 +83,9 @@ def test_10_list_file_versions(self):
def test_11_delete_file_version(self):
versions = self.__class__.file.versions.top(1).get().execute_query()
self.assertEqual(len(versions), 1)
- self.assertIsNotNone(versions[0].resource_path)
- versions[0].delete_object().execute_query()
+ first_version = versions[0]
+ self.assertIsNotNone(first_version.resource_path)
+ first_version.delete_object().execute_query()
def test_13_download_file_content(self):
result = self.__class__.file.get_content().execute_query()