Skip to content

Commit 37e3b29

Browse files
committed
AttachmentCollection.download method introduced, model updates
1 parent b2d4802 commit 37e3b29

File tree

18 files changed

+188
-45
lines changed

18 files changed

+188
-45
lines changed

.github/workflows/python-app.yml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,3 @@ jobs:
6767
run: |
6868
echo "${{env.office365_python_sdk_securevars}}"
6969
pytest
70-
71-
# - name: Lint with flake8
72-
# run: |
73-
# # stop the build if there are Python syntax errors or undefined names
74-
# flake8 office365 --count --select=E9,F63,F7,F82 --show-source --statistics
75-
# # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
76-
# flake8 office365 --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,28 @@
1+
"""
2+
Demonstrates how to download list item attachments
3+
"""
14
import os
25
import tempfile
36

7+
from office365.sharepoint.attachments.attachment import Attachment
48
from office365.sharepoint.client_context import ClientContext
59
from tests import test_client_credentials, test_team_site_url
610

7-
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
811

9-
download_path = tempfile.mkdtemp()
12+
def print_progress(attachment_file):
13+
# type: (Attachment) -> None
14+
print(
15+
"{0} has been downloaded".format(attachment_file.server_relative_url)
16+
)
17+
18+
19+
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
1020

1121
list_title = "Company Tasks"
1222
source_list = ctx.web.lists.get_by_title(list_title)
13-
items = source_list.items
14-
ctx.load(items, ["ID", "UniqueId", "FileRef", "LinkFilename", "Title", "Attachments"])
15-
ctx.execute_query()
23+
items = source_list.items.get().execute_query()
1624
for item in items:
17-
if item.properties[
18-
"Attachments"
19-
]: # 1. determine whether ListItem contains attachments
20-
# 2. Explicitly load attachments for ListItem
21-
attachment_files = item.attachment_files.get().execute_query()
22-
# 3. Enumerate and save attachments
23-
for attachment_file in attachment_files:
24-
download_file_name = os.path.join(
25-
download_path, os.path.basename(attachment_file.file_name)
26-
)
27-
with open(download_file_name, "wb") as fh:
28-
attachment_file.download(fh).execute_query()
29-
print(
30-
f"{attachment_file.server_relative_url} has been downloaded into {download_file_name}"
31-
)
25+
zip_path = os.path.join(tempfile.mkdtemp(), "attachments_{0}.zip".format(item.id))
26+
with open(zip_path, "wb") as f:
27+
item.attachment_files.download(f, print_progress).execute_query()
28+
print("{0} attachments has been downloaded...".format(zip_path))
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
Demonstrates how to download list item attachments
3+
"""
4+
import os
5+
import tempfile
6+
7+
from office365.sharepoint.client_context import ClientContext
8+
from tests import test_client_credentials, test_team_site_url
9+
10+
download_path = tempfile.mkdtemp()
11+
list_title = "Company Tasks"
12+
13+
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
14+
source_list = ctx.web.lists.get_by_title(list_title)
15+
items = source_list.items.get().execute_query()
16+
for item in items:
17+
attachment_files = item.attachment_files.get().execute_query()
18+
for attachment_file in attachment_files:
19+
download_file_name = os.path.join(
20+
download_path, os.path.basename(attachment_file.file_name)
21+
)
22+
with open(download_file_name, "wb") as fh:
23+
attachment_file.download(fh).execute_query()
24+
print(
25+
f"{attachment_file.server_relative_url} has been downloaded into {download_file_name}"
26+
)
27+

office365/directory/identitygovernance/appconsent/request.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
from typing import Optional
2+
3+
from office365.directory.identitygovernance.appconsent.request_scope import (
4+
AppConsentRequestScope,
5+
)
16
from office365.directory.identitygovernance.userconsent.request_collection import (
27
UserConsentRequestCollection,
38
)
49
from office365.entity import Entity
10+
from office365.runtime.client_value_collection import ClientValueCollection
511
from office365.runtime.paths.resource_path import ResourcePath
612

713

@@ -15,6 +21,32 @@ class AppConsentRequest(Entity):
1521
the admin consent workflow is enabled.
1622
"""
1723

