Skip to content

Commit 347698f

Browse files
committed
fix: csv export without tmp file
1 parent 0eaa474 commit 347698f

File tree

4 files changed

+17
-58
lines changed

4 files changed

+17
-58
lines changed

app.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ def read_root():
4848

4949

5050
@app.get("/csv/metrics")
51-
async def metric_csv(
52-
background_tasks: BackgroundTasks, authorization: Optional[str] = None
53-
):
51+
async def metric_csv(authorization: Optional[str] = None):
5452
"""Quantity CSV"""
5553

5654
try:
@@ -63,4 +61,4 @@ async def metric_csv(
6361
except AssertionError:
6462
return PlainTextResponse("Authorization Failed", 403)
6563

66-
return await export_metric_csv(background_tasks)
64+
return await export_metric_csv()

export_csv/metric.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from model.enum import WikibaseType, WikibaseURLType
1818

1919

20-
async def export_metric_csv(background_tasks: BackgroundTasks) -> StreamingResponse:
20+
async def export_metric_csv() -> StreamingResponse:
2121
"""CSV with Requested Metrics"""
2222

2323
query = get_metrics_query()
@@ -26,7 +26,6 @@ async def export_metric_csv(background_tasks: BackgroundTasks) -> StreamingRespo
2626
query=query,
2727
export_filename="metrics",
2828
index_col="wikibase_id",
29-
background_tasks=background_tasks,
3029
)
3130

3231

export_csv/util.py

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"""Utilities"""
22

3-
import os
43
from typing import Optional
5-
import uuid
64
from fastapi import BackgroundTasks
75
from fastapi.responses import StreamingResponse
86
import pandas
@@ -25,14 +23,9 @@ async def read_sql_query(
2523
return df
2624

2725

28-
CHUNK_SIZE = 1024 * 1024
29-
EXPORT_DIRECTORY = "export/data"
30-
31-
3226
async def export_csv(
3327
query: Select,
3428
export_filename: str,
35-
background_tasks: BackgroundTasks,
3629
index_col: Optional[str] = None,
3730
):
3831
"""Export CSV"""
@@ -41,18 +34,8 @@ async def export_csv(
4134
if index_col == "wikibase_id":
4235
assert len(set(df.index)) == len(df), "Returned Multiple Rows per Wikibase"
4336

44-
os.makedirs(EXPORT_DIRECTORY, exist_ok=True)
45-
46-
filename = f"{EXPORT_DIRECTORY}/{uuid.uuid4()}.csv"
47-
df.to_csv(filename)
37+
csv = df.to_csv()
4838
del df
4939

50-
def iterfile():
51-
with open(filename, "rb") as f:
52-
while chunk := f.read(CHUNK_SIZE):
53-
yield chunk
54-
55-
background_tasks.add_task(os.remove, filename)
56-
5740
headers = {"Content-Disposition": f'attachment; filename="{export_filename}.csv"'}
58-
return StreamingResponse(iterfile(), headers=headers, media_type="text/csv")
41+
return StreamingResponse(csv, headers=headers, media_type="text/csv")

tests/test_export_csv/test_export_metrics_csv.py

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
11
"""Test Export Metrics CSV"""
22

3-
import os
43
import re
5-
from typing import Callable
64
import pytest
7-
from export_csv.metric import export_metric_csv
5+
from fastapi.testclient import TestClient
6+
from app import app
87

98

10-
class MockBackgroundTasks:
11-
"""Mock BackgroundTasks"""
12-
13-
task_list = []
14-
15-
# pylint: disable-next=unused-argument
16-
def add_task(self, func: Callable, *args):
17-
"""
18-
Add Task
19-
20-
really add filename to list
21-
"""
22-
23-
self.task_list.append(args[0])
24-
259

2610
EXPECTED_HEADER_ROW = ",".join(
2711
[
@@ -46,7 +30,7 @@ def add_task(self, func: Callable, *args):
4630
"bot_change_user_count",
4731
"software_version_observation_date",
4832
"software_name",
49-
"version\n",
33+
"version",
5034
]
5135
)
5236
EXPECTED_PATTERN = re.compile(
@@ -76,7 +60,7 @@ def add_task(self, func: Callable, *args):
7660
# # Software
7761
r"(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d|)",
7862
r"(MediaWiki|)",
79-
r"(\d+\.\d+\.\d+|)\n",
63+
r"(\d+\.\d+\.\d+|)",
8064
]
8165
)
8266
)
@@ -94,19 +78,14 @@ def add_task(self, func: Callable, *args):
9478
async def test_export_metric_csv():
9579
"""Test Export Metric CSV"""
9680

97-
mock_background_tasks = MockBackgroundTasks()
98-
99-
result = await export_metric_csv(mock_background_tasks)
100-
assert len(mock_background_tasks.task_list) == 1
81+
client = TestClient(app)
82+
result = client.get("/csv/metrics?authorization=test-auth-token")
10183
assert result.status_code == 200
102-
assert result.media_type == "text/csv"
103-
# CANNOT FIGURE OUT HOW TO CHECK CONTENT OF RESPONSE
84+
content = result.content.decode("utf-8")
10485

105-
with open(mock_background_tasks.task_list[0], mode="r", encoding="utf-8") as file:
106-
returned_lines = file.readlines()
107-
assert returned_lines[0] == EXPECTED_HEADER_ROW
108-
for returned_line in returned_lines[1:]:
109-
assert EXPECTED_PATTERN.match(returned_line)
86+
lines = content.splitlines()
87+
assert len(lines) >= 2
88+
assert lines[0] == EXPECTED_HEADER_ROW
11089

111-
for file in mock_background_tasks.task_list:
112-
os.remove(file)
90+
for line in lines[1:]:
91+
assert EXPECTED_PATTERN.match(line)

0 commit comments

Comments
 (0)