Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Refactor zipfile._strip_extra to use higher level abstractions for ex…
…tras instead of a heavy-state loop.
  • Loading branch information
jaraco committed Feb 20, 2023
commit de2802b1ff2e91a9c52c6d43039b3bd96f63d713
59 changes: 37 additions & 22 deletions Lib/zipfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,28 +188,43 @@ class LargeZipFile(Exception):

_DD_SIGNATURE = 0x08074b50

_EXTRA_FIELD_STRUCT = struct.Struct('<HH')

def _strip_extra(extra, xids):
# Remove Extra Fields with specified IDs.
unpack = _EXTRA_FIELD_STRUCT.unpack
modified = False
buffer = []
start = i = 0
while i + 4 <= len(extra):
xid, xlen = unpack(extra[i : i + 4])
j = i + 4 + xlen
if xid in xids:
if i != start:
buffer.append(extra[start : i])
start = j
modified = True
i = j
if not modified:
return extra
if start != len(extra):
buffer.append(extra[start:])
return b''.join(buffer)

class _Extra(bytes):
FIELD_STRUCT = struct.Struct('<HH')

def __new__(cls, val, id=None):
return super().__new__(cls, val)

def __init__(self, val, id=None):
self.id = id

@classmethod
def read_one(cls, raw):
try:
xid, xlen = cls.FIELD_STRUCT.unpack(raw[:4])
except struct.error:
xid = None
xlen = 0
return cls(raw[:4+xlen], xid), raw[4+xlen:]
Comment thread
jaraco marked this conversation as resolved.

@classmethod
def split(cls, data):
while data:
extra, data = _Extra.read_one(data)
yield extra

@classmethod
def strip(cls, data, xids):
"""Remove Extra fields with specified IDs."""
return b''.join(
ex
for ex in cls.split(data)
if ex.id not in xids
)


_strip_extra = _Extra.strip


def _check_zipfile(fp):
try:
Expand Down