Skip to content

refactor(protocols)!: group each protocol's protocol, schema and data into one package #2534

Closed

Description

@JarryShaw

Owner ruling on #2529 (2026-11-01), paraphrased: replace the three parallel trees (protocols/<layer>/<proto>.py, protocols/schema/<layer>/<proto>.py, protocols/data/<layer>/<proto>.py) with one package per protocol, protocols/<layer>/<proto>/{protocol,schema,data}.py.

Settled design:

Pilot: the VLAN family (vlan, c_tag, s_tag), dispatched now as a local experiment, not a PR.

Blocked: the full move waits for the open PRs that touch pcapkit/protocols (#2528 #2527 #2523 #2522 #2521 #2519 #2509 #2483) and the streams in flight. It unblocks when those have merged or closed.

Activity

  1. added
    breakingBreaks public-facing behaviour or API (apply alongside the type label)
    refactorRestructuring for its own sake — neither a fix nor a new capability (refactor: prefix)
    blockedDeferred pending another issue or decision; see the last comment for what unblocks it
    on Nov 1, 2026
  2. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor

    Pilot done on the VLAN family (local f52b9808d, not for push). After the codemod and four kinds of hand edit, all 588 modules import cleanly, 36 test modules pass, and a nitpicky docs build adds no warnings. A dry run over the whole tree touches 56 packages, makes 142 file moves, rewrites 699 files and about 10k dotted references. The codemod is kept, ready for the real run. Decisions needed first:

    1. Framework import cycle: protocol.py imports Raw's and NoPayload's schema/data at the top, and in the new layout those cycle back through misc into protocol.py. Options: (a) defer those imports; (b) keep Raw/NoPayload at the top level as framework; (c) make the layer __init__ files lazy. Recommendation: (a), measured in the full run.
    2. The schema=/data= fallback in __init_subclass__ reads the aggregators that are going away. Only L2TP relies on it. Options: look in the class's own package for sibling schema/data modules, or make the keywords mandatory. Recommendation: sibling lookup.
    3. Does a package __init__ export its class, so that protocols.link.vlan.VLAN still resolves? refactor!: remove every surviving re-export of a moved name or module #1744's D3 allows a package __init__ to aggregate its own submodules. Recommendation: yes, which also makes most imports non-breaking.
    4. The shared ipv6_option schema/data, used by HOPOPT and IPv6_Opts, goes into the family base's package: ipv6_ext's schema/data, per your ruling 1. Recommendation: that.
    5. Framework paths: schema/schema.py → protocols/schema.py, data/data.py and data/protocol.py → protocols/data.py, and the layer bases stay at <layer>/<layer>.py. Recommendation: as listed.
    6. Released changelogs: rewrite only ~ cross-reference targets, which leaves the rendered text unchanged and keeps the links resolving. Recommendation: yes.
    7. Docs: keep one page per protocol at its current URL and add the package's .. module::, rather than a directory per package. Recommendation: keep the URLs.
  3. added
    needs: decisionWaiting on the maintainer to decide — not blocked by other work
    on Nov 1, 2026
  4. moved this to Needs decision in PyPCAPKiton Nov 1, 2026
  5. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor
    1. A
    2. Sibling lookup but still takes the class constructor arguments
    3. Yes
    4. Yes, that
    5. As listed
    6. Yes
    7. Keep the URLs/docs layout, each protocol page contains first the protocol class then schema and data.
  6. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor

    Owner rulings on the pilot, paraphrased:

    1. (a): protocol.py defers its Raw/NoPayload schema and data imports.
    2. Sibling lookup: __init_subclass__ finds schema/data in the class's own package, and an explicit schema=/data= class keyword still overrides it.
    3. Yes: a package __init__ exports its class, so protocols.link.vlan.VLAN still resolves.
    4. Yes: the shared ipv6_option schema and data go into ipv6_ext's package.
    5. As listed: protocols/schema.py and protocols/data.py; layer bases stay at <layer>/<layer>.py.
    6. Yes: released changelogs get only their ~ targets rewritten.
    7. Keep the URLs: one page per protocol, with the protocol class first, then its schema, then its data.
      Back to blocked: the codemod runs once no open PR or in-flight stream touches pcapkit/protocols.
  7. removed
    needs: decisionWaiting on the maintainer to decide — not blocked by other work
    on Nov 1, 2026
  8. moved this from Needs decision to Blocked in PyPCAPKiton Nov 1, 2026
  9. added this to the PyPCAPKit v1.6 milestone on Nov 2, 2026
  10. JarryShaw commented on Nov 2, 2026

    @JarryShaw
    OwnerAuthor

    A worker is bringing the pilot's codemod up to date for every family and dry-running it on current main (all test legs and the docs build), so the final run needs no hand edits. The PR still waits for a tree where no open PR edits pcapkit/protocols/, after #2594. Moved from blocked to wip.

  11. added
    wipWork in flight - a covering PR is open or an agent is actively on it
    and removed
    blockedDeferred pending another issue or decision; see the last comment for what unblocks it
    on Nov 2, 2026
  12. 3 remaining items

  13. moved this from WIP to Needs decision in PyPCAPKiton Nov 2, 2026
  14. JarryShaw commented on Nov 2, 2026

    @JarryShaw
    OwnerAuthor
    1. (c)
    2. rewrite them
    3. keep this.
  15. JarryShaw commented on Nov 2, 2026

    @JarryShaw
    OwnerAuthor

    The owner took the recommendation on all three, paraphrased:

    1. (c): the TLS record data that SSL reads moves into the ssl package, where a family's shared pieces live. That breaks the ssl.protocol → tls.data cycle with no lazy export.
    2. The released 1.5.0 changelog's plain (non-~) references to moved paths are rewritten too, so the docs build stays clean.
    3. Each package __init__ exports its class only. Other shipped names live at their new module paths, with versionremoved at the old ones.

    The codemod worker updates codemod-v2.py and re-runs the dry run. The final run still waits for a quiet protocols tree, after #2692. This settles the questions, so needs: decision comes off.

  16. removed
    needs: decisionWaiting on the maintainer to decide — not blocked by other work
    on Nov 2, 2026
  17. moved this from Needs decision to WIP in PyPCAPKiton Nov 2, 2026
  18. JarryShaw commented on Nov 3, 2026

    @JarryShaw
    OwnerAuthor

    The codemod is updated for all three answers and dry-run again, committed locally as 4bf328a45. No hand edits remain.

    • (c): the 19 TLS data models SSL reads, plus their base, move to ssl/data.py. tls/data.py keeps TLS, and every package now imports eagerly, with no cycle. None of these shipped, so they get no versionremoved. A layout test fails if a base ever reads a member's schema or data module.
    • 1.5.0 changelog: every reference target is rewritten, ~ or not. This adds no new docs warnings outside the unfolded 1.6.0 lines.
    • Exports: class-only, unchanged.

    Every leg passes, apart from the CI-script failures main has too. The final run takes about 50–60 minutes. It dry-runs clean on current main and on #2682, #2691 and #2692. #2704 needs a one-line fix-up to its new test once it lands. The run itself waits until #2692 and the other protocol PRs have merged.

  19. JarryShaw commented on Nov 3, 2026

    @JarryShaw
    OwnerAuthor

    The serial window is open. #2483 is the only open PR, and it touches only the changelog. The final codemod run is underway on main f45c82b5d, with no hand edits and the three rulings above in force. After it lands: #2490 (member reorder), then #2730 (lazy protocol packages).

  20. JarryShaw commented on Nov 3, 2026

    @JarryShaw
    OwnerAuthor

    The PR is #2753 (e9de6cc5e), the final codemod run: one command, no hand edits. A cross-review is running.

  21. removed
    wipWork in flight - a covering PR is open or an agent is actively on it
    on Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingBreaks public-facing behaviour or API (apply alongside the type label)refactorRestructuring for its own sake — neither a fix nor a new capability (refactor: prefix)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions