From 3cc489b0426498c6436613b2b3fef52a55504fed Mon Sep 17 00:00:00 2001 From: vgrem Date: Mon, 18 Sep 2023 09:25:41 +0300 Subject: [PATCH] #730: fix for SitePage.checkout_page method, workbooks namespace new types --- .../listitems/attachments/upload.py | 5 +- examples/sharepoint/views/read_custom.py | 10 ++++ examples/sharepoint/views/read_default.py | 13 +++++ examples/sharepoint/views/read_items.py | 28 ---------- generator/metadata/SharePoint.xml | 2 +- .../onedrive/workbooks/filter_criteria.py | 5 ++ .../onedrive/workbooks/functions/functions.py | 1 - .../onedrive/workbooks/operations/error.py | 10 ++++ office365/onedrive/workbooks/ranges/border.py | 5 ++ office365/onedrive/workbooks/ranges/fill.py | 5 ++ office365/onedrive/workbooks/ranges/format.py | 8 +++ office365/onedrive/workbooks/ranges/range.py | 39 +++++++++++++- office365/onedrive/workbooks/ranges/sort.py | 5 ++ .../onedrive/workbooks/tables/pivot_table.py | 1 - office365/outlook/calendar/email_address.py | 4 +- office365/outlook/calendar/events/event.py | 52 +++++++++++++++++++ .../outlook/calendar/timezones/__init__.py | 0 .../{time_zone_base.py => timezones/base.py} | 0 .../outlook/calendar/timezones/custom.py | 7 +++ office365/outlook/calendar/working_hours.py | 2 +- .../outlook/mail/messages/rules/predicates.py | 13 ++++- .../attachments/creation_information.py | 4 +- office365/sharepoint/listitems/caml/query.py | 1 + office365/sharepoint/lists/list.py | 15 ++++++ office365/sharepoint/publishing/pages/page.py | 9 ++-- .../publishing/pages/reposts/metadata.py | 1 + .../sharing/object_sharing_settings.py | 33 +++++++++++- .../sharepoint/views/field_collection.py | 32 +++++++++--- office365/sharepoint/views/view.py | 26 +++++++--- office365/sharepoint/webs/web.py | 6 ++- office365/teams/team.py | 2 + tests/directory/test_user.py | 1 - tests/sharepoint/test_publishing.py | 12 +++++ tests/sharepoint/test_sharing.py | 4 ++ 34 files changed, 298 insertions(+), 63 deletions(-) create mode 100644 examples/sharepoint/views/read_custom.py create mode 100644 examples/sharepoint/views/read_default.py delete mode 100644 examples/sharepoint/views/read_items.py create mode 100644 office365/onedrive/workbooks/filter_criteria.py create mode 100644 office365/onedrive/workbooks/ranges/border.py create mode 100644 office365/onedrive/workbooks/ranges/fill.py create mode 100644 office365/onedrive/workbooks/ranges/sort.py create mode 100644 office365/outlook/calendar/timezones/__init__.py rename office365/outlook/calendar/{time_zone_base.py => timezones/base.py} (100%) create mode 100644 office365/outlook/calendar/timezones/custom.py diff --git a/examples/sharepoint/listitems/attachments/upload.py b/examples/sharepoint/listitems/attachments/upload.py index 4753012c..a9c97ecd 100644 --- a/examples/sharepoint/listitems/attachments/upload.py +++ b/examples/sharepoint/listitems/attachments/upload.py @@ -1,10 +1,13 @@ +""" +Creates a list item and uploads an attachment +""" + import os from office365.sharepoint.attachments.creation_information import AttachmentCreationInformation from office365.sharepoint.client_context import ClientContext from tests import test_client_credentials, test_team_site_url ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials) - list_title = "Company Tasks" tasks_list = ctx.web.lists.get_by_title(list_title) diff --git a/examples/sharepoint/views/read_custom.py b/examples/sharepoint/views/read_custom.py new file mode 100644 index 00000000..64d56669 --- /dev/null +++ b/examples/sharepoint/views/read_custom.py @@ -0,0 +1,10 @@ +from office365.sharepoint.client_context import ClientContext +from office365.sharepoint.listitems.listitem import ListItem +from tests import test_client_credentials, test_team_site_url + + +ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials) +view = ctx.web.default_document_library().views.get_by_title("All Documents") +items = view.get_items().expand(["Author"]).execute_query() +for item in items: # type: ListItem + print(item.properties) diff --git a/examples/sharepoint/views/read_default.py b/examples/sharepoint/views/read_default.py new file mode 100644 index 00000000..9b5add87 --- /dev/null +++ b/examples/sharepoint/views/read_default.py @@ -0,0 +1,13 @@ +""" +Read list items from a default view +""" +from office365.sharepoint.client_context import ClientContext +from office365.sharepoint.listitems.listitem import ListItem +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() +items = lib.default_view.get_items().execute_query() +for item in items: # type: ListItem + print(item.properties) diff --git a/examples/sharepoint/views/read_items.py b/examples/sharepoint/views/read_items.py deleted file mode 100644 index a5e0576b..00000000 --- a/examples/sharepoint/views/read_items.py +++ /dev/null @@ -1,28 +0,0 @@ -from office365.sharepoint.client_context import ClientContext -from office365.sharepoint.listitems.listitem import ListItem -from tests import test_client_credentials, test_team_site_url - - -def retrieve_default_view_items(context): - """ - :type context: ClientContext - """ - lib = context.web.default_document_library() - items = lib.default_view.get_items().execute_query() - for item in items: # type: ListItem - print(item.id) - - -def retrieve_custom_view_items(context): - """ - :type context: ClientContext - """ - view = context.web.lists.get_by_title("Contacts_Large").views.get_by_title("All contacts") - items = view.get_items().top(5).execute_query() - for item in items: # type: ListItem - print(item.id) - - -ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials) -retrieve_default_view_items(ctx) -#retrieve_custom_view_items(ctx) diff --git a/generator/metadata/SharePoint.xml b/generator/metadata/SharePoint.xml index 8b2db4e1..5e51e37a 100644 --- a/generator/metadata/SharePoint.xml +++ b/generator/metadata/SharePoint.xml @@ -22329,7 +22329,7 @@ - + diff --git a/office365/onedrive/workbooks/filter_criteria.py b/office365/onedrive/workbooks/filter_criteria.py new file mode 100644 index 00000000..c77feb2b --- /dev/null +++ b/office365/onedrive/workbooks/filter_criteria.py @@ -0,0 +1,5 @@ +from office365.runtime.client_value import ClientValue + + +class WorkbookFilterCriteria(ClientValue): + """Represents the filtering criteria applied to a column.""" diff --git a/office365/onedrive/workbooks/functions/functions.py b/office365/onedrive/workbooks/functions/functions.py index 031bdfa7..09a49cd2 100644 --- a/office365/onedrive/workbooks/functions/functions.py +++ b/office365/onedrive/workbooks/functions/functions.py @@ -9,7 +9,6 @@ class WorkbookFunctions(Entity): def abs(self, number): """ Returns the absolute value of a number. The absolute value of a number is the number without its sign - :param float number: The real number of which you want the absolute value. """ return_type = WorkbookFunctionResult(self.context) diff --git a/office365/onedrive/workbooks/operations/error.py b/office365/onedrive/workbooks/operations/error.py index 0635a999..17bed5fc 100644 --- a/office365/onedrive/workbooks/operations/error.py +++ b/office365/onedrive/workbooks/operations/error.py @@ -3,3 +3,13 @@ class WorkbookOperationError(ClientValue): """Represents an error from a failed workbook operation.""" + + def __init__(self, code=None, innerError=None, message=None): + """ + :param str code: + :param str innerError: + :param str message: + """ + self.code = code + self.innerError = innerError + self.message = message diff --git a/office365/onedrive/workbooks/ranges/border.py b/office365/onedrive/workbooks/ranges/border.py new file mode 100644 index 00000000..9e5335fd --- /dev/null +++ b/office365/onedrive/workbooks/ranges/border.py @@ -0,0 +1,5 @@ +from office365.entity import Entity + + +class WorkbookRangeBorder(Entity): + """Represents the border of an object.""" diff --git a/office365/onedrive/workbooks/ranges/fill.py b/office365/onedrive/workbooks/ranges/fill.py new file mode 100644 index 00000000..fa7bc89e --- /dev/null +++ b/office365/onedrive/workbooks/ranges/fill.py @@ -0,0 +1,5 @@ +from office365.entity import Entity + + +class WorkbookRangeFill(Entity): + """Represents the background of a range object.""" diff --git a/office365/onedrive/workbooks/ranges/format.py b/office365/onedrive/workbooks/ranges/format.py index 5e8846b5..24b368a4 100644 --- a/office365/onedrive/workbooks/ranges/format.py +++ b/office365/onedrive/workbooks/ranges/format.py @@ -1,4 +1,5 @@ from office365.entity import Entity +from office365.onedrive.workbooks.ranges.fill import WorkbookRangeFill from office365.onedrive.workbooks.ranges.format_protection import WorkbookFormatProtection from office365.runtime.paths.resource_path import ResourcePath @@ -6,6 +7,13 @@ class WorkbookRangeFormat(Entity): """A format object encapsulating the range's font, fill, borders, alignment, and other properties.""" + @property + def fill(self): + """Returns the fill object defined on the overall range""" + return self.properties.get('fill', + WorkbookRangeFill(self.context, + ResourcePath("fill", self.resource_path))) + @property def protection(self): """Returns the format protection object for a range """ diff --git a/office365/onedrive/workbooks/ranges/range.py b/office365/onedrive/workbooks/ranges/range.py index de75d6bb..20f91297 100644 --- a/office365/onedrive/workbooks/ranges/range.py +++ b/office365/onedrive/workbooks/ranges/range.py @@ -1,4 +1,6 @@ from office365.entity import Entity +from office365.onedrive.workbooks.ranges.format import WorkbookRangeFormat +from office365.onedrive.workbooks.ranges.sort import WorkbookRangeSort from office365.onedrive.workbooks.ranges.view import WorkbookRangeView from office365.runtime.paths.resource_path import ResourcePath from office365.runtime.queries.function import FunctionQuery @@ -19,11 +21,46 @@ def address(self): """ Represents the range reference in A1-style. Address value will contain the Sheet reference (e.g. Sheet1!A1:B4) - :rtype: str or None """ return self.properties.get("address", None) + @property + def address_local(self): + """ + Represents range reference for the specified range in the language of the user. Read-only. + :rtype: str or None + """ + return self.properties.get("addressLocal", None) + + @property + def cell_count(self): + """ + Number of cells in the range. Read-only. + :rtype: int or None + """ + return self.properties.get("cellCount", None) + + @property + def column_count(self): + """ + Represents the total number of columns in the range. Read-only. + :rtype: int or None + """ + return self.properties.get("columnCount", None) + + @property + def format(self): + """Returns a format object, encapsulating the range's font, fill, borders, alignment, and other properties""" + return self.properties.get('format', + WorkbookRangeFormat(self.context, ResourcePath("format", self.resource_path))) + + @property + def sort(self): + """The worksheet containing the current range. """ + return self.properties.get('sort', + WorkbookRangeSort(self.context, ResourcePath("sort", self.resource_path))) + @property def worksheet(self): """The worksheet containing the current range """ diff --git a/office365/onedrive/workbooks/ranges/sort.py b/office365/onedrive/workbooks/ranges/sort.py new file mode 100644 index 00000000..fc9a7db0 --- /dev/null +++ b/office365/onedrive/workbooks/ranges/sort.py @@ -0,0 +1,5 @@ +from office365.entity import Entity + + +class WorkbookRangeSort(Entity): + """Manages sorting operations on Range objects.""" diff --git a/office365/onedrive/workbooks/tables/pivot_table.py b/office365/onedrive/workbooks/tables/pivot_table.py index 5a7aee2e..200adb6c 100644 --- a/office365/onedrive/workbooks/tables/pivot_table.py +++ b/office365/onedrive/workbooks/tables/pivot_table.py @@ -25,7 +25,6 @@ def refresh_all(self): @property def name(self): """Name of the PivotTable. - :rtype: str or None """ return self.properties.get("Name", None) diff --git a/office365/outlook/calendar/email_address.py b/office365/outlook/calendar/email_address.py index dbc606a6..5e6e7cb5 100644 --- a/office365/outlook/calendar/email_address.py +++ b/office365/outlook/calendar/email_address.py @@ -6,8 +6,8 @@ class EmailAddress(ClientValue): def __init__(self, address=None, name=None): """ - :param str address: - :param str name: + :param str address: The email address of the person or entity. + :param str name: The display name of the person or entity. """ super(EmailAddress, self).__init__() self.address = address diff --git a/office365/outlook/calendar/events/event.py b/office365/outlook/calendar/events/event.py index 6c073f9e..99825941 100644 --- a/office365/outlook/calendar/events/event.py +++ b/office365/outlook/calendar/events/event.py @@ -82,6 +82,58 @@ def dismiss_reminder(self): self.context.add_query(qry) return self + @property + def allow_new_time_proposals(self): + """ + true if the meeting organizer allows invitees to propose a new time when responding; otherwise, false. + Optional. Default is true. + :rtype: bool or None + """ + return self.properties.get("allowNewTimeProposals", None) + + @property + def has_attachments(self): + """ + Set to true if the event has attachments. + :rtype: bool or None + """ + return self.properties.get("hasAttachments", None) + + @property + def hide_attendees(self): + """ + When set to true, each attendee only sees themselves in the meeting request and meeting Tracking list. + Default is false. + :rtype: bool or None + """ + return self.properties.get("hideAttendees", None) + + @property + def ical_uid(self): + """ + A unique identifier for an event across calendars. This ID is different for each occurrence in a recurring + series. Read-only. + :rtype: str or None + """ + return self.properties.get("iCalUId", None) + + @property + def importance(self): + """ + The importance of the event. The possible values are: low, normal, high. + :rtype: str + """ + return self.properties.get("importance", None) + + @property + def is_all_day(self): + """ + Set to true if the event lasts all day. If true, regardless of whether it's a single-day or multi-day event, + start and end time must be set to midnight and be in the same time zone. + :rtype: bool or None + """ + return self.properties.get("isAllDay", None) + @property def start(self): """ diff --git a/office365/outlook/calendar/timezones/__init__.py b/office365/outlook/calendar/timezones/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/office365/outlook/calendar/time_zone_base.py b/office365/outlook/calendar/timezones/base.py similarity index 100% rename from office365/outlook/calendar/time_zone_base.py rename to office365/outlook/calendar/timezones/base.py diff --git a/office365/outlook/calendar/timezones/custom.py b/office365/outlook/calendar/timezones/custom.py new file mode 100644 index 00000000..e4da1d80 --- /dev/null +++ b/office365/outlook/calendar/timezones/custom.py @@ -0,0 +1,7 @@ +from office365.outlook.calendar.timezones.base import TimeZoneBase + + +class CustomTimeZone(TimeZoneBase): + """ + Represents a time zone where the transition from standard to daylight saving time, or vice versa is not standard. + """ diff --git a/office365/outlook/calendar/working_hours.py b/office365/outlook/calendar/working_hours.py index 6c802664..861f071c 100644 --- a/office365/outlook/calendar/working_hours.py +++ b/office365/outlook/calendar/working_hours.py @@ -1,4 +1,4 @@ -from office365.outlook.calendar.time_zone_base import TimeZoneBase +from office365.outlook.calendar.timezones.base import TimeZoneBase from office365.runtime.client_value import ClientValue from office365.runtime.types.collections import StringCollection diff --git a/office365/outlook/mail/messages/rules/predicates.py b/office365/outlook/mail/messages/rules/predicates.py index 805dc2cc..7b9b4a51 100644 --- a/office365/outlook/mail/messages/rules/predicates.py +++ b/office365/outlook/mail/messages/rules/predicates.py @@ -1,11 +1,14 @@ +from office365.outlook.mail.recipient import Recipient from office365.runtime.client_value import ClientValue +from office365.runtime.client_value_collection import ClientValueCollection from office365.runtime.types.collections import StringCollection class MessageRulePredicates(ClientValue): """Represents the set of conditions and exceptions that are available for a rule.""" - def __init__(self, body_contains=None, body_or_subject_contains=None, categories=None): + def __init__(self, body_contains=None, body_or_subject_contains=None, categories=None, + from_addresses=None, has_attachments=None, header_contains=None): """ :param list[str] body_contains: Represents the strings that should appear in the body of an incoming message in order for the condition or exception to apply. @@ -13,7 +16,15 @@ def __init__(self, body_contains=None, body_or_subject_contains=None, categories of an incoming message in order for the condition or exception to apply. :param list[str] categories: Represents the categories that an incoming message should be labeled with in order for the condition or exception to apply. + :param list[Recipient] from_addresses: Represents the specific sender email addresses of an incoming message + in order for the condition or exception to apply. + :param bool has_attachments: Indicates whether an incoming message must have attachments in order for the + condition or exception to apply. + :param list[str] header_contains: """ self.bodyContains = StringCollection(body_contains) self.bodyOrSubjectContains = StringCollection(body_or_subject_contains) self.categories = StringCollection(categories) + self.fromAddresses = ClientValueCollection(Recipient, from_addresses) + self.hasAttachments = has_attachments + self.headerContains = StringCollection(header_contains) diff --git a/office365/sharepoint/attachments/creation_information.py b/office365/sharepoint/attachments/creation_information.py index 34f28661..2718b6e4 100644 --- a/office365/sharepoint/attachments/creation_information.py +++ b/office365/sharepoint/attachments/creation_information.py @@ -7,8 +7,8 @@ def __init__(self, filename=None, content=None): """ Represents properties that can be set when creating a file by using the AttachmentFiles.Add method. - :type filename: str - :type content: str or bytes + :param str filename: Specifies the file name of the list item attachment. + :param str or bytes content: The contents of the file as a stream. """ super(AttachmentCreationInformation, self).__init__() self._filename = filename diff --git a/office365/sharepoint/listitems/caml/query.py b/office365/sharepoint/listitems/caml/query.py index fb52b8a3..fb89db61 100644 --- a/office365/sharepoint/listitems/caml/query.py +++ b/office365/sharepoint/listitems/caml/query.py @@ -101,6 +101,7 @@ def parse(query_expr, scope=ViewScope.DefaultValue): @staticmethod def create_all_items_query(): + """Constructs a query""" return CamlQuery.parse("", ViewScope.RecursiveAll) @staticmethod diff --git a/office365/sharepoint/lists/list.py b/office365/sharepoint/lists/list.py index 3646a6f1..ccd04842 100644 --- a/office365/sharepoint/lists/list.py +++ b/office365/sharepoint/lists/list.py @@ -31,6 +31,7 @@ from office365.sharepoint.pages.wiki_page_creation_information import WikiPageCreationInformation from office365.sharepoint.permissions.securable_object import SecurableObject from office365.sharepoint.principal.users.user import User +from office365.sharepoint.sharing.object_sharing_settings import ObjectSharingSettings from office365.sharepoint.sitescripts.utility import SiteScriptUtility from office365.sharepoint.translation.user_resource import UserResource from office365.sharepoint.usercustomactions.collection import UserCustomActionCollection @@ -115,6 +116,20 @@ def _loaded(): self.root_folder.ensure_property("ServerRelativeUrl", _loaded) return return_type + def get_sharing_settings(self): + """ + Retrieves a sharing settings for a List + """ + return_type = ObjectSharingSettings(self.context) + + def _list_loaded(): + from office365.sharepoint.webs.web import Web + list_abs_path = SPResPath.create_absolute(self.context.base_url, self.root_folder.serverRelativeUrl) + Web.get_object_sharing_settings(self.context, str(list_abs_path), return_type=return_type) + + self.ensure_property("RootFolder", _list_loaded) + return return_type + def get_site_script(self, options=None): """Creates site script syntax diff --git a/office365/sharepoint/publishing/pages/page.py b/office365/sharepoint/publishing/pages/page.py index dab03d67..6ae5e0fc 100644 --- a/office365/sharepoint/publishing/pages/page.py +++ b/office365/sharepoint/publishing/pages/page.py @@ -9,6 +9,7 @@ class SharePagePreviewByEmailFieldsData(ClientValue): + """This class contains the information used by SharePagePreviewByEmail method""" def __init__(self, message=None, recipient_emails=None): """ @@ -28,10 +29,9 @@ class SitePage(SitePageMetadata): def checkout_page(self): """Checks out the current Site Page if it is available to be checked out.""" - return_type = SitePage(self.context) - qry = ServiceOperationQuery(self, "CheckoutPage", None, None, None, return_type) + qry = ServiceOperationQuery(self, "CheckoutPage", None, None, None, self) self.context.add_query(qry) - return return_type + return self def copy(self): """Creates a copy of the current Site Page and returns the resulting new SitePage.""" @@ -41,11 +41,12 @@ def copy(self): def discard_page(self): """Discards the current checked out version of the Site Page. Returns the resulting SitePage after discard.""" - qry = ServiceOperationQuery(self, "DiscardPage") + qry = ServiceOperationQuery(self, "DiscardPage", return_type=self) self.context.add_query(qry) return self def ensure_title_resource(self): + """""" qry = ServiceOperationQuery(self, "EnsureTitleResource") self.context.add_query(qry) return self diff --git a/office365/sharepoint/publishing/pages/reposts/metadata.py b/office365/sharepoint/publishing/pages/reposts/metadata.py index 8bfd9a87..3a6a0125 100644 --- a/office365/sharepoint/publishing/pages/reposts/metadata.py +++ b/office365/sharepoint/publishing/pages/reposts/metadata.py @@ -2,6 +2,7 @@ class RepostPageMetadata(SitePageMetadata): + """""" @property def entity_type_name(self): diff --git a/office365/sharepoint/sharing/object_sharing_settings.py b/office365/sharepoint/sharing/object_sharing_settings.py index d87a0530..f1626cb8 100644 --- a/office365/sharepoint/sharing/object_sharing_settings.py +++ b/office365/sharepoint/sharing/object_sharing_settings.py @@ -14,7 +14,6 @@ class ObjectSharingSettings(BaseEntity): def web_url(self): """ The URL pointing to the containing SP.Web object. - :rtype: str """ return self.properties.get("WebUrl", None) @@ -35,6 +34,30 @@ def block_people_picker_and_sharing(self): """ return self.properties.get("BlockPeoplePickerAndSharing", None) + @property + def can_current_user_manage_organization_readonly_link(self): + """ + Boolean indicating whether the current user can create or disable an organization View link. + :rtype: bool + """ + return self.properties.get("CanCurrentUserManageOrganizationReadonlyLink", None) + + @property + def can_current_user_manage_organization_read_write_link(self): + """ + Boolean indicating whether the current user can create or disable an organization Edit link. + :rtype: bool + """ + return self.properties.get("CanCurrentUserManageOrganizationReadWriteLink", None) + + @property + def can_current_user_manage_readonly_link(self): + """ + Boolean indicating whether the current user can create or disable an anonymous View link. + :rtype: bool + """ + return self.properties.get("CanCurrentUserManageReadonlyLink", None) + @property def can_send_email(self): """ @@ -59,6 +82,14 @@ def is_user_site_admin(self): """ return self.properties.get("IsUserSiteAdmin", None) + @property + def list_id(self): + """ + The unique ID of the parent list (if applicable). + :rtype: str + """ + return self.properties.get("ListId", None) + @property def roles(self): """ diff --git a/office365/sharepoint/views/field_collection.py b/office365/sharepoint/views/field_collection.py index 0e15c8de..768bbbd5 100644 --- a/office365/sharepoint/views/field_collection.py +++ b/office365/sharepoint/views/field_collection.py @@ -1,16 +1,30 @@ from office365.runtime.queries.service_operation import ServiceOperationQuery -from office365.sharepoint.base_entity_collection import BaseEntityCollection +from office365.sharepoint.base_entity import BaseEntity -class ViewFieldCollection(BaseEntityCollection): +class ViewFieldCollection(BaseEntity): """Represents a collection of Field resources.""" def __init__(self, context, resource_path=None): - super(ViewFieldCollection, self).__init__(context, str, resource_path) + super(ViewFieldCollection, self).__init__(context, resource_path) + + def __len__(self): + return len(self.items) + + def __getitem__(self, index): + """ + Gets view field by index + :param int index: Index + """ + return self.items[index] + + def __repr__(self): + return repr(self.items) @property def schema_xml(self): - """Gets Schema Xml. + """ + Gets Schema Xml. :rtype: str or None """ return self.properties.get('SchemaXml', None) @@ -18,15 +32,14 @@ def schema_xml(self): @property def items(self): """Gets items. - :rtype: list[str] or None """ return self.properties.get('Items', None) def set_property(self, name, value, persist_changes=False): - self._properties[name] = value if name == "Items": - self._data = list(value.values()) + value = list(value.values()) + super(ViewFieldCollection, self).set_property(name, value, persist_changes) return self def add_view_field(self, field_name): @@ -41,7 +54,6 @@ def add_view_field(self, field_name): def move_view_field_to(self, name, index): """ Moves the field with the specified field internal name to the specified position in the collection - :param str name: Specifies the field internal name. :param int index: Specifies the new position for the field (2). The first position is 0. """ @@ -66,3 +78,7 @@ def remove_view_field(self, field_name): qry = ServiceOperationQuery(self, "RemoveViewField", [field_name]) self.context.add_query(qry) return self + + @property + def entity_type_name(self): + return "SP.ViewFieldCollection" diff --git a/office365/sharepoint/views/view.py b/office365/sharepoint/views/view.py index cb893abd..3fd83b10 100644 --- a/office365/sharepoint/views/view.py +++ b/office365/sharepoint/views/view.py @@ -28,7 +28,7 @@ def _get_items_inner(): caml_query = CamlQuery.parse(self.view_query) qry = ServiceOperationQuery(self.parent_list, "GetItems", None, caml_query, "query", return_type) self.context.add_query(qry) - self.ensure_property("ViewQuery", _get_items_inner) + self.ensure_properties(["ViewQuery", "ViewFields"], _get_items_inner) return return_type def render_as_html(self): @@ -139,12 +139,13 @@ def custom_order(self): @property def editor_modified(self): - """Specifies whether the list view was modified in an editor.""" + """Specifies whether the list view was modified in an editor. + :rtype: bool or None + """ return self.properties.get("EditorModified", None) def formats(self): """Specifies the column and row formatting for the list view. - :stype: str or None """ return self.properties.get("Formats", None) @@ -171,13 +172,15 @@ def default_view(self): @default_view.setter def default_view(self, value): - """Sets whether the list view is the default list view. + """ + Sets whether the list view is the default list view. """ self.set_property("DefaultView", value) @property def default_view_for_content_type(self): - """Specifies whether the list view is the default list view for the content type specified by ContentTypeId. + """ + Specifies whether the list view is the default list view for the content type specified by ContentTypeId. :rtype: bool or None """ return self.properties.get("DefaultViewForContentType", None) @@ -190,7 +193,10 @@ def view_fields(self): @property def view_query(self): - """Gets or sets a value that specifies the query that is used by the list view.""" + """ + Gets or sets a value that specifies the query that is used by the list view. + :rtype: str or None + """ return self.properties.get('ViewQuery', None) @property @@ -210,7 +216,10 @@ def server_relative_path(self): @property def view_joins(self): - """Specifies the joins that are used in the list view.""" + """ + Specifies the joins that are used in the list view + :rtype: str or None + """ return self.properties.get("ViewJoins", None) @property @@ -220,13 +229,14 @@ def visualization_info(self): def get_property(self, name, default_value=None): property_mapping = { + "ContentTypeId": self.content_type_id, "ViewFields": self.view_fields, "DefaultView": self.default_view, "ServerRelativePath": self.server_relative_path, "VisualizationInfo": self.visualization_info } if name in property_mapping: - default_value = property_mapping[name] + default_value = property_mapping.get(name, None) return super(View, self).get_property(name, default_value) def set_property(self, name, value, persist_changes=True): diff --git a/office365/sharepoint/webs/web.py b/office365/sharepoint/webs/web.py index a6e82ccb..a0c8e1e1 100644 --- a/office365/sharepoint/webs/web.py +++ b/office365/sharepoint/webs/web.py @@ -603,7 +603,7 @@ def create_anonymous_link_with_expiration(context, url, is_edit_link, expiration return return_type @staticmethod - def get_object_sharing_settings(context, object_url, group_id, use_simplified_roles): + def get_object_sharing_settings(context, object_url, group_id=None, use_simplified_roles=None, return_type=None): """Given a path to an object in SharePoint, this will generate a sharing settings object which contains necessary information for rendering sharing information @@ -619,8 +619,10 @@ def get_object_sharing_settings(context, object_url, group_id, use_simplified_ro :param int group_id: The id value of the permissions group if adding to a group, 0 otherwise. :param bool use_simplified_roles: A Boolean value indicating whether to use the SharePoint simplified roles (Edit, View) or not. + :param ObjectSharingSettings return_type: Return type """ - return_type = ObjectSharingSettings(context) + if return_type is None: + return_type = ObjectSharingSettings(context) payload = { "objectUrl": object_url, "groupId": group_id, diff --git a/office365/teams/team.py b/office365/teams/team.py index 6ed648f1..abad5589 100644 --- a/office365/teams/team.py +++ b/office365/teams/team.py @@ -1,3 +1,5 @@ +import datetime + from office365.entity import Entity from office365.entity_collection import EntityCollection from office365.runtime.queries.service_operation import ServiceOperationQuery diff --git a/tests/directory/test_user.py b/tests/directory/test_user.py index 06e2cbd8..4411744f 100644 --- a/tests/directory/test_user.py +++ b/tests/directory/test_user.py @@ -77,7 +77,6 @@ def test_13_get_extension(self): self.assertGreater(len(result), 0) def test_14_delete_extension(self): - #result = self.client.me.extensions["Com.Contoso.SSN"].delete_object().execute_query() result = self.__class__.test_extension.delete_object().execute_query() self.assertIsNotNone(result.resource_path) diff --git a/tests/sharepoint/test_publishing.py b/tests/sharepoint/test_publishing.py index f8998f79..2a304d39 100644 --- a/tests/sharepoint/test_publishing.py +++ b/tests/sharepoint/test_publishing.py @@ -58,6 +58,18 @@ def test_11_get_page_diagnostics(self): result = self.client.page_diagnostics.by_page("/sites/team/SitePages/Home.aspx").execute_query() self.assertIsNotNone(result.value) + def test_12_checkout_page(self): + page = self.client.site_pages.pages.get_by_name("Home.aspx") + page.checkout_page().execute_query() + self.assertIsNotNone(page.resource_path) + self.assertTrue(page.is_page_checked_out_to_current_user) + + def test_13_discard_page(self): + page = self.client.site_pages.pages.get_by_name("Home.aspx") + page.discard_page().execute_query() + self.assertFalse(page.is_page_checked_out_to_current_user, "Page is expected to be checked in") + + #def test_12_share_page_preview_by_email(self): # page = self.client.site_pages.pages.get_by_url("/sites/team/SitePages/Home.aspx") # page.share_page_preview_by_email("This page has been shared with you", diff --git a/tests/sharepoint/test_sharing.py b/tests/sharepoint/test_sharing.py index a64d0552..ddf0a7c9 100644 --- a/tests/sharepoint/test_sharing.py +++ b/tests/sharepoint/test_sharing.py @@ -67,3 +67,7 @@ def test8_get_web_sharing_information(self): def test9_get_site_sharing_report_capabilities(self): result = SiteSharingReportHelper.get_site_sharing_report_capabilities(self.client).execute_query() self.assertIsNotNone(result.value) + + def test_10_get_get_list_sharing_settings(self): + result = self.client.web.default_document_library().get_sharing_settings().execute_query() + self.assertIsNotNone(result.list_id)