Schema.unpack is documented and typed as unpack(cls, data, length=None, packet=None), with both trailing parameters optional. The @prepare decorator that wraps it reads its arguments by position out of *args and never looks at **kwargs, so in practice exactly one call shape works: three positional arguments.
Measured on f50436a8a
unpack(data) IndexError: tuple index out of range
unpack(data, length) IndexError: tuple index out of range
unpack(data, length, packet) OK -> a=7 b=8
unpack(data, length=2) IndexError: tuple index out of range
unpack(data, length=2, packet={}) IndexError: tuple index out of range
against a two-field schema and wire = b'\x07\x08'.
Mechanism
pcapkit/utilities/decorators.py:207-210:
def unpack(*args: 'P.args', **kwargs: 'P.kwargs') -> 'R_prepare':
cls = cast('Type[R_prepare]', args[0])
data = cast('bytes | IO[bytes]', args[1])
length = cast('Optional[int]', args[2])
packet = cast('Optional[dict[str, Any]]', args[3])
Four unconditional subscripts, and kwargs is accepted but never read. The body immediately below goes to some trouble to handle length is None and packet is None, so the defaults were clearly intended to be reachable — they just cannot be supplied. A keyword call fails for the same reason a short positional call does: the value lands in kwargs, where nothing looks for it.
There is already a casualty in the tree
pcapkit/corekit/fields/misc.py:539, in SchemaField.__init__:
if isinstance(default, bytes):
default = cast('_TS', schema.unpack(default)) # type: ignore[call-arg,misc]
One argument, so this raises. Which makes SchemaField(schema=..., default=b'...') unusable:
SchemaField(schema=Inner, default=b'\x01\x02')
File "pcapkit/corekit/fields/misc.py", line 539, in __init__
default = cast('_TS', schema.unpack(default))
File "pcapkit/utilities/decorators.py", line 209, in unpack
length = cast('Optional[int]', args[2])
IndexError: tuple index out of range
default is a documented, typed constructor argument of SchemaField, and passing bytes to it — the one type that branch exists to handle — cannot succeed. Note the # type: ignore[call-arg,misc]: mypy already flagged this call as wrong and the diagnosis was suppressed rather than followed.
Nothing else in the tree is affected, because every other call site passes three positional arguments (corekit/fields/collections.py:420 is schema.unpack(file, length, packet)). That is why this has stayed hidden: the internal callers all happen to use the single shape that works.
Fix
Read the arguments the way an ordinary wrapper would, so that the documented signature is the real one:
cls, data = args[0], args[1]
length = args[2] if len(args) > 2 else kwargs.pop('length', None)
packet = args[3] if len(args) > 3 else kwargs.pop('packet', None)
or bind against the wrapped function's signature with inspect.signature(...).bind. Either way misc.py:539 then works as written and its type: ignore can go.
Found while investigating the CGA Parameters failure recorded in #437, which is a different fault in the same area — see the two companion issues. This one is independent of that story and of the mobility header entirely.
Schema.unpackis documented and typed asunpack(cls, data, length=None, packet=None), with both trailing parameters optional. The@preparedecorator that wraps it reads its arguments by position out of*argsand never looks at**kwargs, so in practice exactly one call shape works: three positional arguments.Measured on
f50436a8aagainst a two-field schema and
wire = b'\x07\x08'.Mechanism
pcapkit/utilities/decorators.py:207-210:Four unconditional subscripts, and
kwargsis accepted but never read. The body immediately below goes to some trouble to handlelength is Noneandpacket is None, so the defaults were clearly intended to be reachable — they just cannot be supplied. A keyword call fails for the same reason a short positional call does: the value lands inkwargs, where nothing looks for it.There is already a casualty in the tree
pcapkit/corekit/fields/misc.py:539, inSchemaField.__init__:One argument, so this raises. Which makes
SchemaField(schema=..., default=b'...')unusable:defaultis a documented, typed constructor argument ofSchemaField, and passingbytesto it — the one type that branch exists to handle — cannot succeed. Note the# type: ignore[call-arg,misc]: mypy already flagged this call as wrong and the diagnosis was suppressed rather than followed.Nothing else in the tree is affected, because every other call site passes three positional arguments (
corekit/fields/collections.py:420isschema.unpack(file, length, packet)). That is why this has stayed hidden: the internal callers all happen to use the single shape that works.Fix
Read the arguments the way an ordinary wrapper would, so that the documented signature is the real one:
or bind against the wrapped function's signature with
inspect.signature(...).bind. Either waymisc.py:539then works as written and itstype: ignorecan go.Found while investigating the CGA Parameters failure recorded in #437, which is a different fault in the same area — see the two companion issues. This one is independent of that story and of the mobility header entirely.