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
12 changes: 6 additions & 6 deletions pcapkit/const/pcapng/option_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,13 @@ def _unregistered_member(cls, value: 'int', name: 'str') -> 'OptionType':
:meth:`~pcapkit.corekit.enum.EnumRegistry._unregistered_member` calls
:class:`str`'s ``__new__`` directly on the raw ``value``, but
OptionType stores a *formatted* string (``'{name} [{value}]'``) as
its own :attr:`~aenum.Enum._value_`, not ``value`` itself, so that
its own ``aenum.Enum._value_``, not ``value`` itself, so that
approach would build a member whose value looks nothing like this
registry's real members.

Deliberately does **not** add to :attr:`__members_ns__` either --
that dict is this registry's own second lookup table, alongside
:attr:`~aenum.Enum._value2member_map_`, and growing it would defeat
``aenum.Enum._value2member_map_``, and growing it would defeat
the whole point of an *unregistered* member exactly as growing
``_value2member_map_`` would.

Expand Down Expand Up @@ -246,9 +246,9 @@ def register(cls, value: 'int', name: 'str') -> 'OptionType':
files the member under the namespace that name's prefix gives
(``if_rtaudit`` goes under ``if``), so ``name`` is passed through
to it as well as used as the member's attribute name.
* :attr:`~aenum.Enum._value_` is the formatted ``'{name} [{value}]'``
* ``aenum.Enum._value_`` is the formatted ``'{name} [{value}]'``
string, so the base's duplicate check against
:attr:`~aenum.Enum._value2member_map_` can never match an
``aenum.Enum._value2member_map_`` can never match an
:class:`int` code. The check runs against :attr:`__members_ns__`
instead, the table :meth:`get` resolves codes through: both
``name``'s own namespace and ``opt``, whose codes are common to
Expand Down Expand Up @@ -292,7 +292,7 @@ def register_alias(cls, value: 'int', name: 'str') -> 'OptionType':

Overrides :meth:`~pcapkit.corekit.enum.EnumRegistry.register_alias`
for the same reason as :meth:`register`: the base looks the
:class:`int` code up in :attr:`~aenum.Enum._value2member_map_`, whose
:class:`int` code up in ``aenum.Enum._value2member_map_``, whose
keys are the formatted ``'{name} [{value}]'`` strings, so it could
never find one.

Expand Down Expand Up @@ -324,7 +324,7 @@ def register_alias(cls, value: 'int', name: 'str') -> 'OptionType':
raise ValueError(f'{value!r} is not a registered {cls.__name__} in namespace '
f'{namespace!r} or opt; use {cls.__name__}.register() to mint one')

# NOTE: :func:`~aenum.extend_enum` builds a throwaway member through
# NOTE: ``aenum.extend_enum`` builds a throwaway member through
# :meth:`__new__` to learn its value, and :meth:`__new__` files that
# throwaway in :attr:`__members_ns__` over ``member``. The alias
# resolves to ``member``, so ``member`` is put back.
Expand Down
12 changes: 6 additions & 6 deletions pcapkit/const/reg/apptype/apptype.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco
# signature admits -- an unrecognised :class:`int` still reaches the
# caller as a :exc:`ValueError`, now the base's own
# :exc:`~pcapkit.utilities.exceptions.EnumValueError` since GitHub issue
# #923 rather than :mod:`aenum`'s bare one. It is not compatible for
# #923 rather than ``aenum``'s bare one. It is not compatible for
# keys outside it: ``None``, a :class:`float` and an unhashable key
# used to raise :exc:`AttributeError` from the ``key.lower()`` this
# branch no longer reaches, and now raise :exc:`ValueError` (or, for a
Expand All @@ -197,12 +197,12 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco
return super().get(key, default)

# NOTE: ``_missing_`` used to range-check ``value`` and then defer to
# :mod:`aenum`'s own ``Flag._missing_``, which is what composed an
# ``aenum``'s own ``Flag._missing_``, which is what composed an
# unrecognised bit combination into a pseudo-member -- ``TransportProtocol(3)``
# returning ``tcp|udp`` -- GitHub issue #647's guard against that composing
# *anything*, including values no member declares. GitHub issue #808 removed
# the ``IntFlag`` base once nothing built a composite, and with it the only
# reason this method existed: a plain :class:`~aenum.IntEnum` already raises
# reason this method existed: a plain ``aenum.IntEnum`` already raises
# ``ValueError`` for a value no member declares, with no ``_missing_`` of
# its own needed to get there, so declaring one here would only be
# reproducing what the base class already does.
Expand All @@ -219,7 +219,7 @@ class AppType(EnumRegistry, StrEnum):
:class:`~pcapkit.const.reg.apptype.udp.UDP`,
:class:`~pcapkit.const.reg.apptype.sctp.SCTP` or
:class:`~pcapkit.const.reg.apptype.dccp.DCCP`. Being memberless is also what
makes it subclassable at all, since :mod:`aenum` refuses to extend an
makes it subclassable at all, since |aenum|_ refuses to extend an
enumeration that already has members.

