|
43 | 43 | Union, |
44 | 44 | cast, |
45 | 45 | overload, |
46 | | - runtime_checkable, |
47 | 46 | ) |
48 | 47 | from urllib.error import HTTPError |
49 | 48 | from urllib.parse import ParseResult, urlparse, urlunparse |
@@ -141,14 +140,12 @@ class ReadableBinStream(Protocol): |
141 | 140 | def read(self, size: int = -1) -> bytes: ... |
142 | 141 |
|
143 | 142 |
|
144 | | -@runtime_checkable |
145 | 143 | class WriteSeekableBinStream(Protocol): |
146 | 144 | def write(self, b: bytes) -> int: ... |
147 | 145 | def seek(self, offset: int, whence: int = 0) -> int: ... |
148 | 146 | def tell(self) -> int: ... |
149 | 147 |
|
150 | 148 |
|
151 | | -@runtime_checkable |
152 | 149 | class ReadSeekableBinStream(Protocol): |
153 | 150 | def seek(self, offset: int, whence: int = 0) -> int: ... |
154 | 151 | def tell(self) -> int: ... |
@@ -2220,16 +2217,6 @@ def _save_to_named_tmp_file( |
2220 | 2217 | return tmp_file_obj |
2221 | 2218 |
|
2222 | 2219 |
|
2223 | | -# Minor hack. Relies on Protocols being ABC subclasses. |
2224 | | -# They are currently ABCs anyway, so why not use that |
2225 | | -# for something useful like this? |
2226 | | -# |
2227 | | -# tempfile.NamedTemporaryFile is a dynamic wrapper |
2228 | | -# https://github.com/python/cpython/blob/2dd91d2b92a6c74d78cd3385ede328190cd8eaa9/Lib/tempfile.py#L510 |
2229 | | -# so normal (naive) isinstance checks of tempfile.NamedTemporaryFiles |
2230 | | -# against @runtime_checkable Protocols are not possible. |
2231 | | -ReadSeekableBinStream.register(tempfile._TemporaryFileWrapper) |
2232 | | - |
2233 | 2220 | HTML_SIGNATURES_UC = ( |
2234 | 2221 | b"<!DOCTYPE", |
2235 | 2222 | b"<HTML", |
@@ -2398,7 +2385,6 @@ def close(self) -> None: |
2398 | 2385 | self.exit_stack.close() |
2399 | 2386 |
|
2400 | 2387 |
|
2401 | | -# TODO: bound to @runtime_checkable Protocols |
2402 | 2388 | FileProtoT = TypeVar("FileProtoT") |
2403 | 2389 |
|
2404 | 2390 |
|
@@ -2479,9 +2465,17 @@ def _ensure_file_obj( |
2479 | 2465 | exit_stack.enter_context(fp) |
2480 | 2466 | return cast(FileProtoT, fp) |
2481 | 2467 |
|
2482 | | - if isinstance(f, FileProto): |
| 2468 | + # Ugly, but we need to apply this to TemporaryFiles, and tempfile |
| 2469 | + # is a platform-inconsistent stick mess of dynamic wrappers, |
| 2470 | + # leading to weird Python 3.14 specific bug in run_benchmarks.py |
| 2471 | + # on Windows |
| 2472 | + attrs = FileProto.__protocol_attrs__ # type: ignore[attr-defined] |
| 2473 | + |
| 2474 | + if all(hasattr(f, attr) for attr in attrs): |
2483 | 2475 | return f |
2484 | | - raise ExceptionClass(f"Unsupported file-like object: {f}") |
| 2476 | + raise ExceptionClass( |
| 2477 | + f"Unsupported file-like object: {f}. Must satisfy: {FileProto}" |
| 2478 | + ) |
2485 | 2479 |
|
2486 | 2480 |
|
2487 | 2481 | class DbfReader(_FileChecker[ReadSeekableBinStream]): |
|
0 commit comments