Skip to content

Commit 0135f15

Browse files
committed
Refactor file session upload method in SharePoint API, typing improvements
1 parent 29f2349 commit 0135f15

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+354
-371
lines changed

examples/sharepoint/fields/get_from_web.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
This example retrieves all fields in a SharePoint site.
2+
This example demonstrates how to retrieve all fields in a SharePoint site.
33
"""
44
from office365.sharepoint.client_context import ClientContext
55
from tests import test_client_credentials, test_team_site_url

examples/sharepoint/files/delete.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
"""
2+
Deletes a file from SharePoint site
3+
"""
14
from office365.sharepoint.client_context import ClientContext
25
from tests import test_team_site_url, test_user_credentials
36

47
ctx = ClientContext(test_team_site_url).with_credentials(test_user_credentials)
5-
68
file_url = "Shared Documents/SharePoint User Guide.docx"
79
file = ctx.web.get_file_by_server_relative_url(file_url)
810
file.delete_object().execute_query()

examples/sharepoint/files/download_recent.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import tempfile
33

44
from office365.sharepoint.client_context import ClientContext
5-
from office365.sharepoint.listitems.listitem import ListItem
65
from tests import test_site_url, test_user_credentials
76

87
ctx = ClientContext(test_site_url).with_credentials(test_user_credentials)
@@ -16,7 +15,7 @@
1615
.get()
1716
.execute_query()
1817
)
19-
for item in recent_items: # type: ListItem
18+
for item in recent_items:
2019
file_url = item.properties.get("FileRef")
2120
download_path = os.path.join(tempfile.mkdtemp(), os.path.basename(file_url))
2221
with open(download_path, "wb") as local_file:

examples/sharepoint/files/traverse.py examples/sharepoint/files/get_all_items.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from tests import test_client_credentials, test_team_site_url
55

66
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
7-
doc_lib = ctx.web.lists.get_by_title("Documents_Archive")
7+
doc_lib = ctx.web.default_document_library()
88
items = (
99
doc_lib.items.select(["FileSystemObjectType"])
1010
.expand(["File", "Folder"])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
Retrieves file check out status
3+
4+
https://support.microsoft.com/en-us/office/check-out-or-check-in-files-in-a-document-library-acce24cd-ab39-4fcf-9c4d-1ce3050dc602
5+
"""
6+
7+
from office365.sharepoint.client_context import ClientContext
8+
from tests import test_client_credentials, test_team_site_url
9+
10+
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
11+
file_url = "SitePages/Home.aspx"
12+
file = ctx.web.get_file_by_server_relative_url(file_url).get().execute_query()
13+
14+
if file.check_out_type == 0:
15+
print("The file is checked out for editing on the server")
16+
elif file.check_out_type == 1:
17+
print("The file is checked out for editing on the local computer.")
18+
else:
19+
print("The file is not checked out.")

examples/sharepoint/files/get_content.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"""
2-
Demonstrates how to download a file content (intended for a small files with a size less than 4 Mb)
2+
Demonstrates how to download a file content.
3+
Intended for a 'small' files (with a size less than 4 Mb)
34
"""
45

56
from office365.sharepoint.client_context import ClientContext
67
from tests import test_client_credentials, test_team_site_url
78