Note:
Expand Down Expand Up @@ -2660,7 +2660,7 @@ def get(cls, key: 'int', *, # type: ignore[override] # pylint: disable=argument
if member.svc == canonical:
return member
# NOTE: IANA's oldest row, for a port whose collision postdates
# :data:`__canonical__` -- including one :func:`~aenum.extend_enum`
# :data:`__canonical__` -- including one ``aenum.extend_enum``
# created, which must not displace what the registry already
# answered with.
return matched[0]
Expand Down Expand Up @@ -2861,7 +2861,7 @@ def register_alias(cls, port: 'int', name: 'str') -> 'AppType': # pylint: disab
IANA itself never registered it there.

No new storage: the new member simply joins :data:`__registry__` at
``port``, through the same :func:`~aenum.extend_enum` call
``port``, through the same ``aenum.extend_enum`` call
:meth:`register` uses to mint the first one. It is then reachable
through :attr:`aliases` on every other member already on ``port``, and
vice versa, with nothing further to keep in sync.
Expand Down
12 changes: 6 additions & 6 deletions pcapkit/vendor/pcapng/option_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ def _unregistered_member(cls, value: 'int', name: 'str') -> '{NAME}':
:meth:`~pcapkit.corekit.enum.EnumRegistry._unregistered_member` calls
:class:`str`'s ``__new__`` directly on the raw ``value``, but
{NAME} stores a *formatted* string (``'{{name}} [{{value}}]'``) as
its own :attr:`~aenum.Enum._value_`, not ``value`` itself, so that
its own ``aenum.Enum._value_``, not ``value`` itself, so that
approach would build a member whose value looks nothing like this
registry's real members.

Deliberately does **not** add to :attr:`__members_ns__` either --
that dict is this registry's own second lookup table, alongside
:attr:`~aenum.Enum._value2member_map_`, and growing it would defeat
``aenum.Enum._value2member_map_``, and growing it would defeat
the whole point of an *unregistered* member exactly as growing
``_value2member_map_`` would.

Expand Down Expand Up @@ -156,9 +156,9 @@ def register(cls, value: 'int', name: 'str') -> '{NAME}':
files the member under the namespace that name's prefix gives
(``if_rtaudit`` goes under ``if``), so ``name`` is passed through
to it as well as used as the member's attribute name.
* :attr:`~aenum.Enum._value_` is the formatted ``'{{name}} [{{value}}]'``
* ``aenum.Enum._value_`` is the formatted ``'{{name}} [{{value}}]'``
string, so the base's duplicate check against
:attr:`~aenum.Enum._value2member_map_` can never match an
``aenum.Enum._value2member_map_`` can never match an
:class:`int` code. The check runs against :attr:`__members_ns__`
instead, the table :meth:`get` resolves codes through: both
``name``'s own namespace and ``opt``, whose codes are common to
Expand Down Expand Up @@ -202,7 +202,7 @@ def register_alias(cls, value: 'int', name: 'str') -> '{NAME}':

Overrides :meth:`~pcapkit.corekit.enum.EnumRegistry.register_alias`
for the same reason as :meth:`register`: the base looks the
:class:`int` code up in :attr:`~aenum.Enum._value2member_map_`, whose
:class:`int` code up in ``aenum.Enum._value2member_map_``, whose
keys are the formatted ``'{{name}} [{{value}}]'`` strings, so it could
never find one.

Expand Down Expand Up @@ -234,7 +234,7 @@ def register_alias(cls, value: 'int', name: 'str') -> '{NAME}':
raise ValueError(f'{{value!r}} is not a registered {{cls.__name__}} in namespace '
f'{{namespace!r}} or opt; use {{cls.__name__}}.register() to mint one')

# NOTE: :func:`~aenum.extend_enum` builds a throwaway member through
# NOTE: ``aenum.extend_enum`` builds a throwaway member through
# :meth:`__new__` to learn its value, and :meth:`__new__` files that
# throwaway in :attr:`__members_ns__` over ``member``. The alias
# resolves to ``member``, so ``member`` is put back.
Expand Down
12 changes: 6 additions & 6 deletions pcapkit/vendor/reg/apptype/apptype.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco
# signature admits -- an unrecognised :class:`int` still reaches the
# caller as a :exc:`ValueError`, now the base's own
# :exc:`~pcapkit.utilities.exceptions.EnumValueError` since GitHub issue
# #923 rather than :mod:`aenum`'s bare one. It is not compatible for
# #923 rather than ``aenum``'s bare one. It is not compatible for
# keys outside it: ``None``, a :class:`float` and an unhashable key
# used to raise :exc:`AttributeError` from the ``key.lower()`` this
# branch no longer reaches, and now raise :exc:`ValueError` (or, for a
Expand All @@ -289,12 +289,12 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco
return super().get(key, default)

# NOTE: ``_missing_`` used to range-check ``value`` and then defer to
# :mod:`aenum`'s own ``Flag._missing_``, which is what composed an
# ``aenum``'s own ``Flag._missing_``, which is what composed an
# unrecognised bit combination into a pseudo-member -- ``TransportProtocol(3)``
# returning ``tcp|udp`` -- GitHub issue #647's guard against that composing
# *anything*, including values no member declares. GitHub issue #808 removed
# the ``IntFlag`` base once nothing built a composite, and with it the only
# reason this method existed: a plain :class:`~aenum.IntEnum` already raises
# reason this method existed: a plain ``aenum.IntEnum`` already raises
# ``ValueError`` for a value no member declares, with no ``_missing_`` of
# its own needed to get there, so declaring one here would only be
# reproducing what the base class already does.
Expand All @@ -311,7 +311,7 @@ class {NAME}(EnumRegistry, StrEnum):
:class:`~pcapkit.const.reg.apptype.udp.UDP`,
:class:`~pcapkit.const.reg.apptype.sctp.SCTP` or
:class:`~pcapkit.const.reg.apptype.dccp.DCCP`. Being memberless is also what
makes it subclassable at all, since :mod:`aenum` refuses to extend an
makes it subclassable at all, since |aenum|_ refuses to extend an
enumeration that already has members.

Note:
Expand Down Expand Up @@ -614,7 +614,7 @@ def get(cls, key: 'int', *, # type: ignore[override] # pylint: disable=argument
if member.svc == canonical:
return member
# NOTE: IANA's oldest row, for a port whose collision postdates
# :data:`__canonical__` -- including one :func:`~aenum.extend_enum`
# :data:`__canonical__` -- including one ``aenum.extend_enum``
# created, which must not displace what the registry already
# answered with.
return matched[0]
Expand Down Expand Up @@ -815,7 +815,7 @@ def register_alias(cls, port: 'int', name: 'str') -> '{NAME}': # pylint: disabl
IANA itself never registered it there.

No new storage: the new member simply joins :data:`__registry__` at
``port``, through the same :func:`~aenum.extend_enum` call
``port``, through the same ``aenum.extend_enum`` call
:meth:`register` uses to mint the first one. It is then reachable
through :attr:`aliases` on every other member already on ``port``, and
vice versa, with nothing further to keep in sync.
Expand Down
14 changes: 3 additions & 11 deletions tests/project/test_docs_epilog_links_1936_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,6 @@
#: it, so no one project page is its target, and it stays a literal.
LINKED = ('aenum', 'cryptography', 'dpkt', 'emoji', 'pcapfile', 'pyshark')

#: Paths, relative to :data:`ROOT`, whose literals the scan does not read: the
#: generated constants and the vendor templates that generate them.
EXCLUDED = (
'pcapkit/vendor/pcapng/option_type.py',
'pcapkit/vendor/reg/apptype/apptype.py',
'pcapkit/const/',
)

#: A list of literals that names engines, adapters or toolkits.
ENGINE_LIST = re.compile(r'``\w+``(?:,\s+``\w+``)*(?:,?\s+(?:and|or)\s+``\w+``)?'
r'\s+(?:engines?|toolkits?|adapters?)\b')
Expand Down Expand Up @@ -162,7 +154,9 @@ def test_the_scan_reads_the_sources_it_claims_to(self) -> 'None':
'docs/source/index.rst',
'pcapkit/corekit/enum.py',
'pcapkit/foundation/engines/pypcapfile.py',
'pcapkit/toolkit/pyshark.py'):
'pcapkit/toolkit/pyshark.py',
'pcapkit/vendor/reg/apptype/apptype.py',
'pcapkit/const/reg/apptype/apptype.py'):
self.assertIn(expected, names)
self.assertFalse(any(name.startswith('docs/source/changelog/') for name in names))

