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
112 changes: 112 additions & 0 deletions .github/workflows/cron-issue-pr-kinds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: Issue and PR Kinds

# #2561: keeps tests/project/issue_pr_roles_fixtures/kinds.json current, the
# snapshot of issue and pull request numbers the #1103 roles test checks each
# :issue: and :pr: role against. `detect` regenerates it with
# util/issue_pr_kinds.py; `pr` proposes a change on `bot/issue-pr-kinds` for the
# owner to merge, and nothing here pushes `main`. `pr` pushes with the release
# App's token, not GITHUB_TOKEN, whose pushes start nothing, so the pull
# request's own checks run.
on:
schedule:
- cron: '17 6 * * 1' # Mondays at 06:17 UTC
workflow_dispatch:

permissions: {}

# One run at a time, so two runs cannot race for the branch. A queued run is
# kept, not cancelled: it regenerates from the tracker and skips what the
# branch already proposes.
concurrency:
group: issue-pr-kinds
cancel-in-progress: false

jobs:
# No secret and a read-only token: it reads the tracker and writes only this
# checkout. The script runs on the runner's own python3, standard library only.
detect:
name: Regenerate the issue and pull request kinds
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: read
pull-requests: read
outputs:
publish: ${{ steps.regenerate.outputs.publish }}

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# `publish` is false when nothing changed, or when the open pull request
# from `bot/issue-pr-kinds` already holds this file, so an unmerged
# proposal is not re-pushed, nor its approval asked for, every week.
- name: Regenerate the kinds
id: regenerate
env:
GH_TOKEN: ${{ github.token }}
run: python3 util/issue_pr_kinds.py --github-output

