Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions pcapkit/corekit/fields/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ def __init__(self, length: 'int | Callable[[dict[str, Any]], int]' = lambda _: -
item_type: 'Optional[FieldBase]' = None,
callback: 'Callable[[Self, dict[str, Any]], None]' = lambda *_: None) -> 'None':
#self._name = '<list>'
if not hasattr(self, '_name'):
self._name = f'<{type(self).__name__[:-5].lower()}>'

self._callback = callback
self._item_type = item_type

Expand Down
8 changes: 6 additions & 2 deletions pcapkit/corekit/fields/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,9 @@ def __init__(self, length: 'int | Callable[[dict[str, Any]], int]' = lambda _: -
default: '_TP | NoValueType | bytes' = NO_VALUE,
protocol: 'Optional[Type[_TP] | str]' = None,
callback: 'Callable[[Self, dict[str, Any]], None]' = lambda *_: None) -> 'None':
#self._name = '<payload>'
if not hasattr(self, '_name'):
self._name = f'<{type(self).__name__[:-5].lower()}>'

self._default = default # type: ignore[assignment]

# NOTE: Through the property rather than straight to ``_protocol``, so a
Expand Down Expand Up @@ -652,7 +654,9 @@ def __init__(self, length: 'int | Callable[[dict[str, Any]], int]' = lambda _: -
default: '_TS | NoValueType | bytes' = NO_VALUE,
packet: 'Optional[dict[str, Any]]' = None,
callback: 'Callable[[Self, dict[str, Any]], None]' = lambda *_: None) -> 'None':
#self._name = '<schema>'
if not hasattr(self, '_name'):
self._name = f'<{type(self).__name__[:-5].lower()}>'

self._callback = callback

if packet is None:
Expand Down
77 changes: 77 additions & 0 deletions tests/corekit/test_fields_collections_default_name_1491_unit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
"""Unnamed collection, payload and schema fields have a default name.

GitHub issue #1491: :meth:`ListField.__init__
<pcapkit.corekit.fields.collections.ListField.__init__>` set no ``_name``, so
``ListField().name`` raised :exc:`AttributeError` -- and so did every subclass
that reaches it through ``super().__init__``, :class:`OptionField` included,
whose ``unpack`` reads ``self.name``. :class:`PayloadField` and
:class:`SchemaField` had the same gap. Other fields default to
``<{class name less "Field", lower-cased}>``, as :class:`FieldBase` and
:class:`Field` do in :mod:`pcapkit.corekit.fields.field`.

Classes are imported inside each test, after
:func:`~tests._support.reimport_once_per_class`.

"""

import unittest

from tests._support import reimport_once_per_class


class TestListFieldDefaultName(unittest.TestCase):
"""Pin the default name of unnamed collection fields."""

def setUp(self) -> None:
reimport_once_per_class(self)

def test_list_field(self) -> None:
from pcapkit.corekit.fields.collections import ListField

self.assertEqual(ListField().name, '<list>')
self.assertEqual(repr(ListField()), '<ListField>')

def test_option_field_subclasses(self) -> None:
from pcapkit.corekit.fields.collections import OptionField
from pcapkit.protocols.schema.transport.sctp import ChunkListField, Parameter

for cls, name in ((OptionField, '<option>'), (ChunkListField, '<chunklist>')):
with self.subTest(cls=cls.__name__):
field = cls(base_schema=Parameter, type_name='type',
registry=Parameter.registry)
self.assertEqual(field.name, name)

def test_copy_keeps_default_name(self) -> None:
from pcapkit.corekit.fields.collections import ListField

self.assertEqual(ListField()({}).name, '<list>')

def test_schema_name_wins(self) -> None:
from pcapkit.protocols.schema.transport.sctp import INITChunk

self.assertEqual(INITChunk.__fields__['parameters'].name, 'parameters')


class TestMiscFieldDefaultName(unittest.TestCase):
"""Pin the default name of unnamed :mod:`~pcapkit.corekit.fields.misc` fields."""

def setUp(self) -> None:
reimport_once_per_class(self)

def test_payload_field(self) -> None:
from pcapkit.corekit.fields.misc import PayloadField

self.assertEqual(PayloadField().name, '<payload>')
self.assertEqual(PayloadField()({}).name, '<payload>')

def test_schema_field(self) -> None:
from pcapkit.corekit.fields.misc import SchemaField
from pcapkit.protocols.schema.transport.sctp import Parameter

self.assertEqual(SchemaField(schema=Parameter).name, '<schema>')
self.assertEqual(SchemaField(schema=Parameter)({}).name, '<schema>')


if __name__ == '__main__':
unittest.main()
Loading