Skip to content

Commit

Permalink
typings improvements for SharePoint API, changes namespace improvemen…
Browse files Browse the repository at this point in the history
…ts, examples updates
  • Loading branch information
vgrem committed Oct 27, 2023
1 parent bcc6621 commit c1c875d
Show file tree
Hide file tree
Showing 25 changed files with 198 additions and 159 deletions.
2 changes: 1 addition & 1 deletion examples/outlook/messages/get_basic_props.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
user = client.users[test_user_principal_name]
messages = user.messages.select(["id", "subject"]).top(10).get().execute_query()
for message in messages: # type: Message
print(message.id)
print(message.subject)
Empty file.
7 changes: 7 additions & 0 deletions examples/sharepoint/search/search_sort_list.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
"""
Demonstrates how to use the Search REST service in SharePoint
https://learn.microsoft.com/en-us/sharepoint/dev/general-development/sharepoint-search-rest-api-overview
"""

from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.search.query.sort.sort import Sort
from tests import test_site_url, test_user_credentials
Expand All @@ -9,6 +15,7 @@
select_properties=["Path", "LastModifiedTime"],
row_limit=20,
).execute_query()

results = result.value.PrimaryQueryResult.RelevantResults
for row in results.Table.Rows:
print(row.Cells["Path"], row.Cells["LastModifiedTime"])
2 changes: 2 additions & 0 deletions examples/sharepoint/sites/create_comm_site_with_owner.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""
Creates a modern site
https://learn.microsoft.com/en-us/sharepoint/dev/apis/site-creation-rest#create-a-modern-site
"""
from office365.sharepoint.client_context import ClientContext
from tests import (
Expand Down
2 changes: 1 addition & 1 deletion examples/sharepoint/sites/create_team_site.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Creates Team site
Creates a Team site
"""

from office365.sharepoint.client_context import ClientContext
Expand Down
3 changes: 3 additions & 0 deletions examples/sharepoint/webs/get_all.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""
"""
from office365.sharepoint.client_context import ClientContext
from tests import test_client_credentials, test_site_url

Expand Down
10 changes: 10 additions & 0 deletions examples/sharepoint/webs/get_changes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""
Returns the collection of all changes from the change log that have occurred within the scope of the site
"""
from office365.sharepoint.client_context import ClientContext
from tests import test_client_credentials, test_team_site_url

client = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
changes = client.web.get_changes().execute_query()
for change in changes:
print(change)
22 changes: 21 additions & 1 deletion office365/sharepoint/changes/change.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
import datetime
import inspect
from typing import Optional

from office365.sharepoint.changes.token import ChangeToken
from office365.sharepoint.changes.type import ChangeType
from office365.sharepoint.entity import Entity


class Change(Entity):
"""Base class for a change. installation."""

@property
def change_type_name(self):
return next(
iter(
[
item[0]
for item in inspect.getmembers(ChangeType)
if item[1] == self.change_type
]
),
None,
)

@property
def change_token(self):
"""
Expand All @@ -22,17 +40,19 @@ def change_type(self):

@property
def site_id(self):
# type: () -> Optional[str]
"""
Returns the Id of the site of the changed item
"""
return self.properties.get("SiteId", None)

@property
def time(self):
# type: () -> datetime.datetime
"""
Gets a value that specifies the time that the object was modified.
"""
return self.properties.get("Time", None)
return self.properties.get("Time", datetime.datetime.min)

def get_property(self, name, default_value=None):
if default_value is None:
Expand Down
2 changes: 1 addition & 1 deletion office365/sharepoint/changes/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from office365.sharepoint.entity_collection import EntityCollection


class ChangeCollection(EntityCollection):
class ChangeCollection(EntityCollection[Change]):
"""Represents a collection of Change objects"""

def __init__(self, context, resource_path=None):
Expand Down
3 changes: 3 additions & 0 deletions office365/sharepoint/changes/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ class ChangeList(Change):
The RelativeTime and RootFolderUrl properties are not included in the default scalar property set for this type.
"""

