Lock-free version of ZipFile that reads from a WebFile, allowing for concurrent reads.
| 20 | |
| 21 | |
| 22 | class WebZipFile(ZipFile): |
| 23 | "Lock-free version of ZipFile that reads from a WebFile, allowing for concurrent reads." |
| 24 | def __init__(self, url: str, session: Optional[Session] = None, headers: Optional[Dict[str, str]] = None): |
| 25 | """Open the ZIP file with mode read 'r', write 'w', exclusive create 'x', |
| 26 | or append 'a'.""" |
| 27 | webf = WebFile(url, session=session, headers=headers) |
| 28 | super().__init__(webf, mode='r') |
| 29 | |
| 30 | def open(self, name, mode="r", pwd=None, *, force_zip64=False): |
| 31 | """Return file-like object for 'name'. |
| 32 | |
| 33 | name is a string for the file name within the ZIP file, or a ZipInfo |
| 34 | object. |
| 35 | |
| 36 | mode should be 'r' to read a file already in the ZIP file, or 'w' to |
| 37 | write to a file newly added to the archive. |
| 38 | |
| 39 | pwd is the password to decrypt files (only used for reading). |
| 40 | |
| 41 | When writing, if the file size is not known in advance but may exceed |
| 42 | 2 GiB, pass force_zip64 to use the ZIP64 format, which can handle large |
| 43 | files. If the size is known in advance, it is best to pass a ZipInfo |
| 44 | instance for name, with zinfo.file_size set. |
| 45 | """ |
| 46 | if mode not in {"r", "w"}: |
| 47 | raise ValueError('open() requires mode "r" or "w"') |
| 48 | if pwd and (mode == "w"): |
| 49 | raise ValueError("pwd is only supported for reading files") |
| 50 | if not self.fp: |
| 51 | raise ValueError( |
| 52 | "Attempt to use ZIP archive that was already closed") |
| 53 | |
| 54 | assert mode == "r", "Only read mode is supported for now" |
| 55 | |
| 56 | # Make sure we have an info object |
| 57 | if isinstance(name, ZipInfo): |
| 58 | # 'name' is already an info object |
| 59 | zinfo = name |
| 60 | elif mode == 'w': |
| 61 | zinfo = ZipInfo(name) |
| 62 | zinfo.compress_type = self.compression |
| 63 | zinfo._compresslevel = self.compresslevel |
| 64 | else: |
| 65 | # Get info object for name |
| 66 | zinfo = self.getinfo(name) |
| 67 | |
| 68 | if mode == 'w': |
| 69 | return self._open_to_write(zinfo, force_zip64=force_zip64) |
| 70 | |
| 71 | if self._writing: |
| 72 | raise ValueError("Can't read from the ZIP file while there " |
| 73 | "is an open writing handle on it. " |
| 74 | "Close the writing handle before trying to read.") |
| 75 | |
| 76 | # Open for reading: |
| 77 | self._fileRefCnt += 1 |
| 78 | zef_file = _SharedWebFile(self.fp, zinfo.header_offset) |
| 79 |
nothing calls this directly
no outgoing calls
no test coverage detected