| 1078 | |
| 1079 | |
| 1080 | class _BytesZipFile(_BufferedWriter): |
| 1081 | def __init__( |
| 1082 | self, |
| 1083 | file: FilePath | ReadBuffer[bytes] | WriteBuffer[bytes], |
| 1084 | mode: str, |
| 1085 | archive_name: str | None = None, |
| 1086 | **kwargs: Any, |
| 1087 | ) -> None: |
| 1088 | super().__init__() |
| 1089 | mode = mode.replace("b", "") |
| 1090 | self.archive_name = archive_name |
| 1091 | |
| 1092 | kwargs.setdefault("compression", zipfile.ZIP_DEFLATED) |
| 1093 | # error: No overload variant of "ZipFile" matches argument types |
| 1094 | # "str | PathLike[str] | ReadBuffer[bytes] | WriteBuffer[bytes]", |
| 1095 | # "str", "dict[str, Any]" |
| 1096 | # error: Incompatible types in assignment (expression has type "ZipFile", |
| 1097 | # base class "_BufferedWriter" defined the type as "BytesIO") |
| 1098 | self.buffer: zipfile.ZipFile = zipfile.ZipFile( # type: ignore[call-overload, assignment] |
| 1099 | file, mode, **kwargs |
| 1100 | ) |
| 1101 | |
| 1102 | def infer_filename(self) -> str | None: |
| 1103 | """ |
| 1104 | If an explicit archive_name is not given, we still want the file inside the zip |
| 1105 | file not to be named something.zip, because that causes confusion (GH39465). |
| 1106 | """ |
| 1107 | if isinstance(self.buffer.filename, (os.PathLike, str)): |
| 1108 | filename = Path(self.buffer.filename) |
| 1109 | if filename.suffix == ".zip": |
| 1110 | return filename.with_suffix("").name |
| 1111 | return filename.name |
| 1112 | return None |
| 1113 | |
| 1114 | def write_to_buffer(self) -> None: |
| 1115 | # ZipFile needs a non-empty string |
| 1116 | archive_name = self.archive_name or self.infer_filename() or "zip" |
| 1117 | self.buffer.writestr(archive_name, self.getvalue()) |
| 1118 | |
| 1119 | |
| 1120 | class _IOWrapper: |