def __repr__(self):
return "List: {0}".format(self.list_id)

@property
def base_template(self):
"""An SP.ListTemplateType object that returns the list template type of the list."""
Expand Down
46 changes: 23 additions & 23 deletions office365/sharepoint/changes/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,78 +4,78 @@ class ChangeType:
def __init__(self):
pass

NoChange = "NoChange"
NoChange = 0
"""Indicates that no change has taken place."""

Add = "Add"
Add = 1
"""Specifies that an object has been added within the scope of a list, site, site collection, or content database"""

Update = "Update"
Update = 2
"""Specifies that an object has been modified within the scope of a list, site, site collection,
or content database."""

DeleteObject = "DeleteObject"
DeleteObject = 3
"""
Specifies that an object has been deleted within the scope of a list, site, site collection, or content database
"""

Rename = "Rename"
Rename = 4
"""The leaf in a URL has been renamed."""

MoveAway = "MoveAway"
MoveAway = 5
"""Specifies that a non-leaf segment within a URL has been renamed. The object was moved away from the
location within the site specified by the change."""

MoveInto = "MoveInto"
MoveInto = 6
"""Specifies that a non-leaf segment within a URL has been renamed. The object was moved into the location within
the site specified by the change."""

Restore = "Restore"
Restore = 7
"""Specifies that an object (1) has restored from a backup or from the Recycle Bin"""

RoleAdd = "RoleAdd"
RoleAdd = 8
"""Specifies that a role definition has been added."""

RoleDelete = "RoleDelete"
RoleDelete = 9
"""Specifies that a role definition has been deleted."""

RoleUpdate = "RoleUpdate"
RoleUpdate = 10
"""Specifies that a role definition has been updated."""

AssignmentAdd = "AssignmentAdd"
AssignmentAdd = 11
"""Specifies that a user has been given permissions to a list. The list MUST have different permissions from
its parent."""

AssignmentDelete = "AssignmentDelete"
AssignmentDelete = 12
"""Specifies that a user has lost permissions to a list. The list MUST have different permissions from its parent"""

MemberAdd = "MemberAdd"
MemberAdd = 13
"""Specifies that a user has been added to a group."""

MemberDelete = "MemberDelete"
MemberDelete = 14
"""Specifies that a user has been removed from a group."""

SystemUpdate = "SystemUpdate"
SystemUpdate = 15
"""Specifies that a change has been made to an item by using the protocol server method."""

Navigation = "Navigation"
Navigation = 16
"""Specifies that a change in the navigation structure of a site collection has been made."""

ScopeAdd = "ScopeAdd"
ScopeAdd = 17
"""Specifies that a change in permissions scope has been made to break inheritance from the parent of an object """

ScopeDelete = "ScopeDelete"
ScopeDelete = 18
"""Specifies that a change in permissions scope has been made to revert back to inheriting permissions from
the parent of an object"""

ListContentTypeAdd = "ListContentTypeAdd"
ListContentTypeAdd = 19
"""Specifies that a list content type has been added."""

ListContentTypeDelete = "ListContentTypeDelete"
ListContentTypeDelete = 20
"""Specifies that a list content type has been deleted."""

Dirty = "Dirty"
Dirty = 21
"""Specifies that this item has a pending modification due to an operation on another item."""

Activity = "Activity"
Activity = 22
"""Specifies that an activity change as specified in section 3.2.5.462 has been made to the object """
10 changes: 7 additions & 3 deletions office365/sharepoint/changes/web.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
from typing import Optional

from office365.sharepoint.changes.change import Change


class ChangeWeb(Change):
"""Specifies a change on a site"""

def __repr__(self):
return "Web: {0}, Action: {1}".format(self.web_id, self.change_type_name)

