Skip to content

Commit 7c0dce9

Browse files
committed
fix: rewrite upload_large.py to use resumable_upload with progress and real file
1 parent 757a7b8 commit 7c0dce9

85 files changed

Lines changed: 185 additions & 64 deletions

File tree

Some content is hidden

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

examples/onedrive/files/sharing.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
# 1. Create an anonymous view link
3333
link = item.create_link("view", "anonymous").execute_query()
34-
print(f"Anonymous link: {link.link.web_url}")
34+
print(f"Anonymous link: {link.link.webUrl}")
3535

3636
# 2. Send a sharing invitation to a user
3737
invite = item.invite(
@@ -45,5 +45,4 @@
4545
permissions = item.permissions.get().execute_query()
4646
print(f"Permissions ({len(permissions)}):")
4747
for p in permissions:
48-
roles = p.roles or []
49-
print(f" ID: {p.id} roles: {', '.join(roles)}")
48+
print(f" ID: {p.id} roles: {', '.join(p.roles)}")
Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
11
"""
22
Upload a large file using a resumable upload session.
33
4-
Files larger than ~4 MB should use the resumable upload session.
5-
The SDK handles chunked upload automatically.
4+
Reads from disk in chunks with progress reporting.
5+
No full file loaded into memory.
66
7-
Requires delegated permission ``Files.ReadWrite``.
8-
9-
https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession
7+
Requires delegated permission Files.ReadWrite.
108
"""
119

10+
import os
11+
from pathlib import Path
12+
1213
from office365.graph_client import GraphClient
1314
from tests import test_client_id, test_password, test_tenant, test_username
1415

15-
client = GraphClient(tenant=test_tenant).with_username_and_password(test_client_id, test_username, test_password)
1616

17-
# Create a 5 MB file in memory
18-
content = b"A" * 5_000_000
19-
uploaded = client.me.drive.root.upload("large_file.bin", content).execute_query()
20-
print(f"Uploaded: {uploaded.name} ({len(content)} bytes)")
21-
print(f"Web URL: {uploaded.web_url}")
17+
def main():
18+
client = GraphClient(tenant=test_tenant).with_username_and_password(test_client_id, test_username, test_password)
19+
20+
local_path = Path("../../../tests/data/big_buck_bunny.mp4")
21+
file_size = os.path.getsize(local_path)
22+
23+
def print_progress(uploaded_bytes: int) -> None:
24+
pct = uploaded_bytes / file_size * 100
25+
print(f" Uploaded {uploaded_bytes:,} / {file_size:,} bytes ({pct:.1f}%)")
26+
27+
print(f"Uploading {local_path.name} ({file_size:,} bytes)...")
28+
uploaded = client.me.drive.root.resumable_upload(str(local_path), chunk_uploaded=print_progress).execute_query()
29+
print(f"Uploaded: {uploaded.web_url}")
30+
31+
32+
if __name__ == "__main__":
33+
main()

generator/.checkpoints/SharePoint.xml.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

generator/settings.sharepoint.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[sharepoint]
22
metadata_path = ./metadata/SharePoint.xml
3-
output_path = ../office365/sharepoint
3+
output_path = ../office365
44
template_path = ./templates/sharepoint
55
include_base_types = ComplexType
66

office365/intune/organizations/organization.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from office365.runtime.client_value_collection import ClientValueCollection
1212
from office365.runtime.paths.resource_path import ResourcePath
1313
from office365.runtime.types.collections import StringCollection
14+
from office365.runtime.types.odata_property import odata
1415

1516

1617
class Organization(DirectoryObject):
@@ -19,6 +20,7 @@ class Organization(DirectoryObject):
1920
which operate and are provisioned at the tenant-level.
2021
"""
2122

23+
@odata(name="assignedPlans")
2224
@property
2325
def assigned_plans(self) -> ClientValueCollection[AssignedPlan]:
2426
"""The plans that are assigned to the organization."""
@@ -31,6 +33,7 @@ def branding(self) -> OrganizationalBranding:
3133
OrganizationalBranding(self.context, ResourcePath("branding", self.resource_path)),
3234
)
3335

36+
@odata(name="businessPhones")
3437
@property
3538
def business_phones(self) -> StringCollection:
3639
"""
@@ -47,6 +50,7 @@ def extensions(self) -> EntityCollection[Extension]:
4750
EntityCollection(self.context, Extension, ResourcePath("extensions", self.resource_path)),
4851
)
4952

53+
@odata(name="certificateBasedAuthConfiguration")
5054
@property
5155
def certificate_based_auth_configuration(self) -> EntityCollection[CertificateBasedAuthConfiguration]:
5256
"""Navigation property to manage certificate-based authentication configuration.
@@ -61,23 +65,13 @@ def certificate_based_auth_configuration(self) -> EntityCollection[CertificateBa
6165
),
6266
)
6367

68+
@odata(name="provisionedPlans")
6469
@property
6570
def provisioned_plans(self) -> ClientValueCollection[ProvisionedPlan]:
6671
return self.properties.get("provisionedPlans", ClientValueCollection(ProvisionedPlan))
6772

73+
@odata(name="verifiedDomains")
6874
@property
6975
def verified_domains(self) -> ClientValueCollection[VerifiedDomain]:
7076
"""The collection of domains associated with this tenant."""
7177
return self.properties.get("verifiedDomains", ClientValueCollection(VerifiedDomain))
72-
73-
def get_property(self, name, default_value=None):
74-
if default_value is None:
75-
property_mapping = {
76-
"assignedPlans": self.assigned_plans,
77-
"certificateBasedAuthConfiguration": self.certificate_based_auth_configuration,
78-
"businessPhones": self.business_phones,
79-
"provisionedPlans": self.provisioned_plans,
80-
"verifiedDomains": self.verified_domains,
81-
}
82-
default_value = property_mapping.get(name, None)
83-
return super().get_property(name, default_value)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
from office365.entity import Entity
2+
from office365.runtime.paths.builder import ODataPathBuilder
23

34

45
class OnenoteEntityBaseModel(Entity):
56
"""This is the base type for OneNote entities."""
7+
8+
def set_property(self, name, value, persist_changes=True):
9+
super().set_property(name, value, persist_changes)
10+
if name == "self" and self.resource_url != value:
11+
# Fallback to canonical path
12+
path_str = value.replace(self.context.service_root_url, "")
13+
self._resource_path = ODataPathBuilder.parse_url(path_str)
14+
return self

office365/onenote/notebooks/notebook.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,5 @@ def section_groups(self):
4141
)
4242

4343
@property
44-
def entity_type_name(self):
44+
def entity_type_name(self) -> str:
4545
return None # type: ignore

office365/onenote/sections/section.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,5 @@ def parent_section_group(self) -> SectionGroup:
101101
)
102102

103103
@property
104-
def entity_type_name(self):
104+
def entity_type_name(self) -> str:
105105
return None # type: ignore
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from __future__ import annotations
2+
3+
from dataclasses import field
4+
5+
from office365.runtime.client_value import ClientValue
6+
from office365.runtime.types.collections import StringCollection
7+
8+
9+
class TenantServiceInfoValue(ClientValue):
10+
deletedDateTime: str | None = None
11+
objectId: str | None = None
12+
serviceElements: StringCollection = field(default_factory=StringCollection)
13+
serviceInstance: str | None = None
14+
version: int | None = None
15+
16+
@property
17+
def entity_type_name(self) -> str:
18+
return "SP.Directory.TenantServiceInfoValue"

office365/sharepoint/multigeo/service/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)