Three ProtocolError messages in pcapkit/protocols/internet/ipv6_route.py interpolate {type} inside methods that have no type parameter, so the name resolves to the builtin type and the diagnostic always reads <class 'type'> instead of the routing type number.
The sites, on c28ffc287
pcapkit/protocols/internet/ipv6_route.py:462 raise ProtocolError(f'{self.alias} [TypeNo {type}]: invalid format')
pcapkit/protocols/internet/ipv6_route.py:506 raise ProtocolError(f'{self.alias}: [TypeNo {type}] invalid format')
pcapkit/protocols/internet/ipv6_route.py:546 raise ProtocolError(f'{self.alias}: [TypeNo {type}] invalid format')
Their enclosing signatures, none of which binds type:
def _read_data_type_src(self, schema: 'Schema_SourceRoute', *, header: 'Schema_IPv6_Route') -> 'Data_SourceRoute':
def _read_data_type_2(self, schema: 'Schema_Type2', *, header: 'Schema_IPv6_Route') -> 'Data_Type2':
def _read_data_type_rpl(self, schema: 'Schema_RPL', *, header: 'Schema_IPv6_Route') -> 'Data_RPL':
Observed output
Driving the two reachable cases through a round trip gives the messages verbatim:
ipv6-route-type/Source_Route CONSTRUCT "ProtocolError: IPv6-Route [TypeNo <class 'type'>]: invalid format"
ipv6-route-type/Type_2_Routing_Header CONSTRUCT "ProtocolError: IPv6-Route: [TypeNo <class 'type'>] invalid format"
<class 'type'> is the builtin's repr, which is what confirms the name is not shadowed by a parameter. Because the interpolation is legal Python, neither the type checker nor the linter flags it, and the message only reveals itself when one of these guards actually fires.
Why the read side differs from the make side
The read dispatch passes no type:
name = self._lookup_registry(self.__routing__, schema.type) # :204
...
ipv6_route = meth(schema.data, header=schema) # :211
whereas the make dispatch does — meth(type_val, data, dst=dst_val) at :275 — which is why the ten structurally identical {type} interpolations in pcapkit/protocols/internet/mh.py (:3193, :3194, :3197, :3198, :3301, :3329, :3443, :3555, :3703, :3747) are all correct: every one of them sits in a _make_opt_* method whose first parameter really is type: 'Enum_Option'. I swept every {type} interpolation in pcapkit/ and these three are the only broken ones.
Fix
The routing type is already in scope on the read side as header.type (the same value :204 looks the code up by), so no signature change is needed:
raise ProtocolError(f'{self.alias} [TypeNo {header.type}]: invalid format')
While there: :462 puts the colon after the bracket (IPv6-Route [TypeNo x]: invalid format) while :506 and :546 put it before (IPv6-Route: [TypeNo x] invalid format). The mh.py convention is colon-before, so :462 is the outlier.
Found while reviewing #440, whose round-trip table records these two cases as expected failures; the messages are what that table matches on. Not folded into #440, which is test-only.
Three
ProtocolErrormessages inpcapkit/protocols/internet/ipv6_route.pyinterpolate{type}inside methods that have notypeparameter, so the name resolves to the builtintypeand the diagnostic always reads<class 'type'>instead of the routing type number.The sites, on
c28ffc287Their enclosing signatures, none of which binds
type:Observed output
Driving the two reachable cases through a round trip gives the messages verbatim:
<class 'type'>is the builtin'srepr, which is what confirms the name is not shadowed by a parameter. Because the interpolation is legal Python, neither the type checker nor the linter flags it, and the message only reveals itself when one of these guards actually fires.Why the read side differs from the make side
The read dispatch passes no type:
whereas the make dispatch does —
meth(type_val, data, dst=dst_val)at :275 — which is why the ten structurally identical{type}interpolations inpcapkit/protocols/internet/mh.py(:3193, :3194, :3197, :3198, :3301, :3329, :3443, :3555, :3703, :3747) are all correct: every one of them sits in a_make_opt_*method whose first parameter really istype: 'Enum_Option'. I swept every{type}interpolation inpcapkit/and these three are the only broken ones.Fix
The routing type is already in scope on the read side as
header.type(the same value:204looks the code up by), so no signature change is needed:While there:
:462puts the colon after the bracket (IPv6-Route [TypeNo x]: invalid format) while:506and:546put it before (IPv6-Route: [TypeNo x] invalid format). Themh.pyconvention is colon-before, so:462is the outlier.Found while reviewing #440, whose round-trip table records these two cases as expected failures; the messages are what that table matches on. Not folded into #440, which is test-only.