Expand All @@ -179,8 +173,6 @@ def test_no_bare_literal_of_a_linked_package(self) -> 'None':
offenders = []
for path in _sources():
rel = _rel(path)
if any(rel == ex or rel.startswith(ex) for ex in EXCLUDED):
continue
text = _rendered(path)
spans = [m.span() for m in ENGINE_LIST.finditer(text)]
spans += [m.span() for m in TABLE_CELL.finditer(text)]
Expand Down
40 changes: 13 additions & 27 deletions tests/project/test_docs_unresolvable_roles_1919_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@
(PyPCAP and pcap-ct), ``pcapfile`` (PyPCAPFile) and ``emoji`` publish no
``objects.inv`` with ``py:`` objects in it, so no role naming them can resolve.
``AenumRoleExclusionTests`` in :file:`test_conventions_doc_claims.py` checks
the conventions pages; this class checks every hand-written source under
:file:`docs/` and :file:`pcapkit/`.
the conventions pages; this class checks every source under :file:`docs/`
and :file:`pcapkit/`.
* :class:`DeadTargetTests` -- targets in a package that has an inventory, but
absent from that inventory because the role, the path or the name is wrong
(#1919). Each is pinned in the form that fails to resolve.
* :class:`DocumentedEntryTests` -- the names #1919 decided are contract, which
have an entry rather than a demoted role.

Scoped to hand-written sources. The class formatter in :file:`docs/source/conf.py`
covers the generated half of #1920 by writing a literal for a package outside
Scoped to source files. The class formatter in :file:`docs/source/conf.py`
covers the build-time half of #1920 by writing a literal for a package outside
``intersphinx_mapping``; its output exists only at build time, so this scan reads
the file's own source like any other. ``pcapkit/const/`` and the vendor
templates that generate it are excluded, and are handled separately; the rest of
``pcapkit/vendor/`` is scanned.
the file's own source like any other. The generated modules under
``pcapkit/const/`` are scanned along with the ``pcapkit/vendor/`` templates
that generate them, so a role a template writes fails in both.

"""

Expand All @@ -36,14 +36,6 @@

ROOT = pathlib.Path(__file__).resolve().parents[2]

#: Paths, relative to :data:`ROOT`, that the scan does not read -- see the module
#: docstring for why each is out of scope.
EXCLUDED = (
'pcapkit/vendor/pcapng/option_type.py',
'pcapkit/vendor/reg/apptype/apptype.py',
'pcapkit/const/',
)

#: Top-level packages with no ``py:`` objects in any published inventory, per the
#: note beside ``intersphinx_mapping`` in :file:`docs/source/conf.py`.
INVENTORYLESS = frozenset({'aenum', 'pyshark', 'pcap', 'pcapfile', 'emoji'})
Expand All @@ -55,16 +47,9 @@


def _sources() -> 'list[pathlib.Path]':
"""Every hand-written ``.rst`` under :file:`docs/` and ``.py`` under :file:`pcapkit/`."""
paths = sorted((ROOT / 'docs').rglob('*.rst')) + sorted((ROOT / 'docs').rglob('*.py')) \
"""Every ``.rst`` and ``.py`` under :file:`docs/` and ``.py`` under :file:`pcapkit/`."""
return sorted((ROOT / 'docs').rglob('*.rst')) + sorted((ROOT / 'docs').rglob('*.py')) \
+ sorted((ROOT / 'pcapkit').rglob('*.py'))
kept = []
for path in paths:
rel = path.relative_to(ROOT).as_posix()
if any(rel == ex or rel.startswith(ex) for ex in EXCLUDED):
continue
kept.append(path)
return kept


def _roles() -> 'list[tuple[str, int, str, str]]':
Expand Down Expand Up @@ -100,11 +85,12 @@ def test_the_scan_reads_the_pages_and_modules_it_claims_to(self) -> 'None':
'pcapkit/corekit/enum.py',
'pcapkit/foundation/engines/pypcap.py',
'pcapkit/vendor/default.py',
'pcapkit/vendor/pcapng/option_type.py',
'pcapkit/vendor/reg/apptype/apptype.py',
'pcapkit/const/pcapng/option_type.py',
'pcapkit/const/reg/apptype/apptype.py',
'docs/source/conf.py'):
self.assertIn(expected, names)
for excluded in EXCLUDED:
self.assertFalse(any(name == excluded or name.startswith(excluded)
for name in names), excluded)

def test_the_target_parser_sees_through_an_explicit_title(self) -> 'None':
"""``:mod:`PyPCAP <pcap>``` names ``pcap`` even though its text does not."""
Expand Down
Loading