@property
def web_id(self):
# type: () -> Optional[str]
"""
Identifies the site (2) that has changed
:rtype: str or None
Identifies the site that has changed
"""
return self.properties.get("WebId", None)
39 changes: 21 additions & 18 deletions office365/sharepoint/client_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from office365.runtime.auth.client_credential import ClientCredential
from office365.runtime.auth.token_response import TokenResponse
from office365.runtime.auth.user_credential import UserCredential
from office365.runtime.client_result import ClientResult
from office365.runtime.client_runtime_context import ClientRuntimeContext
from office365.runtime.compat import get_absolute_url, urlparse
from office365.runtime.http.http_method import HttpMethod
Expand All @@ -19,8 +20,14 @@
from office365.runtime.queries.delete_entity import DeleteEntityQuery
from office365.runtime.queries.update_entity import UpdateEntityQuery
from office365.runtime.types.event_handler import EventHandler
from office365.sharepoint.portal.groups.site_info import GroupSiteInfo
from office365.sharepoint.portal.sites.creation_response import SPSiteCreationResponse
from office365.sharepoint.portal.sites.status import SiteStatus
from office365.sharepoint.principal.users.user import User
from office365.sharepoint.publishing.pages.service import SitePageService
from office365.sharepoint.publishing.sites.communication.creation_response import (
CommunicationSiteCreationResponse,
)
from office365.sharepoint.request_user_context import RequestUserContext
from office365.sharepoint.sites.site import Site
from office365.sharepoint.tenant.administration.hubsites.collection import (
Expand Down Expand Up @@ -279,8 +286,10 @@ def _build_modification_query(self, request):
request.ensure_header("IF-MATCH", "*")

def create_modern_site(self, title, alias, owner=None):
# type: (str, str, Optional[str | User]) -> Site
"""
Creates a modern site
Creates a modern (Communication) site
https://learn.microsoft.com/en-us/sharepoint/dev/apis/site-creation-rest#create-a-modern-site
:param str alias: Site alias which defines site url, e.g. https://contoso.sharepoint.com/sites/{alias}
:param str title: Site title
Expand All @@ -290,19 +299,17 @@ def create_modern_site(self, title, alias, owner=None):
site_url = "{base_url}/sites/{alias}".format(
base_url=get_absolute_url(self.base_url), alias=alias
)
result = self.site_manager.create(title, site_url, owner)

def _after_site_create(resp):
"""
:type resp: requests.Response
"""
resp.raise_for_status()
def _after_site_create(result):
# type: (ClientResult[SPSiteCreationResponse]) -> None
if result.value.SiteStatus == SiteStatus.Error:
raise ValueError(result.value.ErrorMessage)
elif result.value.SiteStatus == SiteStatus.Ready:
return_type.set_property("__siteUrl", result.value.SiteUrl)

self.after_execute(_after_site_create)
self.site_manager.create(title, site_url, owner).after_execute(
_after_site_create
)
return return_type

def create_team_site(self, alias, title, is_public=True):
Expand All @@ -312,20 +319,18 @@ def create_team_site(self, alias, title, is_public=True):
:param str title: Site title
:param bool is_public:
"""
result = self.group_site_manager.create_group_ex(title, alias, is_public)
return_type = Site(self)

def _after_site_created(resp):
"""
:type resp: requests.Response
"""
resp.raise_for_status()
def _after_site_created(result):
# type: (ClientResult[GroupSiteInfo]) -> None
if result.value.SiteStatus == SiteStatus.Error:
raise ValueError(result.value.ErrorMessage)
elif result.value.SiteStatus == SiteStatus.Ready:
return_type.set_property("__siteUrl", result.value.SiteUrl)

self.after_execute(_after_site_created)
self.group_site_manager.create_group_ex(title, alias, is_public).after_execute(
_after_site_created
)
return return_type

def create_communication_site(self, alias, title):
Expand All @@ -341,9 +346,7 @@ def create_communication_site(self, alias, title):
)

def _after_site_created(result):
"""
:type result: ClientResult
"""
# type: (ClientResult[CommunicationSiteCreationResponse]) -> None
if result.value.SiteStatus == SiteStatus.Error:
raise ValueError("Site creation error")
elif result.value.SiteStatus == SiteStatus.Ready:
Expand Down
Loading

0 comments on commit c1c875d

Please sign in to comment.