Skip to content

Commit d923bba

Browse files
committed
feat(cli): add csv download functionality to device commands
Add download_activity_csv utility function to handle downloading activity reports and integrate it with both assign_device and unassign_device commands to provide users with downloaded CSV files when available.
1 parent c4a1737 commit d923bba

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

pyaxm/cli.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing_extensions import Annotated
55
from typing import List
66
from pyaxm.client import Client
7+
from pyaxm.utils import download_activity_csv
78

89
app = typer.Typer()
910

@@ -80,6 +81,10 @@ def assign_device(device_id: Annotated[List[str], typer.Argument()], server_id:
8081
df = pd.DataFrame([activity_data])
8182
df.to_csv(sys.stdout, index=False)
8283

84+
file_path = download_activity_csv(activity)
85+
if file_path:
86+
typer.echo(f"Report downloaded successfully to: {file_path}")
87+
8388
@app.command()
8489
def unassign_device(device_id: Annotated[List[str], typer.Argument()], server_id: Annotated[str, typer.Argument()]):
8590
"""Unassign one or more devices from an MDM server."""
@@ -89,6 +94,10 @@ def unassign_device(device_id: Annotated[List[str], typer.Argument()], server_id
8994
activity_data.update(activity.attributes.model_dump())
9095
df = pd.DataFrame([activity_data])
9196
df.to_csv(sys.stdout, index=False)
97+
98+
file_path = download_activity_csv(activity)
99+
if file_path:
100+
typer.echo(f"Report downloaded successfully to: {file_path}")
92101

93102
if __name__ == "__main__":
94103
app()

pyaxm/utils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import os
2+
import re
3+
import requests
4+
from typing import Optional
5+
from urllib.parse import urlparse, parse_qs
6+
from pyaxm.models import OrgDeviceActivity
7+
8+
9+
def download_activity_csv(activity: OrgDeviceActivity, save_path: str = None) -> Optional[str]:
10+
"""
11+
Download CSV file from activity if download URL is available.
12+
13+
:param activity: OrgDeviceActivity object with attributes.downloadUrl property
14+
:param save_path: Optional path to save file (defaults to current directory)
15+
:return: Path to saved file or None if no download URL
16+
"""
17+
if not save_path:
18+
save_path = os.getcwd()
19+
20+
if not (activity.attributes and activity.attributes.downloadUrl):
21+
return None
22+
23+
url = activity.attributes.downloadUrl
24+
parsed_url = urlparse(url)
25+
query_params = parse_qs(parsed_url.query)
26+
27+
disposition = query_params['response-content-disposition'][0]
28+
match = re.search(r'filename="([^"]+)"', disposition)
29+
filename = match.group(1)
30+
31+
file_path = os.path.join(save_path, filename)
32+
33+
response = requests.get(url)
34+
response.raise_for_status()
35+
36+
with open(file_path, 'wb') as f:
37+
f.write(response.content)
38+
39+
return file_path

0 commit comments

Comments
 (0)