89
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
9-
file_url = "SitePages/Home.aspx"
1010
file = ctx.web.lists.get_by_title("Site Pages").root_folder.files.get_by_url(
1111
"Home.aspx"
1212
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
Retrieves file extended properties (accessible via associated ListItem)
3+
"""
4+
5+
from office365.sharepoint.client_context import ClientContext
6+
from tests import test_client_credentials, test_team_site_url
7+
8+
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
9+
file_url = "SitePages/Home.aspx"
10+
file_item = (
11+
ctx.web.get_file_by_server_relative_url(file_url)
12+
.listItemAllFields.get()
13+
.execute_query()
14+
)
15+
for k, v in file_item.properties.items():
16+
print("{0}: {1}".format(k, v))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""
2+
Retrieves file system metadata
3+
"""
4+
5+
from office365.sharepoint.client_context import ClientContext
6+
from tests import test_client_credentials, test_team_site_url
7+
8+
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
9+
file_url = "SitePages/Home.aspx"
10+
file = (
11+
ctx.web.get_file_by_server_relative_url(file_url)
12+
.expand(["ModifiedBy", "Author", "TimeCreated", "TimeLastModified"])
13+
.get()
14+
.execute_query()
15+
)
16+
17+
print(file.author)
18+
print(file.modified_by)
19+
print(file.time_created)
20+
print(file.time_last_modified)

examples/sharepoint/files/get_version.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"""
44

55
from office365.sharepoint.client_context import ClientContext
6-
from office365.sharepoint.files.versions.version import FileVersion
76
from tests import test_client_credentials, test_team_site_url
87

98
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
@@ -14,5 +13,5 @@
1413
.get()
1514
.execute_query()
1615
)
17-
for version in file_with_versions.versions: # type: FileVersion
16+
for version in file_with_versions.versions:
1817
print(version.version_label)

examples/sharepoint/files/list.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@ def enum_folder(parent_folder, fn):
1919

2020

2121
def print_file(f):
22-
"""
23-
:type f: File
24-
"""
25-
print(f.properties["ServerRelativeUrl"])
22+
# type: (File) -> None
23+
print(f.serverRelativeUrl)
2624

2725

2826
target_folder_url = "Shared Documents"

examples/sharepoint/files/upload_large.py

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010

1111
def print_upload_progress(offset):
12+
# type: (int) -> None
1213
file_size = os.path.getsize(local_path)
1314
print(
1415
"Uploaded '{0}' bytes from '{1}'...[{2}%]".format(

examples/sharepoint/folders/get_folder_files.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Prints file names in a folder
2+
Gets files within a folder
33
"""
44
from office365.sharepoint.client_context import ClientContext
55
from tests import test_client_credentials, test_team_site_url
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
"""
2-
Share a Folder with External User
2+
Share a folder with a set of users
33
"""
44

5-
import json
6-
75
from office365.sharepoint.client_context import ClientContext
8-
from office365.sharepoint.sharing.role_type import RoleType
6+
from office365.sharepoint.sharing.role import Role
97
from office365.sharepoint.sharing.user_role_assignment import UserRoleAssignment
108
from tests import (
119
test_client_credentials,
@@ -16,6 +14,7 @@
1614
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
1715
folder_url = "Shared Documents/Archive"
1816
folder = ctx.web.get_folder_by_server_relative_path(folder_url)
19-
assignment = UserRoleAssignment(RoleType.Guest, test_user_principal_name_alt)
17+
assignment = UserRoleAssignment(Role.Edit, test_user_principal_name_alt)
2018
result = folder.update_document_sharing_info([assignment]).execute_query()
21-
print(json.dumps(result.value.to_json(), indent=4))
19+
for item in result.value:
20+
print(item)

examples/sharepoint/hubsites/__init__.py

Whitespace-only changes.
+5-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import json
2-
1+
"""
2+
Gets information about all hub sites that the current user can access.
3+
"""
34
from office365.sharepoint.client_context import ClientContext
45
from tests import test_team_site_url, test_user_credentials
56

67
ctx = ClientContext(test_team_site_url).with_credentials(test_user_credentials)
78
hub_sites = ctx.hub_sites.get().execute_query()
8-
print(json.dumps(hub_sites.to_json(), indent=4))
9+
for hub_site in hub_sites:
10+
print(hub_site)

examples/sharepoint/lists/delete.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Delete a SharePoint list
2+
Deletes a SharePoint list
33
"""
44
from office365.sharepoint.client_context import ClientContext
55
from tests import test_client_credentials, test_team_site_url

examples/sharepoint/export/save_list_as_template.py examples/sharepoint/lists/save_as_template.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
"""
2+
Saves the list as a template in the list template gallery
3+
"""
14
from office365.sharepoint.client_context import ClientContext
25
from tests import test_client_credentials, test_team_site_url
36

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
Revokes user access from web
3+
"""
4+
from office365.sharepoint.client_context import ClientContext
5+
from office365.sharepoint.sharing.role_type import RoleType
6+
from tests import (
7+
test_client_credentials,
8+
test_team_site_url,
9+
test_user_principal_name_alt,
10+
)
11+
12+
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
13+
result = ctx.web.remove_role_assignment(
14+
test_user_principal_name_alt, RoleType.Contributor
15+
).execute_query()
16+
print("Access has been revoked")

examples/sharepoint/print_server_settings.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
2+
Prints server settings
33
"""
44

55
from office365.sharepoint.client_context import ClientContext
@@ -12,4 +12,4 @@
1212
installed_languages = ServerSettings.get_global_installed_languages(ctx, 15)
1313
ctx.execute_batch()
1414
print("Is SharePoint Online? : {0}".format(is_online.value))
15-
print("Installed languages amount : {0}".format(len(installed_languages.items)))
15+
print("Installed languages : {0}".format(installed_languages))

examples/sharepoint/search/search_documents.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
"""
2+
3+
"""
14
from office365.sharepoint.client_context import ClientContext
25
from tests import test_site_url, test_user_credentials
36

examples/sharepoint/search/search_sites.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""
22
Search SharePoint sites the current user is member of
3-
43
"""
54

65
from office365.sharepoint.client_context import ClientContext

office365/sharepoint/clientsidecomponent/hostedapps/manager.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44

55

66
class HostedAppsManager(Entity):
7-
def get_by_id(self, _id):
7+
def get_by_id(self, id_):
88
"""
99
Gets an hosted app based on the Id.
1010
11-
:param str _id: The Id of the hosted app to get.
11+
:param str id_: The Id of the hosted app to get.
1212
"""
1313
return HostedApp(
14-
self.context, ServiceOperationPath("GetById", [_id], self.resource_path)
14+
self.context, ServiceOperationPath("GetById", [id_], self.resource_path)
1515
)
1616

1717
@property

office365/sharepoint/contenttypes/content_type_id.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ def __init__(self, string_value=None):
2020
self.StringValue = string_value
2121

2222
def __repr__(self):
23-
return self.StringValue
23+
return self.StringValue or self.entity_type_name

office365/sharepoint/fields/field.py

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ class Field(Entity):
1414
def __init__(self, context, resource_path=None):
1515
super(Field, self).__init__(context, resource_path)
1616

17+
def __repr__(self):
18+
return self.internal_name or self.id
19+
1720
@staticmethod
1821
def resolve_field_type(type_id_or_name):
1922
from office365.sharepoint.fields.calculated import FieldCalculated

office365/sharepoint/files/collection.py

+50-12
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import os
2+
import uuid
3+
from typing import IO, Callable
24

5+
from office365.runtime.client_result import ClientResult
36
from office365.runtime.paths.service_operation import ServiceOperationPath
47
from office365.runtime.queries.service_operation import ServiceOperationQuery
58
from office365.sharepoint.entity_collection import EntityCollection
69
from office365.sharepoint.files.creation_information import FileCreationInformation
710
from office365.sharepoint.files.file import File
8-
from office365.sharepoint.internal.queries.upload_session import (
9-
create_upload_session_query_ex,
10-
)
1111
from office365.sharepoint.types.resource_path import ResourcePath as SPResPath
1212

1313

@@ -35,21 +35,59 @@ def upload(self, path_or_file):
3535
return self.add(name, content, True)
3636

3737
def create_upload_session(
38-
self, path_or_file, chunk_size, chunk_uploaded=None, **kwargs
38+
self, file, chunk_size, chunk_uploaded=None, file_name=None, **kwargs
3939
):
40+
# type: (IO|str, int, Callable[[int, ...], None], str, ...) -> File
4041
"""Upload a file as multiple chunks
41-
42-
:param str or typing.IO path_or_file: path where file to upload resides or file handle
42+
:param str or typing.IO file: path where file to upload resides or file handle
4343
:param int chunk_size: upload chunk size (in bytes)
4444
:param (long)->None or None chunk_uploaded: uploaded event
45+
:param str file_name: custom file name
4546
:param kwargs: arguments to pass to chunk_uploaded function
4647
"""
4748

48-
qry = create_upload_session_query_ex(
49-
self, path_or_file, chunk_size, chunk_uploaded, **kwargs
50-
)
51-
self.context.add_query(qry)
52-
return qry.return_type
49+
auto_close = False
50+
if not hasattr(file, "read"):
51+
file = open(file, "rb")
52+
auto_close = True
53+
54+
file_size = os.fstat(file.fileno()).st_size
55+
file_name = file_name if file_name else os.path.basename(file.name)
56+
upload_id = str(uuid.uuid4())
57+
58+
def _upload_session(return_type, return_file):
59+
# type: (File|ClientResult, File) -> None
60+
if return_file is None:
61+
return_file = return_type
62+
63+
uploaded_bytes = file.tell()
64+
if callable(chunk_uploaded):
65+
chunk_uploaded(uploaded_bytes, **kwargs)
66+
67+
if uploaded_bytes == file_size:
68+
if auto_close and not file.closed:
69+
file.close()
70+
return
71+
72+
content = file.read(chunk_size)
73+
74+
if uploaded_bytes == 0:
75+
return_file.start_upload(upload_id, content).after_execute(
76+
_upload_session, return_file
77+
)
78+
elif uploaded_bytes + len(content) < file_size:
79+
return_file.continue_upload(
80+
upload_id, uploaded_bytes, content
81+
).after_execute(_upload_session, return_file)
82+
else:
83+
return_file.finish_upload(
84+
upload_id, uploaded_bytes, content
85+
).after_execute(_upload_session, return_file)
86+
87+
if file_size > chunk_size:
88+
return self.add(file_name, None, True).after_execute(_upload_session, None)
89+
else:
90+
return self.add(file_name, file.read(), True)
5391

5492
def add(self, url, content, overwrite=False):
5593
"""
@@ -60,7 +98,7 @@ def add(self, url, content, overwrite=False):
6098
or absolute form. Its length MUST be equal to or greater than 1.
6199
:param bool overwrite: Specifies whether to overwrite an existing file with the same name and in the same
62100
location as the one being added.
63-
:param str or bytes content: Specifies the binary content of the file to be added.
101+
:param str or bytes or None content: Specifies the binary content of the file to be added.
64102
"""
65103
return_type = File(self.context)
66104
self.add_child(return_type)

0 commit comments

Comments
 (0)