Skip to content

Commit cb5b9d5

Browse files
committed
SharePoint API: ListItem.system_update for document fix
1 parent 8bad836 commit cb5b9d5

File tree

9 files changed

+90
-16
lines changed

9 files changed

+90
-16
lines changed

examples/sharepoint/listitems/get_deleted.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
from tests import test_client_credentials, test_team_site_url
77

88
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
9-
# result = ctx.web.default_document_library().get_changes(ChangeQuery(list_=False, item=True)).execute_query()
109
result = (
1110
ctx.web.recycle_bin.get().execute_query()
12-
) # filter("ItemType eq 1").execute_query()
11+
)
1312
for item in result:
1413
print(item.properties)

examples/sharepoint/listitems/system_update2.py renamed to examples/sharepoint/listitems/system_update_alt.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
ctx = ClientContext(test_site_url).with_credentials(test_client_credentials)
77

88
target_list = ctx.web.lists.get_by_title("Documents")
9-
items = target_list.items.get().top(1).execute_query()
9+
items = target_list.items.get().filter("FSObjType eq 0").top(1).execute_query()
1010
if len(items) == 0:
1111
sys.exit("No items were found")
1212

1313
item = items[0]
14+
item.set_property("Title", "Some title goes here 123..")
1415
item.system_update().execute_query()

office365/directory/applications/application.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ def spa(self):
231231
@property
232232
def key_credentials(self):
233233
"""The collection of key credentials associated with the application. Not nullable."""
234-
self._ser_property_names.append("keyCredentials")
234+
self._properties_to_persist.append("keyCredentials")
235235
return self.properties.setdefault(
236236
"keyCredentials", ClientValueCollection(KeyCredential)
237237
)

office365/runtime/client_object.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(self, context, resource_path=None, parent_collection=None):
3030
# type: (ClientRuntimeContext, Optional[ResourcePath], Optional[ClientObjectCollection]) -> None
3131
"""Base client object which define named properties and relationships of an entity."""
3232
self._properties = {}
33-
self._ser_property_names = []
33+
self._properties_to_persist = []
3434
self._query_options = QueryOptions()
3535
self._parent_collection = parent_collection
3636
self._context = context
@@ -43,9 +43,9 @@ def clear_state(self):
4343
self._properties = {
4444
k: v
4545
for k, v in self._properties.items()
46-
if k not in self._ser_property_names
46+
if k not in self._properties_to_persist
4747
}
48-
self._ser_property_names = []
48+
self._properties_to_persist = []
4949
self._query_options = QueryOptions()
5050
return self
5151

@@ -139,8 +139,8 @@ def _persist_changes(self, name):
139139
Marks a property as a serializable
140140
:param str name: A property name
141141
"""
142-
if name not in self._ser_property_names:
143-
self._ser_property_names.append(name)
142+
if name not in self._properties_to_persist:
143+
self._properties_to_persist.append(name)
144144
return self
145145

146146
def get_property(self, name, default_value=None):
@@ -155,7 +155,7 @@ def set_property(self, name, value, persist_changes=True):
155155
# type: (str|int, P_T, bool) -> Self
156156
"""Sets property value"""
157157
if persist_changes:
158-
self._ser_property_names.append(name)
158+
self._properties_to_persist.append(name)
159159

160160
typed_value = self.get_property(name)
161161
if isinstance(typed_value, (ClientObject, ClientValue)):
@@ -242,6 +242,14 @@ def query_options(self):
242242
def properties(self):
243243
return self._properties
244244

245+
@property
246+
def persistable_properties(self):
247+
return {
248+
k: self.get_property(k)
249+
for k in self._properties_to_persist
250+
if k in self._properties
251+
}
252+
245253
@property
246254
def parent_collection(self):
247255
"""Parent collection"""
@@ -254,7 +262,7 @@ def to_json(self, json_format=None):
254262
ser_prop_names = [n for n in self._properties.keys()]
255263
include_control_info = False
256264
else:
257-
ser_prop_names = [n for n in self._ser_property_names]
265+
ser_prop_names = [n for n in self._properties_to_persist]
258266
include_control_info = (
259267
self.entity_type_name is not None
260268
and json_format.include_control_information

office365/sharepoint/listitems/listitem.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ def validate_update_list_item(
276276
"""Validates and sets the values of the specified collection of fields for the list item.
277277
278278
:param dict form_values: Specifies a collection of field internal names and values for the given field
279-
:param dict new_document_update: Specifies whether the list item is a document being updated after upload.
279+
:param bool new_document_update: Specifies whether the list item is a document being updated after upload.
280280
:param str checkin_comment: Check-in comment, if any. This parameter is only applicable when the list item
281281
is checked out.
282282
:param bool or None dates_in_utc:
@@ -313,8 +313,46 @@ def update(self):
313313

