Skip to content

Commit

Permalink
Bug fixes (#28), introduced a simplified way of initializing a client…
Browse files Browse the repository at this point in the history
…, improvements
  • Loading branch information
vgrem committed Mar 30, 2020
1 parent 4b32bf0 commit 043e66d
Show file tree
Hide file tree
Showing 64 changed files with 607 additions and 421 deletions.
37 changes: 18 additions & 19 deletions examples/sharepoint/file_operations.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import os

from office365.runtime.auth.UserCredential import UserCredential
from settings import settings

from office365.runtime.auth.authentication_context import AuthenticationContext
from office365.sharepoint.caml_query import CamlQuery
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.file import File
Expand Down Expand Up @@ -41,8 +41,7 @@ def read_folder_and_files(context, list_title):


def upload_file(context):

path = "../tests/data/SharePoint User Guide.docx"
path = "../../tests/data/SharePoint User Guide.docx"
with open(path, 'rb') as content_file:
file_content = content_file.read()

Expand All @@ -58,25 +57,25 @@ def upload_file(context):


def download_file(context):
response = File.open_binary(context, "/Shared Documents/SharePoint User Guide.docx")
with open("./data/SharePoint User Guide.docx", "wb") as local_file:
path = "../../tests/data/SharePoint User Guide.docx"
response = File.open_binary(context, "/teams/DemoSite/Shared Documents/SharePoint User Guide.docx")
response.raise_for_status()
with open(path, "wb") as local_file:
local_file.write(response.content)


if __name__ == '__main__':
site_url = 'https://mediadev8.sharepoint.com/teams/DemoSite/'

ctx_auth = AuthenticationContext(url=site_url)
if ctx_auth.acquire_token_for_user(username=settings['user_credentials']['username'],
password=settings['user_credentials']['password']):
# if ctx_auth.acquire_token_for_app(client_id=settings['client_credentials']['client_id'],
# client_secret=settings['client_credentials']['client_secret']):
ctx = ClientContext(site_url, ctx_auth)
# get a source file located in library 'Shared Documents'
source_file = ctx.web.get_file_by_server_relative_url("/teams/DemoSite/Shared Documents/Guide.docx")
# move a file into sub folder called 'Archive'
source_file.moveto("/teams/DemoSite/Shared Documents/Archive/Guide.docx", 1)
# execute a query
ctx.execute_query()
else:
print(ctx_auth.get_last_error())
ctx = ClientContext.connect_with_credentials(site_url, UserCredential(settings['user_credentials']['username'],
settings['user_credentials']['password']))

# upload_file(ctx)
download_file(ctx)

# get a source file located in library 'Shared Documents'
# source_file = ctx.web.get_file_by_server_relative_url("/teams/DemoSite/Shared Documents/Guide.docx")
# move a file into sub folder called 'Archive'
# source_file.moveto("/teams/DemoSite/Shared Documents/Archive/Guide.docx", 1)
# execute a query
# ctx.execute_query()
4 changes: 2 additions & 2 deletions office365/directory/directoryObjectCollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __getitem__(self, key):

def getByIds(self, ids):
"""Returns the directory objects specified in a list of IDs."""
qry = ServiceOperationQuery(self, "getByIds")
result = ClientResult(None)
self.context.add_query(qry, result)
qry = ServiceOperationQuery(self, "getByIds", None, None, None, result)
self.context.add_query(qry)
return result
4 changes: 2 additions & 2 deletions office365/directory/groupCollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def add(self, group_properties):
Office 365 group (unified group)
Security group"""
grp = Group(self.context)
qry = CreateEntityQuery(self, group_properties)
self.context.add_query(qry, grp)
self.add_child(grp)
qry = CreateEntityQuery(self, group_properties, grp)
self.context.add_query(qry)
return grp
4 changes: 2 additions & 2 deletions office365/directory/userCollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def __init__(self, context, resource_path=None):
def add(self, user_properties):
"""Create a new user."""
usr = User(self.context)
qry = CreateEntityQuery(self, user_properties)
self.context.add_query(qry, usr)
qry = CreateEntityQuery(self, user_properties, usr)
self.context.add_query(qry)
self.add_child(usr)
return usr
24 changes: 15 additions & 9 deletions office365/graphClient.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import adal
from office365.directory.directoryObjectCollection import DirectoryObjectCollection
from office365.onedrive.driveItem import DriveItem
from office365.onedrive.siteCollection import SiteCollection
from office365.runtime.client_query import UpdateEntityQuery, DeleteEntityQuery, ServiceOperationQuery
from office365.runtime.client_result import ClientResult
from office365.runtime.client_runtime_context import ClientRuntimeContext
from office365.runtime.odata.odata_request import ODataRequest
from office365.runtime.odata.v4_json_format import V4JsonFormat
from office365.runtime.resource_path import ResourcePath
from office365.runtime.http.http_method import HttpMethod
Expand All @@ -12,28 +15,31 @@
from office365.directory.userCollection import UserCollection
from office365.onedrive.driveCollection import DriveCollection
from office365.onedrive.sharedDriveItemCollection import SharedDriveItemCollection
from office365.runtime.resource_path_url import ResourcePathUrl


class DownloadContentQuery(ServiceOperationQuery):
def __init__(self, entity_type, format_name=None):
return_type = ClientResult(None)
action_name = "content"
if format_name is not None:
action_name = action_name + r"?format={0}".format(format_name)
super(DownloadContentQuery, self).__init__(entity_type, action_name, None, None)
super(DownloadContentQuery, self).__init__(entity_type, action_name, None, None, None, return_type)


class ReplaceMethodQuery(ServiceOperationQuery):
pass


class UploadContentQuery(ServiceOperationQuery):
def __init__(self, entity_type, content=None):
super(UploadContentQuery, self).__init__(entity_type, "content", None, content)
def __init__(self, parent_entity, name, content):
return_type = DriveItem(parent_entity.context, ResourcePathUrl(name, parent_entity.resourcePath))
super(UploadContentQuery, self).__init__(return_type, "content", None, content, None, return_type)


class SearchQuery(ServiceOperationQuery):
def __init__(self, entity_type, query_text):
super(SearchQuery, self).__init__(entity_type, "search", {"q": query_text}, None)
def __init__(self, entity_type, query_text, return_type):
super(SearchQuery, self).__init__(entity_type, "search", {"q": query_text}, None, None, return_type)


class GraphClient(ClientRuntimeContext):
Expand All @@ -42,15 +48,15 @@ class GraphClient(ClientRuntimeContext):
def __init__(self, tenant, acquire_token_callback):
self.__service_root_url = "https://graph.microsoft.com/v1.0/"
super(GraphClient, self).__init__(self.__service_root_url, None)
self.json_format = V4JsonFormat("minimal")
self._pending_request = ODataRequest(self, V4JsonFormat("minimal"))
self._pending_request.beforeExecute += self._build_specific_query
self._resource = "https://graph.microsoft.com"
self._authority_host_url = "https://login.microsoftonline.com"
self._tenant = tenant
self._acquire_token_callback = acquire_token_callback

def execute_query(self):
self.pending_request.before_execute_request(self._build_specific_query)
super(GraphClient, self).execute_query()
def get_pending_request(self):
return self._pending_request

@staticmethod
def _build_specific_query(request, query):
Expand Down
51 changes: 27 additions & 24 deletions office365/onedrive/driveItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from office365.runtime.resource_path import ResourcePath
from office365.onedrive.baseItem import BaseItem
from office365.onedrive.listItem import ListItem
from office365.runtime.resource_path_url import ResourcePathUrl



class DriveItem(BaseItem):
Expand All @@ -16,34 +16,34 @@ class DriveItem(BaseItem):
def create_upload_session(self, item):
"""Creates a temporary storage location where the bytes of the file will be saved until the complete file is
uploaded. """
result = ClientResult(UploadSession())
qry = ServiceOperationQuery(self,
"createUploadSession",
None,
{
"item": item
}
},
None,
result
)
result = ClientResult(UploadSession())
self.context.add_query(qry, result)
self.context.add_query(qry)
return result

def upload(self, name, content):
"""The simple upload API allows you to provide the contents of a new file or update the contents of an
existing file in a single API call. This method only supports files up to 4MB in size. """
drive_item = DriveItem(self.context, ResourcePathUrl(self.context, self.resourcePath, name))
from office365.graphClient import UploadContentQuery
qry = UploadContentQuery(drive_item, content)
self.context.add_query(qry, drive_item)
return drive_item
qry = UploadContentQuery(self, name, content)
self.context.add_query(qry)
return qry.returnType

def download(self):
"""Download the contents of the primary stream (file) of a DriveItem. Only driveItems with the file property
can be downloaded. """
from office365.graphClient import DownloadContentQuery
qry = DownloadContentQuery(self)
result = ClientResult(None)
self.context.add_query(qry, result)
return result
self.context.add_query(qry)
return qry.returnType

def create_folder(self, name):
"""Create a new folder or DriveItem in a Drive with a specified parent item or path."""
Expand All @@ -54,56 +54,59 @@ def create_folder(self, name):
"folder": {},
"@microsoft.graph.conflictBehavior": ConflictBehavior.Rename
}
qry = CreateEntityQuery(self.children, payload)
self.context.add_query(qry, drive_item)
qry = CreateEntityQuery(self.children, payload, drive_item)
self.context.add_query(qry)
return drive_item

def convert(self, format_name):
"""Converts the contents of an item in a specific format"""
from office365.graphClient import DownloadContentQuery
qry = DownloadContentQuery(self, format_name)
result = ClientResult(None)
self.context.add_query(qry, result)
return result
self.context.add_query(qry)
return qry.returnType

def copy(self, name, parent_reference=None):
"""Asynchronously creates a copy of an driveItem (including any children), under a new parent item or with a
new name. """
result = ClientResult(None)
qry = ServiceOperationQuery(self,
"copy",
None,
{
"name": name,
"parentReference": parent_reference
}
},
None,
result
)
result = ClientResult(None)
self.context.add_query(qry, result)
self.context.add_query(qry)
return result

def move(self, name, parent_reference=None):
"""To move a DriveItem to a new parent item, your app requests to update the parentReference of the DriveItem
to move. """
from office365.graphClient import ReplaceMethodQuery
result = ClientResult(None)
qry = ReplaceMethodQuery(self,
"move",
None,
{
"name": name,
"parentReference": parent_reference
}
},
None,
result
)
result = ClientResult(None)
self.context.add_query(qry, result)
self.context.add_query(qry)
return result

def search(self, query_text):
"""Search the hierarchy of items for items matching a query. You can search within a folder hierarchy,
a whole drive, or files shared with the current user. """
from office365.graphClient import SearchQuery
qry = SearchQuery(self, query_text)
result = ClientResult(None)
self.context.add_query(qry, result)
qry = SearchQuery(self, query_text, result)
self.context.add_query(qry)
return result

@property
Expand Down
2 changes: 1 addition & 1 deletion office365/onedrive/driveItemCollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ def get_by_id(self, _id):
def get_by_url(self, url):
"""Retrieve DriveItem by url"""
return DriveItem(self.context,
ResourcePathUrl(self.context, self.resourcePath, url))
ResourcePathUrl(url, self.resourcePath))
10 changes: 5 additions & 5 deletions office365/onedrive/listCollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ def __init__(self, context, resource_path=None):

def add(self, list_creation_information):
"""Creates a Drive list resource"""
new_list = List(self.context)
qry = CreateEntityQuery(self, list_creation_information)
self.context.add_query(qry, new_list)
self.add_child(new_list)
return new_list
target_list = List(self.context)
self.add_child(target_list)
qry = CreateEntityQuery(self, list_creation_information, target_list)
self.context.add_query(qry)
return target_list
8 changes: 4 additions & 4 deletions office365/outlookservices/contact_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ def __init__(self, context, resource_path=None):
def add_from_json(self, contact_creation_information):
"""Creates a Contact resource from JSON"""
contact = Contact(self.context)
qry = CreateEntityQuery(self, contact_creation_information)
self.context.add_query(qry, contact)
self.add_child(contact)
qry = CreateEntityQuery(self, contact_creation_information, contact)
self.context.add_query(qry)
return contact

def add(self):
"""Creates a Contact resource"""
contact = Contact(self.context)
qry = CreateEntityQuery(self, contact)
self.context.add_query(qry, contact)
self.add_child(contact)
qry = CreateEntityQuery(self, contact, contact)
self.context.add_query(qry)
return contact

def get_by_id(self, contact_id):
Expand Down
4 changes: 2 additions & 2 deletions office365/outlookservices/event_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __init__(self, context, resource_path=None):
def add_from_json(self, event_creation_information):
"""Creates a Event resource from JSON"""
event = Event(self.context)
qry = CreateEntityQuery(self, event_creation_information)
self.context.add_query(qry, event)
self.add_child(event)
qry = CreateEntityQuery(self, event_creation_information, event)
self.context.add_query(qry)
return event
4 changes: 2 additions & 2 deletions office365/outlookservices/messageCollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __init__(self, context, resource_path=None):
def add_from_json(self, message_creation_information):
"""Create a draft of a new message from JSON"""
contact = Message(self.context)
qry = CreateEntityQuery(self, message_creation_information)
self.context.add_query(qry, contact)
self.add_child(contact)
qry = CreateEntityQuery(self, message_creation_information, contact)
self.context.add_query(qry)
return contact
9 changes: 5 additions & 4 deletions office365/outlookservices/outlook_client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from office365.runtime.client_query import UpdateEntityQuery, DeleteEntityQuery
from office365.runtime.client_runtime_context import ClientRuntimeContext
from office365.runtime.odata.odata_request import ODataRequest
from office365.runtime.odata.v4_json_format import V4JsonFormat
from office365.runtime.resource_path import ResourcePath
from office365.runtime.http.http_method import HttpMethod
Expand All @@ -12,11 +13,11 @@ class OutlookClient(ClientRuntimeContext):
def __init__(self, ctx_auth):
self.__service_root_url = "https://outlook.office365.com/api/v1.0/"
super(OutlookClient, self).__init__(self.__service_root_url, ctx_auth)
self.json_format = V4JsonFormat("minimal")
self._pendingRequest = ODataRequest(self, V4JsonFormat("minimal"))
self._pendingRequest.beforeExecute += self._build_specific_query

def execute_query(self):
self.pending_request.before_execute_request(self._build_specific_query)
super(OutlookClient, self).execute_query()
def get_pending_request(self):
return self._pendingRequest

@staticmethod
def _build_specific_query(request, query):
Expand Down
5 changes: 5 additions & 0 deletions office365/runtime/auth/ClientCredential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class ClientCredential(object):

def __init__(self, client_id, client_secret):
self.clientId = client_id
self.clientSecret = client_secret
5 changes: 5 additions & 0 deletions office365/runtime/auth/UserCredential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class UserCredential(object):

def __init__(self, user_name, password):
self.userName = user_name
self.password = password

0 comments on commit 043e66d

Please sign in to comment.