Align the layer sub-package exports with the top-level package - #113
Merged
Conversation
Each layer's __init__ carried a subset of what the top-level package re-exports, so "from netprotocols.layer7 import DHCP" failed while "from netprotocols import DHCP" worked -- an asymmetry that only bites people who import by layer, and is invisible from the top. layer3 was missing GRE, IPv4Option, IPv6Option, NDPOption and IGMPv3GroupRecord; layer7 exported only DNS, omitting DHCP, DNSOverTCP and DNSResourceRecord. layer4 was missing TCPOption, which the issue did not mention -- the same defect, found by deriving the expected set rather than working from the reported list. tests/test_exports.py now derives that expectation from each object's __module__, so a protocol added to the top level but forgotten in its layer fails the suite. It also checks the converse (no layer exports a name the top level lacks) and guards its own derivation, so a broken __module__ inspection cannot make the parametrized cases vacuously pass. Closes#80 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QJnVMNGwTRDktC4rkABtgt
Uh oh!
There was an error while loading. Please reload this page.
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes#80.
Each layer's
__init__carried a subset of what the top-level packagere-exports, so
from netprotocols.layer7 import DHCPfailed whilefrom netprotocols import DHCPworked. The asymmetry only bites peoplewho import by layer, and is invisible from the top.
What's included
src/netprotocols/layer3/__init__.py— addsGRE,IPv4Option,IPv6Option,NDPOption,IGMPv3GroupRecord.src/netprotocols/layer4/__init__.py— addsTCPOption.src/netprotocols/layer7/__init__.py— addsDHCP,DNSOverTCP,DNSResourceRecord.tests/test_exports.py— 33 parametrized cases keeping the two setsin agreement.
CHANGELOG.md— entries under## [Unreleased].layer2was already complete. Purely additive: no name changed meaning,and every added object is the same object the top level exposes (the
test asserts identity, not just presence).
One extra find
layer4was missingTCPOption, which the issue did not mention. Itturned up because the test derives the expected set from each object's
__module__rather than working from the reported list — the sameapproach that will catch the next one.
Verification
uv run ruff checkanduv run ruff format --checkare cleanuv run mypyis clean (strict)uv run pytestpasses — 735 tests, 33 new; coverage 99.79%, abovethe gate Enforce the coverage level already achieved #79 just added
CHANGELOG.mdhas an entry under## [Unreleased]The imports named in the issue, which previously raised
ImportError:And the test was checked against a regression — removing
DHCPfromlayer7's__all__failstest_name_is_exported_by_its_layer[layer7-DHCP]rather than passingquietly.
Notes
test_every_layer_contributes_somethingexists to guard the derivationitself: the parametrized cases are generated by inspecting
__module__,so if that inspection ever broke, the list would empty and every case
above it would vacuously pass. That test fails instead.
🤖 Generated with Claude Code
https://claude.ai/code/session_01QJnVMNGwTRDktC4rkABtgt
Generated by Claude Code