|
4 | 4 | import json |
5 | 5 | import logging |
6 | 6 | import os |
| 7 | +import platform |
7 | 8 | import random |
8 | 9 | import re |
9 | 10 | import time |
10 | 11 | from dataclasses import dataclass |
11 | 12 | from datetime import datetime, timedelta, timezone |
12 | 13 | from enum import Enum |
13 | | -from tempfile import NamedTemporaryFile, mkstemp |
| 14 | +from tempfile import NamedTemporaryFile |
14 | 15 | from threading import Lock |
15 | 16 | from typing import Any, Callable, List, Optional, Type, Union |
16 | 17 | from urllib.parse import parse_qs, urlparse |
@@ -199,6 +200,8 @@ def to_string(test_case: "FilesApiDownloadTestCase") -> str: |
199 | 200 | return test_case.name |
200 | 201 |
|
201 | 202 | def run(self, config: Config, monkeypatch) -> None: |
| 203 | + if self.use_parallel and platform.system() == "Windows": |
| 204 | + pytest.skip("Skipping parallel download tests on Windows") |
202 | 205 | config = config.copy() |
203 | 206 | config.enable_experimental_files_api_client = self.enable_new_client |
204 | 207 | config.files_ext_client_download_max_total_recovers = self.max_recovers_total |
@@ -935,6 +938,9 @@ def processor() -> list: |
935 | 938 | raise RuntimeError("Unexpected request " + str(request)) |
936 | 939 |
|
937 | 940 | def run_one_case(self, config: Config, monkeypatch, download_mode: DownloadMode, use_parallel: bool) -> None: |
| 941 | + if use_parallel and platform.system() == "Windows": |
| 942 | + logger.debug("Parallel download is not supported on Windows. Falling back to sequential download.") |
| 943 | + return |
938 | 944 | config = config.copy() |
939 | 945 | config.enable_experimental_files_api_client = True |
940 | 946 | config.enable_presigned_download_api = True |
@@ -1149,7 +1155,8 @@ def save_part(self, part_number: int, part_content: bytes, etag: str) -> None: |
1149 | 1155 | # part might already have been uploaded |
1150 | 1156 | with self.global_lock: |
1151 | 1157 | if part_number not in self.uploaded_parts: |
1152 | | - fd, part_file = mkstemp() |
| 1158 | + with NamedTemporaryFile(mode="wb", delete=False) as f: |
| 1159 | + part_file = f.name |
1153 | 1160 | self.uploaded_parts[part_number] = [part_file, etag, Lock()] |
1154 | 1161 | existing_part = self.uploaded_parts[part_number] |
1155 | 1162 | with existing_part[2]: # lock per part |
@@ -1275,9 +1282,9 @@ def clear_state(self) -> None: |
1275 | 1282 | def get_upload_file(self, content: bytes, source_type: "UploadSourceType") -> Union[str, io.BytesIO]: |
1276 | 1283 | """Returns a file or stream to upload based on the source type.""" |
1277 | 1284 | if source_type == UploadSourceType.FILE: |
1278 | | - fd, file_path = mkstemp() |
1279 | | - with open(fd, "wb") as f: |
| 1285 | + with NamedTemporaryFile(mode="wb", delete=False) as f: |
1280 | 1286 | f.write(content) |
| 1287 | + file_path = f.name |
1281 | 1288 | self.created_temp_files.append(file_path) |
1282 | 1289 | return file_path |
1283 | 1290 | elif source_type == UploadSourceType.STREAM: |
@@ -2211,8 +2218,8 @@ def save_part(self, start_offset: int, end_offset_incl: int, part_content: bytes |
2211 | 2218 | if unconfirmed_delta > 0: |
2212 | 2219 | part_content = part_content[:-unconfirmed_delta] |
2213 | 2220 |
|
2214 | | - fd, part_file = mkstemp() |
2215 | | - with open(fd, "wb") as f: |
| 2221 | + with NamedTemporaryFile(mode="wb", delete=False) as f: |
| 2222 | + part_file = f.name |
2216 | 2223 | f.write(part_content) |
2217 | 2224 |
|
2218 | 2225 | self.uploaded_parts.append(part_file) |
|
0 commit comments