netprotocols 2.7.0__tar.gz → 2.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- netprotocols-2.9.0/.flake8 +28 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/ISSUE_TEMPLATE/config.yml +1 -2
- netprotocols-2.9.0/.github/dependabot.yml +51 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/pull_request_template.md +4 -1
- netprotocols-2.9.0/.github/workflows/ci.yml +195 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/workflows/codeql.yml +13 -26
- netprotocols-2.9.0/.github/workflows/docs-lint.yml +62 -0
- netprotocols-2.9.0/.github/workflows/fuzz.yml +82 -0
- netprotocols-2.9.0/.github/workflows/mutation.yml +75 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/workflows/pr-title-lint.yml +1 -5
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/workflows/release.yml +24 -40
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/workflows/scorecard.yml +3 -7
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.gitignore +4 -4
- {netprotocols-2.7.0 → netprotocols-2.9.0}/ARCHITECTURE.md +358 -109
- {netprotocols-2.7.0 → netprotocols-2.9.0}/CHANGELOG.md +104 -1
- netprotocols-2.9.0/CONTRIBUTING.md +389 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/PKG-INFO +67 -32
- {netprotocols-2.7.0 → netprotocols-2.9.0}/README.md +66 -31
- {netprotocols-2.7.0 → netprotocols-2.9.0}/SECURITY.md +7 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/docs/CLAIMS.md +647 -90
- netprotocols-2.9.0/docs/conf.py +158 -0
- netprotocols-2.9.0/docs/index.rst +4 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/pyproject.toml +49 -44
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/_pcap.py +2 -6
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/benchmark.py +22 -34
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/benchmark_encode.py +41 -19
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/benchmark_import.py +5 -7
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures.sh +5 -4
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_bgp.sh +2 -2
- netprotocols-2.9.0/scripts/capture_fixtures_gre.sh +453 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_igmp.sh +2 -3
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_ipip.sh +1 -1
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_ipsec.sh +4 -5
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_ospf.sh +3 -4
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_stun.sh +1 -1
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_supplement.sh +6 -7
- netprotocols-2.9.0/scripts/capture_fixtures_tls.sh +565 -0
- netprotocols-2.9.0/scripts/capture_fixtures_vrrp_rfc9568.sh +339 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/check_fixtures.py +724 -186
- netprotocols-2.9.0/scripts/check_markers.py +288 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/extract_http_streams.py +8 -3
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/filter_codeql_sarif.py +18 -12
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/ipsec_fixture_packets.py +6 -7
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/llc_fixture_frames.py +3 -4
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/mpls_fixture_packets.py +3 -4
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/mutmut_survivors.txt +10 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/pyodide/check_in_pyodide.py +8 -14
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/pyodide/package.json +1 -1
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/pyodide/run_in_pyodide.mjs +3 -4
- netprotocols-2.9.0/scripts/survey_protocols.py +959 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/__init__.py +14 -2
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/_base.py +120 -118
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/_defaults.py +16 -8
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/_enums.py +3 -3
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/_tlv.py +3 -2
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/checksum.py +295 -112
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/flow.py +19 -13
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/__init__.py +2 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/arp.py +59 -29
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/cdp.py +34 -36
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/ethernet.py +35 -18
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/llc.py +44 -30
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/lldp.py +49 -46
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/mpls.py +16 -13
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/stp.py +51 -38
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/vlan.py +25 -12
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/__init__.py +2 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/ah.py +51 -23
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/esp.py +35 -18
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/gre.py +47 -16
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/icmp.py +78 -48
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/igmp.py +73 -31
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/ip.py +166 -66
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/ipv6_ext.py +120 -40
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/ospf.py +50 -27
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/pim.py +45 -28
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/vrrp.py +28 -19
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer4/__init__.py +2 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer4/_ports.py +2 -2
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer4/sctp.py +77 -55
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer4/tcp.py +43 -24
- netprotocols-2.9.0/src/netprotocols/layer4/udp.py +94 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/__init__.py +14 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/bgp.py +78 -55
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/dhcp.py +96 -53
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/dns.py +144 -62
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/hsrp.py +33 -32
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/http.py +149 -83
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/ntp.py +41 -26
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/radius.py +48 -39
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/rip.py +30 -27
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/stun.py +69 -45
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/tftp.py +46 -39
- netprotocols-2.9.0/src/netprotocols/layer7/tls.py +1353 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/vxlan.py +17 -21
- netprotocols-2.9.0/src/netprotocols/packet.py +462 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/pcap.py +85 -77
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/registry.py +175 -92
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/utils/__init__.py +2 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/utils/exceptions.py +36 -26
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/utils/ipv4.py +3 -3
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/utils/mac.py +5 -5
- netprotocols-2.9.0/src/netprotocols/walk.py +304 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/conftest.py +89 -13
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/MANIFEST.md +217 -40
- netprotocols-2.9.0/tests/fixtures/gre6.pcap +0 -0
- netprotocols-2.9.0/tests/fixtures/gre_csum.pcap +0 -0
- netprotocols-2.9.0/tests/fixtures/tls/tls_session.pcap +0 -0
- netprotocols-2.9.0/tests/fixtures/tls.pcap +0 -0
- netprotocols-2.9.0/tests/fixtures/vrrp_rfc9568.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fuzz/fuzz_decode_frame.py +12 -8
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fuzz/fuzz_http_decode.py +2 -2
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/strategies.py +58 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ah.py +1 -1
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_bgp.py +34 -3
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_cdp.py +8 -14
- netprotocols-2.9.0/tests/test_check_fixtures.py +3587 -0
- netprotocols-2.9.0/tests/test_check_markers.py +312 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_checksum.py +226 -46
- netprotocols-2.9.0/tests/test_checksum_datagram_extent.py +421 -0
- netprotocols-2.9.0/tests/test_conftest.py +89 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_contract.py +262 -4
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_corpus.py +58 -8
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_dhcp.py +1 -1
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_diagnostics.py +16 -17
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_dns.py +14 -17
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_docs.py +23 -26
- netprotocols-2.9.0/tests/test_encoding_cookies.py +95 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_esp.py +13 -12
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ethernet.py +1 -1
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_exports.py +3 -3
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_filter_codeql_sarif.py +63 -10
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_fuzz.py +441 -15
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_gre.py +1 -1
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_igmp.py +3 -3
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ip.py +5 -7
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ipip.py +2 -2
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ipv6_ext.py +8 -9
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ipv6_routing_final_dst.py +4 -4
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_llc.py +12 -3
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_lldp.py +7 -20
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_mutmut_gate.py +2 -2
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ospf.py +7 -2
- netprotocols-2.9.0/tests/test_packet.py +190 -0
- netprotocols-2.9.0/tests/test_packet_checksum_extents.py +293 -0
- netprotocols-2.9.0/tests/test_packet_checksums.py +223 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_pattern_matching.py +14 -17
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_pcap.py +9 -13
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_pim.py +63 -30
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_radius.py +47 -20
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_registry.py +309 -15
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_rip.py +13 -6
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_sctp.py +56 -40
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_stp.py +7 -18
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_stun.py +3 -2
- netprotocols-2.9.0/tests/test_survey_protocols.py +262 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_tftp.py +21 -8
- netprotocols-2.9.0/tests/test_tls.py +2532 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_tlv.py +11 -11
- netprotocols-2.9.0/tests/test_trailer.py +591 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_version.py +2 -3
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_vlan.py +1 -1
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_vrrp.py +160 -14
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_vxlan.py +4 -5
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_walk.py +6 -6
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_workflows.py +872 -110
- netprotocols-2.9.0/tests/typecheck/withheld.py +40 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/uv.lock +623 -117
- netprotocols-2.7.0/.github/dependabot.yml +0 -65
- netprotocols-2.7.0/.github/workflows/ci.yml +0 -173
- netprotocols-2.7.0/.github/workflows/docs-lint.yml +0 -75
- netprotocols-2.7.0/.github/workflows/fuzz.yml +0 -105
- netprotocols-2.7.0/.github/workflows/mutation.yml +0 -115
- netprotocols-2.7.0/CONTRIBUTING.md +0 -205
- netprotocols-2.7.0/scripts/capture_fixtures_gre.sh +0 -112
- netprotocols-2.7.0/src/netprotocols/layer4/udp.py +0 -61
- netprotocols-2.7.0/src/netprotocols/packet.py +0 -281
- netprotocols-2.7.0/src/netprotocols/walk.py +0 -243
- netprotocols-2.7.0/tests/fixtures/staging/ah.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/arp_exchange.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/bgp/bgp_session.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/bgp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/dhcp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/dns_tcp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/esp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/gre.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/hsrp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/http.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/icmpv4_echo_lo.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/icmpv4_external.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/icmpv4_ttl_exceeded.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/icmpv6_echo_lo.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/igmp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/ipip.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/ipv4_fragments.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/ipv6_fragments.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/ipv6_mld.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/ipv6_ndp_mld.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/llc.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/lldp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/mpls/mpls_snaplen.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/mpls.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/ntp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/ospf.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/pim.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/radius.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/rip.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/staging/sctp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/stun/stun_rfc3489.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/stun.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/tcp_http.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/tcp_https.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/tftp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/udp_dns.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/vlan_icmp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/vrrp.pcap +0 -0
- netprotocols-2.7.0/tests/fixtures/vxlan.pcap +0 -0
- netprotocols-2.7.0/tests/test_packet.py +0 -103
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.claude/skills/steward/SKILL.md +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.gitattributes +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/CODEOWNERS +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/ISSUE_TEMPLATE/protocol_request.yml +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/LICENSE +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/benchmarks/baseline.json +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_dhcp.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_dns_tcp.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_hsrp.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_http.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_llc.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_lldp.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_mpls.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_ntp.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_pim.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_radius.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_rip.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_sctp.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_tftp.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_vlan.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_vrrp.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_vxlan.sh +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/check_mutmut_survivors.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/pyodide/package-lock.json +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/py.typed +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ah.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/arp_exchange.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/bgp/bgp_session.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/bgp.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/codeql/python.sarif +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/dhcp.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/dns_tcp.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/esp.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/gre.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/hsrp.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/01.request +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/01.response +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/02.request +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/02.response +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/03.request +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/03.response +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/04.request +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/04.response +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/05.request +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/05.response +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/06.request +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/06.response +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/07.request +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/07.response +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/http.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/icmpv4_echo_lo.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/icmpv4_external.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/icmpv4_ttl_exceeded.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/icmpv6_echo_lo.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/igmp.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipip.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipv4_fragments.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipv6_fragments.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipv6_mld.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipv6_ndp_mld.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/llc.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/lldp.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/mpls/mpls_snaplen.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/mpls.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ntp.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ospf.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/pim.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/radius.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/rip.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/sctp.pcap +0 -0
- {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/stun/stun_rfc3489.pcap +0 -0
- {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/stun.pcap +0 -0
- {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/tcp_http.pcap +0 -0
- {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/tcp_https.pcap +0 -0
- {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/tftp.pcap +0 -0
- {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/udp_dns.pcap +0 -0
- {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/vlan_icmp.pcap +0 -0
- {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/vrrp.pcap +0 -0
- {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/vxlan.pcap +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_arp.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_enums.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_extract_http_streams.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_flow.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_hsrp.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_http.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_icmp.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_mpls.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ntp.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_tcp.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_udp.py +0 -0
- {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_utils.py +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# flake8 runs only pydoclint here: `select` limits it to pydoclint's DOC
|
|
2
|
+
# codes, and ruff covers everything else. Run it as `uv run flake8 src`.
|
|
3
|
+
# The standard these settings enforce is CONTRIBUTING.md's "Docstrings
|
|
4
|
+
# and comments" section.
|
|
5
|
+
[flake8]
|
|
6
|
+
select = DOC
|
|
7
|
+
extend-ignore =
|
|
8
|
+
# DOC201: a function that returns a value needs no :returns: field.
|
|
9
|
+
DOC201,
|
|
10
|
+
# DOC402: a generator needs no :yields: field.
|
|
11
|
+
DOC402,
|
|
12
|
+
# DOC502: a :raises: field may name an exception that a callee raises.
|
|
13
|
+
DOC502,
|
|
14
|
+
# DOC503: the :raises: fields may differ from the body's own raise
|
|
15
|
+
# statements; DOC501 still requires a :raises: field when the body
|
|
16
|
+
# raises.
|
|
17
|
+
DOC503,
|
|
18
|
+
|
|
19
|
+
# pydoclint's own options.
|
|
20
|
+
style = sphinx
|
|
21
|
+
# Docstrings carry no types: the signature's annotations hold them.
|
|
22
|
+
arg-type-hints-in-docstring = False
|
|
23
|
+
check-return-types = False
|
|
24
|
+
check-yield-types = False
|
|
25
|
+
# A docstring with no fields (:param:, :raises:, ...) is not checked.
|
|
26
|
+
skip-checking-short-docstrings = True
|
|
27
|
+
# Class attributes are not checked against the class docstring.
|
|
28
|
+
check-class-attributes = False
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
# Freeform issues
|
|
2
|
-
# fit a form); the templates just make the common cases structured.
|
|
1
|
+
# Freeform issues are enabled alongside the issue templates.
|
|
3
2
|
blank_issues_enabled: true
|
|
4
3
|
contact_links:
|
|
5
4
|
- name: Contributing guide
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
updates:
|
|
4
|
+
# --- Python tooling, managed by uv --------------------------------
|
|
5
|
+
#
|
|
6
|
+
# This project's dependencies are declared only as PEP 735
|
|
7
|
+
# [dependency-groups] in pyproject.toml (see uv.lock). The "uv"
|
|
8
|
+
# ecosystem parses [dependency-groups]; Dependabot's "pip" ecosystem
|
|
9
|
+
# does not.
|
|
10
|
+
- package-ecosystem: "uv"
|
|
11
|
+
directory: "/"
|
|
12
|
+
schedule:
|
|
13
|
+
interval: "weekly"
|
|
14
|
+
commit-message:
|
|
15
|
+
prefix: "chore"
|
|
16
|
+
groups:
|
|
17
|
+
# The "dev" dependency-group's packages (pytest, mypy, ruff, etc.),
|
|
18
|
+
# updated together in one PR. Matched by package name: for the uv
|
|
19
|
+
# ecosystem, Dependabot's dependency-type classifier reports every
|
|
20
|
+
# dependency as "production" (dependabot/dependabot-core#13202),
|
|
21
|
+
# so a `dependency-type: development` group would be empty. A
|
|
22
|
+
# runtime dependency under [project.dependencies] is not in this
|
|
23
|
+
# list, and updates in a PR of its own.
|
|
24
|
+
dev-dependencies:
|
|
25
|
+
patterns:
|
|
26
|
+
- "hypothesis"
|
|
27
|
+
- "mypy"
|
|
28
|
+
- "pytest"
|
|
29
|
+
- "pytest-cov"
|
|
30
|
+
- "ruff"
|
|
31
|
+
|
|
32
|
+
# --- GitHub Actions -------------------------------------------------
|
|
33
|
+
#
|
|
34
|
+
# Keeps the SHA-pinned `uses:` references in .github/workflows current
|
|
35
|
+
# (Dependabot updates both the pinned SHA and its trailing `# vX.Y.Z`
|
|
36
|
+
# comment).
|
|
37
|
+
- package-ecosystem: "github-actions"
|
|
38
|
+
directory: "/"
|
|
39
|
+
schedule:
|
|
40
|
+
interval: "weekly"
|
|
41
|
+
commit-message:
|
|
42
|
+
prefix: "ci"
|
|
43
|
+
groups:
|
|
44
|
+
# github/codeql-action ships init, analyze, and upload-sarif as
|
|
45
|
+
# subdirectories of one repository, and Dependabot tracks each
|
|
46
|
+
# `uses:` path as its own dependency. init and analyze must run
|
|
47
|
+
# the same release: analyze refuses a config file written by a
|
|
48
|
+
# different init version. This group bumps all three in one PR.
|
|
49
|
+
codeql-action:
|
|
50
|
+
patterns:
|
|
51
|
+
- "github/codeql-action*"
|
|
@@ -18,11 +18,14 @@ becomes the PR description.
|
|
|
18
18
|
|
|
19
19
|
## Verification
|
|
20
20
|
|
|
21
|
-
<!-- Paste the QA-ladder output, or tick the boxes.
|
|
21
|
+
<!-- Paste the QA-ladder output, or tick the boxes. The first six boxes cover the seven checks CI runs; the CHANGELOG entry is checked in review. -->
|
|
22
22
|
|
|
23
23
|
- [ ] `uv run ruff check` and `uv run ruff format --check` are clean
|
|
24
|
+
- [ ] `uv run flake8 src` (pydoclint) is clean
|
|
24
25
|
- [ ] `uv run mypy` is clean (strict)
|
|
25
26
|
- [ ] `uv run pytest` passes locally (CI runs it on Python 3.12 / 3.13 / 3.14)
|
|
27
|
+
- [ ] `python3 scripts/check_markers.py` is clean: no work markers
|
|
28
|
+
- [ ] `uv run sphinx-build -W -n -b dummy docs <outdir>` is clean: every docstring cross-reference resolves
|
|
26
29
|
- [ ] `CHANGELOG.md` has an entry under `## [Unreleased]`
|
|
27
30
|
|
|
28
31
|
### New protocol or dispatch change — also:
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
# release.yml calls this workflow to run the same ladder against a
|
|
9
|
+
# tagged commit before publishing.
|
|
10
|
+
workflow_call:
|
|
11
|
+
|
|
12
|
+
# A newer run for the same pull request (keyed on its number) or ref
|
|
13
|
+
# cancels the older one. The group's prefix is the literal "ci", so it
|
|
14
|
+
# never equals release.yml's own group when release.yml calls this
|
|
15
|
+
# workflow.
|
|
16
|
+
concurrency:
|
|
17
|
+
group: ci-${{ github.event.pull_request.number || github.ref }}
|
|
18
|
+
cancel-in-progress: true
|
|
19
|
+
|
|
20
|
+
# Every job only reads the checked-out tree.
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
lint:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
29
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
30
|
+
with:
|
|
31
|
+
python-version: "3.12"
|
|
32
|
+
- run: uv run ruff check
|
|
33
|
+
- run: uv run ruff format --check
|
|
34
|
+
# pydoclint, run as a flake8 plugin with the settings in .flake8.
|
|
35
|
+
- run: uv run flake8 src
|
|
36
|
+
# Fails on any work-marker word in tracked text (see
|
|
37
|
+
# scripts/check_markers.py). Offline.
|
|
38
|
+
- run: python3 scripts/check_markers.py
|
|
39
|
+
# Runs scripts/check_fixtures.py, stdlib-only, under the runner's
|
|
40
|
+
# python3 over tests/fixtures and over each subdirectory holding a
|
|
41
|
+
# tracked capture; fails if no capture is tracked or if any
|
|
42
|
+
# directory's run exits non-zero. tests/test_check_fixtures.py
|
|
43
|
+
# also runs it over every capture directory under each Python the
|
|
44
|
+
# test job's matrix names. It runs whether or not an earlier step
|
|
45
|
+
# failed.
|
|
46
|
+
- name: Check every committed capture with check_fixtures.py
|
|
47
|
+
if: ${{ !cancelled() }}
|
|
48
|
+
shell: bash
|
|
49
|
+
run: |
|
|
50
|
+
set -euo pipefail
|
|
51
|
+
mapfile -t dirs < <(
|
|
52
|
+
git ls-files -- 'tests/fixtures/*.pcap' | xargs -n1 dirname | sort -u
|
|
53
|
+
)
|
|
54
|
+
if [ "${#dirs[@]}" -eq 0 ]; then
|
|
55
|
+
echo "::error::git ls-files found no capture under tests/fixtures."
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
for dir in "${dirs[@]}"; do
|
|
59
|
+
python3 scripts/check_fixtures.py "$dir"
|
|
60
|
+
done
|
|
61
|
+
# Renders every docstring in src/ through Sphinx autodoc
|
|
62
|
+
# (docs/conf.py) and fails on any warning, an unresolved
|
|
63
|
+
# cross-reference role included. Fetches the Python inventory from
|
|
64
|
+
# docs.python.org; the dummy builder writes no output.
|
|
65
|
+
- run: uv run --frozen sphinx-build -W -n -b dummy docs "$RUNNER_TEMP/sphinx"
|
|
66
|
+
|
|
67
|
+
typecheck:
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
71
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
72
|
+
with:
|
|
73
|
+
python-version: "3.12"
|
|
74
|
+
- run: uv run mypy
|
|
75
|
+
|
|
76
|
+
test:
|
|
77
|
+
runs-on: ubuntu-latest
|
|
78
|
+
strategy:
|
|
79
|
+
matrix:
|
|
80
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
83
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
84
|
+
with:
|
|
85
|
+
python-version: ${{ matrix.python-version }}
|
|
86
|
+
# Also runs the doctests in src/: pyproject.toml's pytest
|
|
87
|
+
# addopts and testpaths include --doctest-modules and src.
|
|
88
|
+
- run: uv run --frozen pytest --cov=netprotocols --cov-report=term
|
|
89
|
+
# Runs every module that measures allocations with
|
|
90
|
+
# tests/conftest.py's allocation_peak while tracemalloc is already
|
|
91
|
+
# tracing from interpreter start.
|
|
92
|
+
- name: Allocation tests under PYTHONTRACEMALLOC=1
|
|
93
|
+
env:
|
|
94
|
+
PYTHONTRACEMALLOC: "1"
|
|
95
|
+
run: >-
|
|
96
|
+
uv run --frozen pytest -o addopts="" -q
|
|
97
|
+
tests/test_conftest.py tests/test_cdp.py tests/test_lldp.py
|
|
98
|
+
tests/test_sctp.py tests/test_stp.py
|
|
99
|
+
|
|
100
|
+
# Scans the dev dependency group (the only third-party code CI itself
|
|
101
|
+
# installs) for known vulnerabilities. --no-emit-project leaves out
|
|
102
|
+
# the `-e .` line for this package, which has no hash: pip-audit
|
|
103
|
+
# requires a hash on every requirement once any one carries a hash.
|
|
104
|
+
dependency-scan:
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
108
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
109
|
+
with:
|
|
110
|
+
python-version: "3.12"
|
|
111
|
+
- name: Export dev dependencies
|
|
112
|
+
run: >-
|
|
113
|
+
uv export --group dev --format requirements-txt --no-emit-project
|
|
114
|
+
-o requirements-dev.txt
|
|
115
|
+
- name: Audit dev dependencies for known vulnerabilities
|
|
116
|
+
run: >-
|
|
117
|
+
uv run --with pip-audit --no-project
|
|
118
|
+
pip-audit -r requirements-dev.txt
|
|
119
|
+
|
|
120
|
+
build:
|
|
121
|
+
runs-on: ubuntu-latest
|
|
122
|
+
steps:
|
|
123
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
124
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
125
|
+
- run: uv build
|
|
126
|
+
- run: uv run --isolated --no-project --with dist/*.whl python -c "import netprotocols; print(netprotocols.__version__)"
|
|
127
|
+
# Two back-to-back builds must emit byte-identical wheels: the step
|
|
128
|
+
# compares their sha256 and fails on any difference, such as an
|
|
129
|
+
# embedded timestamp or a change in archive member order.
|
|
130
|
+
- name: Verify the wheel build is reproducible
|
|
131
|
+
run: |
|
|
132
|
+
set -euo pipefail
|
|
133
|
+
uv build -o dist-repro-1
|
|
134
|
+
uv build -o dist-repro-2
|
|
135
|
+
hash1=$(sha256sum dist-repro-1/*.whl | cut -d ' ' -f1)
|
|
136
|
+
hash2=$(sha256sum dist-repro-2/*.whl | cut -d ' ' -f1)
|
|
137
|
+
echo "Build 1 sha256: $hash1"
|
|
138
|
+
echo "Build 2 sha256: $hash2"
|
|
139
|
+
if [ "$hash1" != "$hash2" ]; then
|
|
140
|
+
echo "::error::Wheel build is not reproducible: sha256 differs between two successive 'uv build' runs."
|
|
141
|
+
exit 1
|
|
142
|
+
fi
|
|
143
|
+
echo "Wheel build is reproducible."
|
|
144
|
+
|
|
145
|
+
# Checks the README's browser/WASM claim: boots a Pyodide runtime
|
|
146
|
+
# under Node (scripts/pyodide/run_in_pyodide.mjs) and decodes the
|
|
147
|
+
# whole real-capture corpus with the wheel this job builds.
|
|
148
|
+
# scripts/pyodide/check_in_pyodide.py describes the checks.
|
|
149
|
+
pyodide:
|
|
150
|
+
runs-on: ubuntu-latest
|
|
151
|
+
steps:
|
|
152
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
153
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
154
|
+
with:
|
|
155
|
+
python-version: "3.12"
|
|
156
|
+
- run: uv build
|
|
157
|
+
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
158
|
+
with:
|
|
159
|
+
node-version: "22"
|
|
160
|
+
- run: npm ci
|
|
161
|
+
working-directory: scripts/pyodide
|
|
162
|
+
- run: >-
|
|
163
|
+
node scripts/pyodide/run_in_pyodide.mjs
|
|
164
|
+
"$GITHUB_WORKSPACE" scripts/pyodide/check_in_pyodide.py
|
|
165
|
+
|
|
166
|
+
# Blocking: fails when normalized decode throughput is more than 15%
|
|
167
|
+
# below the committed baseline. A failing measurement is repeated
|
|
168
|
+
# once, and the job fails only if the second fails too.
|
|
169
|
+
#
|
|
170
|
+
# Runs on the baseline's interpreter: normalization cancels how fast
|
|
171
|
+
# the machine is, not which CPython runs it (see the module docstring
|
|
172
|
+
# in scripts/benchmark.py). `--update-baseline` re-records the
|
|
173
|
+
# baseline.
|
|
174
|
+
benchmark:
|
|
175
|
+
runs-on: ubuntu-latest
|
|
176
|
+
steps:
|
|
177
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
178
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
179
|
+
with:
|
|
180
|
+
python-version: "3.12"
|
|
181
|
+
- name: Corpus decode throughput
|
|
182
|
+
shell: bash
|
|
183
|
+
run: |
|
|
184
|
+
# The step exits with the benchmark's own status, saved in
|
|
185
|
+
# $status before its output is copied to the step summary.
|
|
186
|
+
status=0
|
|
187
|
+
uv run --frozen --group bench python scripts/benchmark.py \
|
|
188
|
+
--check --threshold 15 --compare >benchmark.out 2>&1 || status=$?
|
|
189
|
+
{
|
|
190
|
+
echo '```'
|
|
191
|
+
cat benchmark.out
|
|
192
|
+
echo '```'
|
|
193
|
+
} >>"$GITHUB_STEP_SUMMARY"
|
|
194
|
+
cat benchmark.out
|
|
195
|
+
exit "$status"
|
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
name: CodeQL
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
# built-in "default setup", so this analysis lives in version control
|
|
5
|
-
# alongside the rest of this repository's CI (ci.yml, fuzz.yml,
|
|
6
|
-
# release.yml, mutation.yml, scorecard.yml) and its action pins are
|
|
7
|
-
# reviewable the same way theirs are. Default setup is configured
|
|
8
|
-
# through repository settings instead of a file, so it isn't available
|
|
9
|
-
# to author from here.
|
|
3
|
+
# CodeQL advanced setup: the Python analysis is configured in this file.
|
|
10
4
|
on:
|
|
11
5
|
push:
|
|
12
6
|
branches: [master]
|
|
13
7
|
pull_request:
|
|
14
8
|
branches: [master]
|
|
15
9
|
schedule:
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
# UTC slot.
|
|
10
|
+
# Weekly on Sundays at 06:00 UTC, clear of the other workflows'
|
|
11
|
+
# cron slots.
|
|
19
12
|
- cron: "0 6 * * 0"
|
|
20
13
|
|
|
21
14
|
permissions:
|
|
@@ -36,13 +29,9 @@ jobs:
|
|
|
36
29
|
steps:
|
|
37
30
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
38
31
|
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
|
|
42
|
-
# mode the CodeQL Action's own docs recommend for interpreted
|
|
43
|
-
# languages, and it sidesteps the question of an autobuild step
|
|
44
|
-
# fitting this project's uv-based build at all.
|
|
45
|
-
- uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
|
32
|
+
# build-mode: none extracts the database straight from source,
|
|
33
|
+
# with no build step.
|
|
34
|
+
- uses: github/codeql-action/init@1fc58d04a4d4374f921bdac573c3811c240f9c26 # v4.39.2
|
|
46
35
|
with:
|
|
47
36
|
languages: python
|
|
48
37
|
build-mode: none
|
|
@@ -50,14 +39,12 @@ jobs:
|
|
|
50
39
|
# analyze writes the SARIF without uploading it, the filter step
|
|
51
40
|
# drops one query's results on two paths, and upload-sarif uploads
|
|
52
41
|
# what is left. py/weak-sensitive-data-hashing flags the MD5 that
|
|
53
|
-
# RADIUS
|
|
42
|
+
# RADIUS and STUN mandate, which their tests and
|
|
54
43
|
# scripts/check_fixtures.py compute over published test secrets
|
|
55
|
-
# with usedforsecurity=False to verify captured traffic.
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
# results whose primary location is under tests/ or scripts/; the
|
|
60
|
-
# query still runs on src/, every other query on all three.
|
|
44
|
+
# with usedforsecurity=False to verify captured traffic. The
|
|
45
|
+
# filter removes only that query's results whose primary location
|
|
46
|
+
# is under tests/ or scripts/; the query still runs on src/, every
|
|
47
|
+
# other query on all three.
|
|
61
48
|
#
|
|
62
49
|
# upload: failure-only is the action's documented mode for a
|
|
63
50
|
# workflow that post-processes the SARIF: analyze uploads nothing
|
|
@@ -80,7 +67,7 @@ jobs:
|
|
|
80
67
|
# category. Setting one on either step alone would start a second
|
|
81
68
|
# analysis next to the first.
|
|
82
69
|
- id: analyze
|
|
83
|
-
uses: github/codeql-action/analyze@
|
|
70
|
+
uses: github/codeql-action/analyze@1fc58d04a4d4374f921bdac573c3811c240f9c26 # v4.39.2
|
|
84
71
|
with:
|
|
85
72
|
upload: failure-only
|
|
86
73
|
|
|
@@ -95,6 +82,6 @@ jobs:
|
|
|
95
82
|
SARIF_DIR: ${{ steps.analyze.outputs.sarif-output }}
|
|
96
83
|
run: python3 scripts/filter_codeql_sarif.py "$SARIF_DIR"
|
|
97
84
|
|
|
98
|
-
- uses: github/codeql-action/upload-sarif@
|
|
85
|
+
- uses: github/codeql-action/upload-sarif@1fc58d04a4d4374f921bdac573c3811c240f9c26 # v4.39.2
|
|
99
86
|
with:
|
|
100
87
|
sarif_file: ${{ steps.analyze.outputs.sarif-output }}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Docs lint
|
|
2
|
+
|
|
3
|
+
# Runs lycheeverse/lychee (a link checker) over the small set of
|
|
4
|
+
# hand-maintained docs that carry the project's external claims and
|
|
5
|
+
# cross-references: README.md, ARCHITECTURE.md, CONTRIBUTING.md,
|
|
6
|
+
# CHANGELOG.md, and docs/CLAIMS.md. The pull_request trigger, filtered
|
|
7
|
+
# to those paths, checks the links of a docs edit; the weekly schedule
|
|
8
|
+
# checks the links of unchanged files, which can go dead.
|
|
9
|
+
on:
|
|
10
|
+
pull_request:
|
|
11
|
+
branches: [master]
|
|
12
|
+
paths:
|
|
13
|
+
- "README.md"
|
|
14
|
+
- "ARCHITECTURE.md"
|
|
15
|
+
- "CONTRIBUTING.md"
|
|
16
|
+
- "CHANGELOG.md"
|
|
17
|
+
- "docs/CLAIMS.md"
|
|
18
|
+
schedule:
|
|
19
|
+
# Weekly on Mondays at 06:00 UTC, clear of the other workflows'
|
|
20
|
+
# cron slots.
|
|
21
|
+
- cron: "0 6 * * 1"
|
|
22
|
+
workflow_dispatch:
|
|
23
|
+
|
|
24
|
+
concurrency:
|
|
25
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
26
|
+
cancel-in-progress: true
|
|
27
|
+
|
|
28
|
+
permissions:
|
|
29
|
+
contents: read
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
lychee:
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
36
|
+
|
|
37
|
+
# lychee-action's `token` input defaults to `${{ github.token }}`,
|
|
38
|
+
# which it exports as GITHUB_TOKEN; lychee checks github.com links
|
|
39
|
+
# through the API with it, under the authenticated rate limit.
|
|
40
|
+
#
|
|
41
|
+
# --timeout/--max-retries/--retry-wait-time exceed lychee's own
|
|
42
|
+
# defaults (20s/3/1s), so a slow or briefly rate-limited external
|
|
43
|
+
# host does not fail the run.
|
|
44
|
+
#
|
|
45
|
+
# --exclude skips img.shields.io, which serves the README badges
|
|
46
|
+
# and intermittently rate-limits or times out under CI traffic. It
|
|
47
|
+
# is the only exclusion.
|
|
48
|
+
- name: Check links in the project's hand-maintained docs
|
|
49
|
+
uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0
|
|
50
|
+
with:
|
|
51
|
+
args: >-
|
|
52
|
+
--no-progress
|
|
53
|
+
--verbose
|
|
54
|
+
--timeout 30
|
|
55
|
+
--max-retries 3
|
|
56
|
+
--retry-wait-time 10
|
|
57
|
+
--exclude '^https://img\.shields\.io'
|
|
58
|
+
README.md
|
|
59
|
+
ARCHITECTURE.md
|
|
60
|
+
CONTRIBUTING.md
|
|
61
|
+
CHANGELOG.md
|
|
62
|
+
docs/CLAIMS.md
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
name: Nightly fuzz
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
# Daily at 03:00 UTC.
|
|
6
|
+
- cron: "0 3 * * *"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
# Keyed on the triggering event too, so the nightly cron can never
|
|
10
|
+
# cancel a manually dispatched run on the same ref (the release
|
|
11
|
+
# checklist in CONTRIBUTING.md relies on one) -- runs of the same kind
|
|
12
|
+
# still supersede each other.
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
# Runs the whole suite under tests/test_fuzz.py's "nightly" profile:
|
|
22
|
+
# 10,000 examples with a random seed each run (see tests/test_fuzz.py's
|
|
23
|
+
# module docstring), where the "netprotocols" profile CI uses runs
|
|
24
|
+
# the same 200 derandomized inputs every time. Python 3.12 only.
|
|
25
|
+
fuzz:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
29
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
30
|
+
with:
|
|
31
|
+
python-version: "3.12"
|
|
32
|
+
# Keyed by run id with a prefix restore-key: restores the most
|
|
33
|
+
# recent run's Hypothesis example database and saves this run's as
|
|
34
|
+
# a new entry (actions/cache never overwrites an existing key), so
|
|
35
|
+
# the database accumulates from run to run.
|
|
36
|
+
- name: Restore accumulated Hypothesis examples
|
|
37
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
38
|
+
with:
|
|
39
|
+
path: .hypothesis
|
|
40
|
+
key: hypothesis-nightly-${{ github.run_id }}
|
|
41
|
+
restore-keys: |
|
|
42
|
+
hypothesis-nightly-
|
|
43
|
+
- name: Run the full suite under the nightly fuzz profile
|
|
44
|
+
env:
|
|
45
|
+
HYPOTHESIS_PROFILE: nightly
|
|
46
|
+
run: uv run --frozen pytest
|
|
47
|
+
# On failure, uploads the example database, which holds the
|
|
48
|
+
# minimal counterexample.
|
|
49
|
+
- name: Upload the failing example database
|
|
50
|
+
if: failure()
|
|
51
|
+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
52
|
+
with:
|
|
53
|
+
name: hypothesis-nightly-failure-${{ github.run_id }}
|
|
54
|
+
path: .hypothesis
|
|
55
|
+
retention-days: 30
|
|
56
|
+
|
|
57
|
+
# Coverage-guided fuzzing with Atheris: libFuzzer's mutation engine
|
|
58
|
+
# drives decode_frame, and HTTP.decode, which decode_frame never
|
|
59
|
+
# reaches (HTTP is not port-dispatched), through a harness of its
|
|
60
|
+
# own. Python 3.12 only.
|
|
61
|
+
atheris:
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
65
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
66
|
+
with:
|
|
67
|
+
python-version: "3.12"
|
|
68
|
+
- name: Run Atheris against decode_frame
|
|
69
|
+
run: |
|
|
70
|
+
uv run --frozen --with atheris \
|
|
71
|
+
python tests/fuzz/fuzz_decode_frame.py -max_total_time=300
|
|
72
|
+
- name: Run Atheris against HTTP.decode
|
|
73
|
+
run: |
|
|
74
|
+
uv run --frozen --with atheris \
|
|
75
|
+
python tests/fuzz/fuzz_http_decode.py -max_total_time=300
|
|
76
|
+
- name: Upload crash artifacts
|
|
77
|
+
if: failure()
|
|
78
|
+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
79
|
+
with:
|
|
80
|
+
name: atheris-crash-${{ github.run_id }}
|
|
81
|
+
path: crash-*
|
|
82
|
+
retention-days: 30
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Nightly mutation testing
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
# Daily at 04:00 UTC, an hour after fuzz.yml.
|
|
6
|
+
- cron: "0 4 * * *"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
# Keyed on the triggering event too, so the nightly cron can never
|
|
10
|
+
# cancel a manually dispatched run on the same ref (the release
|
|
11
|
+
# checklist in CONTRIBUTING.md relies on one) -- runs of the same kind
|
|
12
|
+
# still supersede each other.
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
# Python 3.12 only.
|
|
22
|
+
mutation:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.12"
|
|
29
|
+
- name: Install the project with dev dependencies
|
|
30
|
+
run: uv sync --group dev --frozen
|
|
31
|
+
# only_mutate in pyproject.toml's [tool.mutmut] table limits
|
|
32
|
+
# mutation to four files: src/netprotocols/checksum.py, _tlv.py,
|
|
33
|
+
# layer7/dns.py and layer7/http.py. These positional filters
|
|
34
|
+
# narrow that below a file, which mutmut's config cannot: in
|
|
35
|
+
# dns.py they keep only the name-compression byte walk,
|
|
36
|
+
# _read_name and _labels, and leave out the record, RDATA and
|
|
37
|
+
# dataclass code; in http.py they keep the private module-level
|
|
38
|
+
# functions, the HTTP/1.1 grammar; checksum.py and _tlv.py are
|
|
39
|
+
# mutated whole. A comment in the same [tool.mutmut] table gives
|
|
40
|
+
# this command, and tests/test_workflows.py pins the filter set.
|
|
41
|
+
# The checkout holds no mutants/ directory, so mutmut generates
|
|
42
|
+
# every mutant, traces the configured test selection in full to
|
|
43
|
+
# map each function to the tests that call it, and checks every
|
|
44
|
+
# mutant the filters select.
|
|
45
|
+
- name: Run mutmut against the scoped targets
|
|
46
|
+
run: |
|
|
47
|
+
uv run --frozen mutmut run \
|
|
48
|
+
'netprotocols.checksum.*' \
|
|
49
|
+
'netprotocols._tlv.*' \
|
|
50
|
+
'netprotocols.layer7.dns.x__read_name*' \
|
|
51
|
+
'netprotocols.layer7.dns.x__labels*' \
|
|
52
|
+
'netprotocols.layer7.http.x__*'
|
|
53
|
+
# `mutmut run` exits 0 however many mutants survive, so it can
|
|
54
|
+
# never turn this job red on its own. This step is what does: it
|
|
55
|
+
# fails on any undetected mutant not in the triage record
|
|
56
|
+
# (scripts/mutmut_survivors.txt), on a stale entry there, and on
|
|
57
|
+
# a scoped file with no checked mutant at all.
|
|
58
|
+
- name: Fail on survivors outside the triage record
|
|
59
|
+
run: |
|
|
60
|
+
uv run --frozen mutmut results --all true > mutmut-results.txt
|
|
61
|
+
uv run --frozen python scripts/check_mutmut_survivors.py \
|
|
62
|
+
mutmut-results.txt
|
|
63
|
+
# On failure, uploads the status listing and the mutants
|
|
64
|
+
# directory, which holds mutmut's per-file results and its
|
|
65
|
+
# function-to-test map; a path that does not exist is skipped.
|
|
66
|
+
- name: Upload mutmut results on failure
|
|
67
|
+
if: failure()
|
|
68
|
+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
69
|
+
with:
|
|
70
|
+
name: mutmut-nightly-failure-${{ github.run_id }}
|
|
71
|
+
path: |
|
|
72
|
+
mutmut-results.txt
|
|
73
|
+
mutants
|
|
74
|
+
if-no-files-found: ignore
|
|
75
|
+
retention-days: 30
|
|
@@ -6,11 +6,7 @@ name: PR Title Lint
|
|
|
6
6
|
# individual commit messages within a PR (see CONTRIBUTING.md); nothing
|
|
7
7
|
# here checks or rewrites those.
|
|
8
8
|
#
|
|
9
|
-
# Runs on `pull_request
|
|
10
|
-
# the PR's own metadata with a read-only, non-elevated token — no need for
|
|
11
|
-
# the elevated-permissions trigger the action's own docs suggest for
|
|
12
|
-
# repos that also want its optional "[WIP]" title support, which this
|
|
13
|
-
# repo doesn't use.
|
|
9
|
+
# Runs on `pull_request`, with a read-only token.
|
|
14
10
|
on:
|
|
15
11
|
pull_request:
|
|
16
12
|
branches: [master]
|