Skip to content

Commit

Permalink
examples refactorings and type hints enhancements for ClientValue, Cl…
Browse files Browse the repository at this point in the history
…ientResult and EventHandler
  • Loading branch information
vgrem committed Oct 10, 2023
1 parent 6505e23 commit eb10e17
Show file tree
Hide file tree
Showing 16 changed files with 53 additions and 39 deletions.
12 changes: 5 additions & 7 deletions examples/sharepoint/folders/download.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
"""
Demonstrates how to download folders content
Demonstrates how to enumerate folder files and download file's content
"""
import os
import tempfile

from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.files.file import File
from office365.sharepoint.folders.folder import Folder
from tests import test_client_credentials, test_team_site_url


def print_progress(file):
# type: (File) -> None
print("File {0} has been downloaded".format(file.serverRelativeUrl))


def download_files(source_folder, download_path):
"""
Demonstrates how to enumerate folder files and download file's content
:type source_folder: Folder
:type download_path: str
"""
# type: (Folder, str) -> None

# 1. retrieve files collection (metadata) from library root folder
files = source_folder.files.get().execute_query()

# 2. start download process (per file)
for file in files: # type: File
for file in files:
print("Downloading file: {0} ...".format(file.properties["ServerRelativeUrl"]))
download_file_name = os.path.join(download_path, file.name)
with open(download_file_name, "wb") as local_file:
Expand Down
6 changes: 4 additions & 2 deletions examples/sharepoint/folders/get_folder_files.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""
Prints file names in a folder
"""
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.files.file import File
from tests import test_client_credentials, test_team_site_url

ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
root_folder = ctx.web.default_document_library().root_folder
ctx.load(root_folder, ["Files"])
ctx.execute_query()
for file in root_folder.files: # type: File
for file in root_folder.files:
print(file.name)
4 changes: 1 addition & 3 deletions examples/sharepoint/folders/list_folders.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ def enum_folder(parent_folder, action):


def print_folder_stat(folder):
"""
:type folder: Folder
"""
# type: (Folder) -> None
print(folder.serverRelativeUrl)
print(folder.time_created)

Expand Down
4 changes: 2 additions & 2 deletions examples/sharepoint/search/search_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@

ctx = ClientContext(test_site_url).with_credentials(test_user_credentials)
result = ctx.search.query("IsDocument:1", row_limit=10).execute_query()
for i, row in enumerate(result.value.PrimaryQueryResult.RelevantResults.Table.Rows):
print("{0}: {1}".format(i + 1, row.Cells["Path"]))
for row in result.value.PrimaryQueryResult.RelevantResults.Table.Rows:
print("{0}".format(row.Cells["Path"]))
4 changes: 1 addition & 3 deletions examples/sharepoint/sharing/share_file_org.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import json

from examples.sharepoint import upload_sample_file
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.sharing.links.kind import SharingLinkKind
Expand All @@ -8,4 +6,4 @@
ctx = ClientContext(test_team_site_url).with_credentials(test_user_credentials)
remote_file = upload_sample_file(ctx, "../../data/Financial Sample.xlsx")
result = remote_file.share_link(SharingLinkKind.OrganizationView).execute_query()
print(json.dumps(result.value.to_json(), indent=4))
print("Shared link url: {0}".format(result.value.sharingLinkInfo))
7 changes: 4 additions & 3 deletions examples/sharepoint/sharing/share_file_with_password.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Share a file with a password
"""
import json

Expand All @@ -14,5 +14,6 @@
result = target_file.share_link(
SharingLinkKind.Flexible, role=RoleType.Editor, password="password"
).execute_query()
print(json.dumps(result.value.to_json(), indent=4))
# print("Shared link url: {0}".format(result.value.sharingLinkInfo))

# print(json.dumps(result.value.to_json(), indent=4))
print("Shared link url: {0}".format(result.value.sharingLinkInfo))
2 changes: 1 addition & 1 deletion examples/sharepoint/tenant/check_licenses.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
test_admin_credentials
)
result = admin_client.tenant.check_tenant_intune_license().execute_query()
print(result.value)
print("Intune license: {0}".format("Yes" if result.value else "No"))
9 changes: 9 additions & 0 deletions office365/runtime/client_value.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
from typing import Any, Iterator, Tuple, TypeVar

from typing_extensions import Self

from office365.runtime.odata.v3.json_light_format import JsonLightFormat

T = TypeVar("T", int, float, str, bool, "ClientValue")


class ClientValue(object):
"""Represent complex type.
Expand All @@ -8,6 +14,7 @@ class ClientValue(object):
"""

def set_property(self, k, v, persist_changes=True):
# type: (str, Any, bool) -> Self
prop_type = getattr(self, k, None)
if isinstance(prop_type, ClientValue) and v is not None:
if isinstance(v, list):
Expand All @@ -26,9 +33,11 @@ def set_property(self, k, v, persist_changes=True):
return self

def get_property(self, k):
# type: (str) -> T
return getattr(self, k)

def __iter__(self):
# type: () -> Iterator[Tuple[str, T]]
for n, v in vars(self).items():
yield n, v

Expand Down
6 changes: 3 additions & 3 deletions office365/runtime/client_value_collection.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import uuid
from typing import Dict, Generic, Iterator, List, Optional, TypeVar
from typing import Any, Dict, Generic, Iterator, List, Optional, TypeVar

from typing_extensions import Self

Expand Down Expand Up @@ -63,7 +63,7 @@ def to_json(self, json_format=None):
return json

def create_typed_value(self, initial_value=None):
# type: (Optional[T]) -> T
# type: (Optional[Any]) -> T
if initial_value is None:
return uuid.uuid4() if self._item_type == uuid.UUID else self._item_type()
elif self._item_type == uuid.UUID:
Expand All @@ -76,7 +76,7 @@ def create_typed_value(self, initial_value=None):
return initial_value

def set_property(self, index, value, persist_changes=False):
# type: (str | int, T, bool) -> Self
# type: (str | int, Any, bool) -> Self
client_value = self.create_typed_value(value)
self.add(client_value)
return self
Expand Down
21 changes: 13 additions & 8 deletions office365/runtime/types/event_handler.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,49 @@
import types
from typing import Callable
from typing import Callable, Iterator, TypeVar

from typing_extensions import Self
from typing_extensions import ParamSpec, Self

P = ParamSpec("P")
F = TypeVar("F", bound=Callable[..., None])


class EventHandler:
def __init__(self, once=False):
# type: (bool) -> None
self._listeners = []
self._listeners = [] # type: list[F]
self._once = once

def __contains__(self, listener):
# type: (Callable[..., None]) -> bool
# type: (F) -> bool
return listener in self._listeners

def __iter__(self):
# type: () -> Iterator[F]
return iter(self._listeners)

def __iadd__(self, listener):
# type: (Callable[..., None]) -> Self
# type: (F) -> Self
self._listeners.append(listener)
return self

def __isub__(self, listener):
# type: (Callable[..., None]) -> Self
# type: (F) -> Self
self._listeners.remove(listener)
return self

def __len__(self):
return len(self._listeners)

def notify(self, *args, **kwargs):
# type: (P.args, P.kwargs) -> None
for listener in self._listeners:
if self._once:
self._listeners.remove(listener)
listener(*args, **kwargs)

@staticmethod
def is_builtin(listener):
# type: (Callable[..., None]) -> bool
def is_system(listener):
# type: (F) -> bool
from office365.runtime.client_request import ClientRequest
from office365.runtime.client_runtime_context import ClientRuntimeContext

Expand Down
2 changes: 1 addition & 1 deletion office365/sharepoint/client_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ def _get_context_web_information(self):
client = ODataRequest(JsonLightFormat())
client.beforeExecute += self._authenticate_request
for e in self.pending_request().beforeExecute:
if not EventHandler.is_builtin(e):
if not EventHandler.is_system(e):
client.beforeExecute += e
request = RequestOptions("{0}/contextInfo".format(self.service_root_url()))
request.method = HttpMethod.Post
Expand Down
2 changes: 1 addition & 1 deletion office365/sharepoint/files/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from office365.sharepoint.types.resource_path import ResourcePath as SPResPath


class FileCollection(EntityCollection):
class FileCollection(EntityCollection[File]):
"""Represents a collection of File resources."""

def __init__(self, context, resource_path=None, parent=None):
Expand Down
2 changes: 1 addition & 1 deletion office365/sharepoint/folders/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from office365.sharepoint.types.resource_path import ResourcePath as SPResPath


class FolderCollection(EntityCollection):
class FolderCollection(EntityCollection[Folder]):
"""Represents a collection of Folder resources."""

def __init__(self, context, resource_path=None, parent=None):
Expand Down
6 changes: 3 additions & 3 deletions office365/sharepoint/listitems/listitem.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
from office365.runtime.client_value_collection import ClientValueCollection
from office365.runtime.paths.key import KeyPath
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.changes.collection import ChangeCollection
from office365.sharepoint.changes.query import ChangeQuery
from office365.sharepoint.comments.collection import CommentCollection
from office365.sharepoint.entity_collection import EntityCollection
from office365.sharepoint.fields.image_value import ImageFieldValue
from office365.sharepoint.fields.lookup_value import FieldLookupValue
from office365.sharepoint.fields.multi_lookup_value import FieldMultiLookupValue
Expand Down Expand Up @@ -65,7 +63,9 @@ def share_link(self, link_kind, expiration=None, role=None, password=None):
:param str password: Optional password value to apply to the tokenized sharing link,
if it can support password protection.
"""
return_type = ClientResult(self.context, ShareLinkResponse())
return_type = ClientResult(
self.context, ShareLinkResponse()
) # type: ClientResult[ShareLinkResponse]
request = ShareLinkRequest(
settings=ShareLinkSettings(
link_kind=link_kind, expiration=expiration, role=role, password=password
Expand Down
3 changes: 3 additions & 0 deletions office365/sharepoint/sharing/links/share_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ class ShareLinkResponse(ClientValue):
"""

def __init__(self, sharing_link_info=SharingLinkInfo()):
"""
:param SharingLinkInfo sharing_link_info:
"""
self.sharingLinkInfo = sharing_link_info

@property
Expand Down
2 changes: 1 addition & 1 deletion office365/sharepoint/tenant/administration/tenant.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def check_tenant_intune_license(self):
"""
Checks whether a tenant has the Intune license.
"""
return_type = ClientResult(self.context, bool())
return_type = ClientResult(self.context) # type: ClientResult[bool]
qry = ServiceOperationQuery(
self, "CheckTenantIntuneLicense", None, None, None, return_type
)
Expand Down

0 comments on commit eb10e17

Please sign in to comment.