314314
def system_update(self):
315315
"""Update the list item."""
316-
qry = ServiceOperationQuery(self, "SystemUpdate")
317-
self.context.add_query(qry)
316+
317+
sys_metadata = ["EditorId", "Modified"]
318+
319+
def _after_system_update(result):
320+
# type: (ClientResult[ClientValueCollection[ListItemFormUpdateValue]]) -> None
321+
has_any_error = any([item.HasException for item in result.value])
322+
if has_any_error:
323+
raise ValueError(
324+
"Update ListItem failed"
325+
)
326+
327+
def _system_update():
328+
from office365.sharepoint.fields.user_value import FieldUserValue
329+
330+
form_values = self.persistable_properties
331+
for n in sys_metadata:
332+
if n == "Id":
333+
pass
334+
elif n.endswith("Id"):
335+
user = self.context.web.site_users.get_by_id(self.get_property(n))
336+
form_values[n[:-2]] = FieldUserValue.from_user(user)
337+
else:
338+
form_values[n] = self.get_property(n)
339+
340+
self.validate_update_list_item(
341+
form_values=form_values,
342+
dates_in_utc=True,
343+
new_document_update=True,
344+
).after_execute(_after_system_update)
345+
346+
347+
def _list_loaded():
348+
if self.parent_list.base_template == 101:
349+
self.ensure_properties(sys_metadata, _system_update)
350+
else:
351+
next_qry = ServiceOperationQuery(self, "SystemUpdate")
352+
self.context.add_query(next_qry)
353+
354+
self.parent_list.ensure_properties(["BaseTemplate"], _list_loaded)
355+
#self.ensure_properties(sys_metadata, _system_update)
318356
return self
319357

320358
def update_overwrite_version(self):
@@ -378,7 +416,7 @@ def parent_list(self):
378416
"""Get parent List"""
379417
from office365.sharepoint.lists.list import List
380418

381-
return self.properties.get(
419+
return self.properties.setdefault(
382420
"ParentList",
383421
List(self.context, ResourcePath("ParentList", self.resource_path)),
384422
)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from office365.runtime.client_value import ClientValue
2+
3+
4+
class InsightsSummaryResponse(ClientValue):
5+
6+
@property
7+
def entity_type_name(self):
8+
return "Microsoft.SharePoint.Administration.TenantAdmin.InsightsSummaryResponse"

office365/sharepoint/tenant/administration/tenant.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,17 @@ def get_ransomware_activities(self):
375375
self.context.add_query(qry)
376376
return return_type
377377

378+
def get_ransomware_events_overview(self):
379+
# type: () -> ClientResult[AnyStr]
380+
""" """
381+
return_type = ClientResult(self.context)
382+
qry = ServiceOperationQuery(
383+
self, "GetRansomwareEventsOverview", None, None, None, return_type
384+
)
385+
self.context.add_query(qry)
386+
return return_type
387+
388+
378389
def get_sp_list_item_count(self, list_name):
379390
# type: (str) -> ClientResult[int]
380391
""" """

tests/sharepoint/test_tenant.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,8 @@ def test_29_get_app_service_principal(self):
209209
def test_30_get_cdn_urls(self):
210210
result = self.tenant.cdn_api.get_cdn_urls([test_team_site_url]).execute_query()
211211
self.assertIsNotNone(result.value)
212+
213+
# You need a SharePoint Advanced Management license to perform this action
214+
#def test_31_get_ransomware_events_overview(self):
215+
# result = self.tenant.get_ransomware_events_overview().execute_query()
216+
# self.assertIsNotNone(result.value)

tests/sharepoint/test_web.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,11 @@ def test_25_parse_datetime(self):
183183
self.assertIsNotNone(result.value)
184184

185185
# def test_26_list_acs_service_principals(self):
186-
# result = self.client.web.get_acs_service_principals().execute_query()
186+
# from office365.sharepoint.client_context import ClientContext
187+
# admin_client = ClientContext(test_team_site_url).with_credentials(
188+
# test_admin_credentials
189+
# )
190+
# result = admin_client.web.get_acs_service_principals().execute_query()
187191
# self.assertIsNotNone(result.value)
188192

189193
def test_27_ensure_tenant_app_catalog(self):

0 commit comments

Comments
 (0)