24+
def __str__(self):
25+
return self.app_display_name or self.entity_type_name
26+
27+
def __repr__(self):
28+
return self.app_id or self.entity_type_name
29+
30+
@property
31+
def app_display_name(self):
32+
# type: () -> Optional[str]
33+
"""Display name of the application object on which this extension property is defined. Read-only"""
34+
return self.properties.get("appDisplayName", None)
35+
36+
@property
37+
def app_id(self):
38+
# type: () -> Optional[str]
39+
"""The identifier of the application"""
40+
return self.properties.get("appId", None)
41+
42+
@property
43+
def pending_scopes(self):
44+
# type: () -> ClientValueCollection[AppConsentRequestScope]
45+
"""A list of pending scopes waiting for approval. Required."""
46+
return self.properties.get(
47+
"pendingScopes", ClientValueCollection(AppConsentRequestScope)
48+
)
49+
1850
@property
1951
def user_consent_requests(self):
2052
"""A list of pending user consent requests."""
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from office365.runtime.client_value import ClientValue
2+
3+
4+
class AppConsentRequestScope(ClientValue):
5+
"""The appConsentRequestScope details the dynamic permission scopes for which access is being requested."""
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from office365.entity import Entity
2+
3+
4+
class PrivilegedAccessGroup(Entity):
5+
"""The entry point for all resources related to Privileged Identity Management (PIM) for groups."""
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
1+
from office365.directory.identitygovernance.privilegedaccess.group import (
2+
PrivilegedAccessGroup,
3+
)
14
from office365.entity import Entity
5+
from office365.runtime.paths.resource_path import ResourcePath
26

37

48
class PrivilegedAccessRoot(Entity):
59
"""Represents the entry point for resources related to Privileged Identity Management (PIM)."""
10+
11+
@property
12+
def group(self):
13+
"""A list of pending user consent requests."""
14+
return self.properties.get(
15+
"group",
16+
PrivilegedAccessGroup(
17+
self.context, ResourcePath("group", self.resource_path)
18+
),
19+
)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from office365.entity import Entity
2+
3+
4+
class PrivilegedAccessScheduleInstance(Entity):
5+
"""An abstract type that exposes properties relating to the instances of membership and ownership assignments
6+
and eligibilities to groups that are governed by PIM"""
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from office365.entity import Entity
2+
3+
4+
class AdminConsentRequestPolicy(Entity):
5+
"""
6+
Represents the policy for enabling or disabling the Microsoft Entra admin consent workflow.
7+
The admin consent workflow allows users to request access for apps that they wish to use and that require admin
8+
authorization before users can use the apps to access organizational data.
9+
There is a single adminConsentRequestPolicy per tenant.
10+
"""

office365/directory/policies/root.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from office365.directory.policies.admin_consent_request import AdminConsentRequestPolicy
12
from office365.directory.policies.app_management import AppManagementPolicy
23
from office365.directory.policies.authentication_flows import AuthenticationFlowsPolicy
34
from office365.directory.policies.authentication_methods import (
@@ -20,6 +21,19 @@
2021
class PolicyRoot(Entity):
2122
"""Resource type exposing navigation properties for the policies singleton."""
2223

24+
@property
25+
def admin_consent_request_policy(self):
26+
"""
27+
The policy by which consent requests are created and managed for the entire tenant.
28+
"""
29+
return self.properties.get(
30+
"adminConsentRequestPolicy",
31+
AdminConsentRequestPolicy(
32+
self.context,
33+
ResourcePath("adminConsentRequestPolicy", self.resource_path),
34+
),
35+
)
36+
2337
@property
2438
def authentication_methods_policy(self):
2539
"""
@@ -151,6 +165,7 @@ def conditional_access_policies(self):
151165
def get_property(self, name, default_value=None):
152166
if default_value is None:
153167
property_mapping = {
168+
"adminConsentRequestPolicy": self.admin_consent_request_policy,
154169
"authenticationStrengthPolicies": self.authentication_strength_policies,
155170
"authenticationFlowsPolicy": self.authentication_flows_policy,
156171
"appManagementPolicies": self.app_management_policies,

0 commit comments

Comments
 (0)