- name: Upload the kinds
if: ${{ steps.regenerate.outputs.publish == 'true' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: issue-pr-kinds
path: tests/project/issue_pr_roles_fixtures/kinds.json
retention-days: 30

- name: Say why no pull request opens
if: ${{ steps.regenerate.outputs.publish == 'true' && vars.RELEASE_APP_CLIENT_ID == '' }}
run: >-
echo "::warning title=No pull request without the release App::vars.RELEASE_APP_CLIENT_ID is unset,
so the pr job skips. Set up the App as docs/source/contributing/releasing.rst describes."

# The release App's key is a secret of the `github-release` environment, so
# the owner approves only a run with something to propose. The token has no
# `workflows` permission, so the script recreates the branch rather than move
# it past a workflow change on main.
pr:
name: Open or update the pull request
needs: detect
if: >-
${{ needs.detect.outputs.publish == 'true' && vars.RELEASE_APP_CLIENT_ID != '' &&
github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
timeout-minutes: 10
environment: github-release
# GITHUB_TOKEN only downloads `detect`'s artifact; the App's token does the rest.
permissions:
actions: read

steps:
- name: Mint the release App's token
id: app
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
with:
client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write

# The commit `detect` read, so the branch is cut from it.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.sha }}
token: ${{ steps.app.outputs.token }}

- name: Download the kinds
env:
GH_TOKEN: ${{ github.token }}
run: >-
gh run download "$GITHUB_RUN_ID" --repo "$GITHUB_REPOSITORY" --name issue-pr-kinds
--dir "$RUNNER_TEMP/kinds"

- name: Push the kinds and open or update their pull request
env:
GH_TOKEN: ${{ steps.app.outputs.token }}
APP_SLUG: ${{ steps.app.outputs.app-slug }}
APP_BOT_ID: ${{ vars.RELEASE_APP_BOT_ID }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: python3 util/issue_pr_kinds.py --publish "$RUNNER_TEMP/kinds/kinds.json" --run-url "$RUN_URL"
15 changes: 8 additions & 7 deletions docs/source/contributing/conventions/const-vendor-pairing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ Const-Vendor Pairing
under** :mod:`pcapkit.vendor`, with no exception. A registry copied from an IANA,
IETF or similar web-published table is never hand-maintained -- the crawler
re-scrapes the source and regenerates the module, so a hand edit to the generated
file is silently discarded on the next run. :issue:`2441`, raised in cross-review
and knowingly deferred rather than fixed.
file is silently discarded on the next run. Raised in cross-review of :pr:`2441`,
which deferred the TLS crawlers; ruled on :issue:`2495`, where the owner allowed no
exception and pointed a hand-maintained registry at the ``DATA`` attribute below.

The ``DATA`` Attribute, for a Registry With No Web Source
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -44,8 +45,8 @@ other generated module does.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:class:`~pcapkit.const.tls.content_type.ContentType` and
:class:`~pcapkit.const.tls.handshake_type.HandshakeType` (:pr:`2441`) now have
matching crawlers -- :mod:`pcapkit.vendor.tls.content_type` and
:class:`~pcapkit.const.tls.handshake_type.HandshakeType`, which came with the TLS
record layer, have matching crawlers -- :mod:`pcapkit.vendor.tls.content_type` and
:mod:`pcapkit.vendor.tls.handshake_type`, exported as ``TLS_ContentType`` and
``TLS_HandshakeType`` -- closing the gap :issue:`2495` tracked. Both take the
normal ``LINK``-and-scrape shape against IANA's ``tls-parameters-5.csv`` and
Expand All @@ -56,9 +57,9 @@ ARPHRD, TLS's source is a live, web-published table, so neither reads a
Running either crawler is a true no-op against the committed ``const``
modules: regenerating both reproduces the tree byte-for-byte, the same
guarantee ARPHRD and the ``sslv2`` restack carry. Getting there meant
regenerating the ``const`` modules committed alongside :pr:`2441`, which
predated the crawler and had drifted from it in three ways, caught in
cross-review of :pr:`2503`:
regenerating the ``const`` modules committed with the TLS record layer, which
predated the crawler and had drifted from it in the ways cross-review of
:pr:`2503` (:issue:`2495`) caught:

* the committed ``ContentType`` resolved values 32-63 to ``Unassigned`` via a
flat ``_missing_`` fallback, while IANA's registry -- and the crawler --
Expand Down
10 changes: 10 additions & 0 deletions docs/source/contributing/conventions/documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,16 @@ Format and Mechanics
:file:`tests/project/test_docs_issue_pr_roles_1103_unit.py` fails on a bare number
or a hand-written link in rendered text, and
:file:`tests/project/test_issue_refs_in_comments.py` on a role in a plain comment.
The first also fails on a role of the wrong kind, reading each number's kind from
:file:`tests/project/issue_pr_roles_fixtures/kinds.json`, which
``python util/issue_pr_kinds.py`` regenerates from the tracker, and which the
scheduled Issue and PR Kinds workflow proposes a refresh of
(:doc:`/contributing/workflows`).
It skips a number above the file's highest until a refresh, and fails on a lower
one the file lacks, such as a Discussion's. Its ``ALLOWED`` set exempts the
hand-written links and the bare ``#1962`` on :doc:`/contributing/workflows`, which
other tests pin in that form, so converting one means changing its pin in the same
commit.
* **Prose names the real defining module, not a re-export.** One strand of the
consistency sweep on :doc:`the roadmap </contributing/pep>`. The sentinels are the
worked example: every one is defined in :mod:`pcapkit.corekit.sentinels`, and
Expand Down
4 changes: 2 additions & 2 deletions docs/source/contributing/conventions/mint-criterion.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ and :file:`pcapkit/vendor/ipx/socket.py`'s ``UNASSIGNED_RANGE_NAMES``.
MISSING -->|"out of range, or no block covers it"| RAISE["ValueError"]
MISSING -->|"CGAType only"| MINT["extend_enum<br/>permanent member, registry grows"]
MISSING -->|"flag registries"| FLAG["super().\_missing\_<br/>pseudo-member cached in the value table only"]
MISSING -->|"block label names a party"| SUFFIXED["_unregistered_member<br/>label + _0x&lt;code&gt;"]
MISSING -->|"block label names a procedure"| BARE["_unregistered_member<br/>bare block label"]
MISSING -->|"block label names a party"| SUFFIXED["\_unregistered\_member<br/>label + \_0x&lt;code&gt;"]
MISSING -->|"block label names a procedure"| BARE["\_unregistered\_member<br/>bare block label"]

The Criterion
~~~~~~~~~~~~~
Expand Down
6 changes: 3 additions & 3 deletions docs/source/contributing/conventions/process.rst
Original file line number Diff line number Diff line change
Expand Up @@ -444,9 +444,9 @@ The PEP Discussion, Kept Current
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:file:`docs/source/contributing/pep.rst` is the source of truth for what each wave of
the roadmap covers and where it stands. The owner's ruling on :pr:`2483`: upon each
release, amend that page inline, and also post the update -- or edit it inline, either
is fine -- to the roadmap's own GitHub Discussion,
the roadmap covers and where it stands. Ruled in review of :pr:`2483` (:issue:`2449`):
upon each release, amend that page inline, and also post the update -- or edit it
inline, either is fine -- to the roadmap's own GitHub Discussion,
`PyPCAPKit Enhancement Proposals <https://github.com/JarryShaw/PyPCAPKit/discussions/106>`__.
The page stays authoritative; the Discussion is kept in step with it, not the other
way round, so a contributor who only reads the Discussion is not working from a stale
Expand Down
29 changes: 16 additions & 13 deletions docs/source/contributing/conventions/protocol-family-grouping.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ The ``id()`` Criterion
~~~~~~~~~~~~~~~~~~~~~~

**A family base lists its direct concrete subclasses.** An abstract intermediate is
left out, and so is everything beneath it. :pr:`2441`.
left out, and so is everything beneath it. Ruled in review of :pr:`2441`; no issue
holds the ruling.

The member list takes either of these forms:

Expand Down Expand Up @@ -46,7 +47,7 @@ HTTP/2 share :class:`~pcapkit.protocols.application.http.HTTP`, IPv4 and IPv6 sh
:class:`~pcapkit.protocols.internet.ip.IP`, AH and ESP share
:class:`~pcapkit.protocols.internet.ipsec.IPsec`, and SSLv2 and SSLv3 share
:class:`~pcapkit.protocols.application.ssl.SSL` (:ref:`below <protocol-family-ssl>`).
:pr:`2441`.
Ruled in review of :pr:`2441`; no issue holds the ruling.

.. _protocol-family-ssl:

Expand Down Expand Up @@ -250,20 +251,21 @@ parser's ``error``, a frame the segment ends inside stays
Canonical Names
~~~~~~~~~~~~~~~

**A versioned protocol's display name includes its version.** This is the stated
preference on :pr:`2444`, not a settled rule.
**A versioned protocol's display name includes its version.** This is the preference
stated in review of :pr:`2444`, not a settled rule; no issue holds it.
:class:`~pcapkit.protocols.link.l2tpv2.L2TPv2`'s ``name`` is
``Layer 2 Tunnelling Protocol version 2``. The HTTP/1.1 and HTTP/2 classes define no
``name`` of their own, so they report ``Hypertext Transfer Protocol``, which carries
no version.

**ICMPv4 is the case where the RFC's own name carries no version.** The ruling on
:pr:`2446`: ``ICMPv4`` keeps its versioned class and module name, but its ``id()``
drops the version for the RFC canonical name (:rfc:`792` names it plain ``ICMP``),
and its ``name`` carries no "version 4". ``ICMPv6`` keeps its own version, since
:rfc:`4443` names it with one.
**ICMPv4 is the case where the RFC's own name carries no version.** Ruled in review
of :pr:`2446` (:issue:`2436`): ``ICMPv4`` keeps its versioned class and module name,
but its ``id()`` drops the version for the RFC canonical name (:rfc:`792` names it
plain ``ICMP``), and its ``name`` carries no "version 4". ``ICMPv6`` keeps its own
version, since :rfc:`4443` names it with one.

**IGMPv1 follows the same shape, by the same reasoning** (:issue:`2439`, :pr:`2506`).
**IGMPv1 follows the same shape, by the same reasoning**, ruled in review of
:pr:`2506`; no issue holds the ruling.
:rfc:`1112` names IGMPv1's protocol plain ``IGMP``, so
:meth:`IGMPv1.id() <pcapkit.protocols.internet.igmpv1.IGMPv1.id>` is ``('IGMP',)`` and
its ``alias`` is ``'IGMP'``, while
Expand Down Expand Up @@ -292,8 +294,9 @@ Selector Matching
~~~~~~~~~~~~~~~~~

**A family name selects every version, and each version name selects its own.**
:pr:`2443`. On an IPv4 frame, ``'IP' in`` is ``True`` and ``'IPv6' in`` is ``False``.
On an IPv6 frame, ``'IP' in`` is ``True`` and ``'IPv4' in`` is ``False``.
Ruled in review of :pr:`2443` (:issue:`2438`). On an IPv4 frame, ``'IP' in`` is
``True`` and ``'IPv6' in`` is ``False``. On an IPv6 frame, ``'IP' in`` is ``True``
and ``'IPv4' in`` is ``False``.

HTTP follows it too (:issue:`2524`). On an HTTP/1.1 frame, ``'HTTP' in`` and
``'HTTP/1' in`` are ``True`` and ``'HTTP/2' in`` is ``False``, since the layer is
Expand Down Expand Up @@ -335,7 +338,7 @@ No Invented Suffixes
:class:`~pcapkit.protocols.application.http.HTTP`,
:class:`~pcapkit.protocols.link.vlan.VLAN` and
:class:`~pcapkit.protocols.link.l2tp.L2TP` are the precedent. No ``_Family`` suffix is
added (:pr:`2446`).
added, as ruled in review of :pr:`2446` (:issue:`2436`).

**A protocol class takes its module's name**, whatever its canonical name and
``id()``. The family base takes the family's name and a member its module's versioned
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ So :class:`~pcapkit.protocols.application.ftp_data.FTP_DATA`, declared
Ordering layer-first is correct in both cases, which is the point: a contributor does
not have to work out which case they are in.

Things That Will Look Like Mistakes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Apparent Mistakes
~~~~~~~~~~~~~~~~~

Each is deliberate. Do not "fix" any of them.

Expand All @@ -166,8 +166,8 @@ parser disagree.
layer it is built from.** :class:`~pcapkit.protocols.misc.checksum.ip_pseudo.IP_Pseudo`
is built from an IPv4 or IPv6 layer but is no layer on the wire, and its ``__layer__``
is :obj:`None`. Pseudo-header protocols share :mod:`pcapkit.protocols.misc.checksum`,
ruled in review of the IP pseudo-header for :issue:`2471`, whose thread does not hold
it.
ruled in review of the IP pseudo-header, :pr:`2479` (:issue:`2471`); the issue's
thread does not hold it.

**The dispatch tier is decoupled from the subpackage.** A protocol's subpackage says
nothing about which registry reaches it, and no dispatch key depends on it:
Expand Down Expand Up @@ -213,9 +213,9 @@ those also exists on :class:`~pcapkit.protocols.protocol.ProtocolBase`, so each
resolves on :class:`~pcapkit.protocols.application.ospf.OSPF`. The strict difference
:class:`~pcapkit.protocols.link.link.Link` minus
:class:`~pcapkit.protocols.application.application.Application` minus
:class:`~pcapkit.protocols.protocol.ProtocolBase` is ``__proto_key__`` alone
(:issue:`2343`), which :class:`~pcapkit.protocols.link.link.Link` declares and neither of
the others does, so it does **not** resolve on
:class:`~pcapkit.protocols.protocol.ProtocolBase` is ``__proto_key__`` alone, which
:class:`~pcapkit.protocols.link.link.Link` declares, as asked for on :pr:`2392` (no
issue holds the ruling), and neither of the others does, so it does **not** resolve on
:class:`~pcapkit.protocols.application.ospf.OSPF`. Nothing turns on that:
:func:`~pcapkit.foundation.registry.protocols.register_protocol_code` reads the pairing
out of the registry owner's own namespace rather than off the class, and reads its
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Reassembly Integration

Where a new reassembly engine under :mod:`pcapkit.foundation.reassembly` plugs into
the rest of the package. Points 1 to 3 are the owner's ruling on the DTLS reassembly
work of :issue:`2440`, whose pull-request review applies it; the issue itself does not
hold it. Point 4 rests on :pr:`2469`, which settled the DTLS case alone: in review of
work, applied in review of :pr:`2451` (:issue:`2440`); the issue itself does not hold
it. Point 4 rests on :pr:`2469`, which settled the DTLS case alone: in review of
how DTLS sizes a handshake message's buffer, the owner had DTLS reassembly follow its
RFCs.
No issue holds that ruling.
Expand Down
2 changes: 1 addition & 1 deletion docs/source/contributing/conventions/registry-protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Which branch a key takes, and what each miss ends in:

flowchart TD
GET["get(key, default)"] -->|"isinstance(key, str)"| NAME["\_member\_map\_ lookup"]
GET -->|"otherwise"| VALUE["_validate_value(key)<br/>then cls(key)"]
GET -->|"otherwise"| VALUE["\_validate\_value(key)<br/>then cls(key)"]
NAME -->|"miss, no usable default"| KEYERR["EnumKeyError<br/>quiet, derives KeyError"]
NAME -->|"hit,<br/>or miss, key is a registered value,<br/>or miss, default is a registered value"| OK["canonical member"]
VALUE -->|"resolves, or \_missing\_ answers,<br/>or ValueError, default is a registered value"| OK
Expand Down
5 changes: 3 additions & 2 deletions docs/source/contributing/conventions/sentinel-convention.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ derives from it mechanically -- title-case each underscore-separated word and ap
GitHub issue :issue:`911`'s housing ruling -- one module for all of them -- is why the table
names a single defining module, and it is the only import path. The modules that *use* a
sentinel import it from there but do not re-export it: :issue:`1744` dropped the
per-module re-exports, under the ruling on :issue:`1715` that a moved name keeps no
re-export at its old path. Import the object, and the type for an annotation, from
per-module re-exports, under the ruling that a moved name keeps no re-export at its old
path. It was ruled in review of :pr:`1715` (:issue:`1711`), overturning the re-export
that issue's own plan kept. Import the object, and the type for an annotation, from
:mod:`pcapkit.corekit.sentinels`.

Where a sentinel name already exists and already follows SCREAMING_SNAKE, keep it;
Expand Down
2 changes: 1 addition & 1 deletion docs/source/contributing/pep.rst
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ constructor's keyword set once, when
:func:`~pcapkit.protocols.schema.schema.schema_final` is applied at
class-definition time, rather than inferring it afresh at every call --
:attr:`~pcapkit.protocols.protocol.Protocol.__own_make_keywords__`
(:issue:`2358`) settles the same kind of question explicitly rather than
(:issue:`2286`) settles the same kind of question explicitly rather than
inferring it, though for a different question: which keywords a ``make()``
override owns, not what the names passed to it resolve against.

Expand Down
Loading
Loading