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.
Files changed (310) hide show
  1. netprotocols-2.9.0/.flake8 +28 -0
  2. {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/ISSUE_TEMPLATE/config.yml +1 -2
  3. netprotocols-2.9.0/.github/dependabot.yml +51 -0
  4. {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/pull_request_template.md +4 -1
  5. netprotocols-2.9.0/.github/workflows/ci.yml +195 -0
  6. {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/workflows/codeql.yml +13 -26
  7. netprotocols-2.9.0/.github/workflows/docs-lint.yml +62 -0
  8. netprotocols-2.9.0/.github/workflows/fuzz.yml +82 -0
  9. netprotocols-2.9.0/.github/workflows/mutation.yml +75 -0
  10. {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/workflows/pr-title-lint.yml +1 -5
  11. {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/workflows/release.yml +24 -40
  12. {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/workflows/scorecard.yml +3 -7
  13. {netprotocols-2.7.0 → netprotocols-2.9.0}/.gitignore +4 -4
  14. {netprotocols-2.7.0 → netprotocols-2.9.0}/ARCHITECTURE.md +358 -109
  15. {netprotocols-2.7.0 → netprotocols-2.9.0}/CHANGELOG.md +104 -1
  16. netprotocols-2.9.0/CONTRIBUTING.md +389 -0
  17. {netprotocols-2.7.0 → netprotocols-2.9.0}/PKG-INFO +67 -32
  18. {netprotocols-2.7.0 → netprotocols-2.9.0}/README.md +66 -31
  19. {netprotocols-2.7.0 → netprotocols-2.9.0}/SECURITY.md +7 -0
  20. {netprotocols-2.7.0 → netprotocols-2.9.0}/docs/CLAIMS.md +647 -90
  21. netprotocols-2.9.0/docs/conf.py +158 -0
  22. netprotocols-2.9.0/docs/index.rst +4 -0
  23. {netprotocols-2.7.0 → netprotocols-2.9.0}/pyproject.toml +49 -44
  24. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/_pcap.py +2 -6
  25. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/benchmark.py +22 -34
  26. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/benchmark_encode.py +41 -19
  27. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/benchmark_import.py +5 -7
  28. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures.sh +5 -4
  29. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_bgp.sh +2 -2
  30. netprotocols-2.9.0/scripts/capture_fixtures_gre.sh +453 -0
  31. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_igmp.sh +2 -3
  32. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_ipip.sh +1 -1
  33. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_ipsec.sh +4 -5
  34. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_ospf.sh +3 -4
  35. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_stun.sh +1 -1
  36. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_supplement.sh +6 -7
  37. netprotocols-2.9.0/scripts/capture_fixtures_tls.sh +565 -0
  38. netprotocols-2.9.0/scripts/capture_fixtures_vrrp_rfc9568.sh +339 -0
  39. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/check_fixtures.py +724 -186
  40. netprotocols-2.9.0/scripts/check_markers.py +288 -0
  41. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/extract_http_streams.py +8 -3
  42. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/filter_codeql_sarif.py +18 -12
  43. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/ipsec_fixture_packets.py +6 -7
  44. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/llc_fixture_frames.py +3 -4
  45. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/mpls_fixture_packets.py +3 -4
  46. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/mutmut_survivors.txt +10 -0
  47. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/pyodide/check_in_pyodide.py +8 -14
  48. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/pyodide/package.json +1 -1
  49. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/pyodide/run_in_pyodide.mjs +3 -4
  50. netprotocols-2.9.0/scripts/survey_protocols.py +959 -0
  51. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/__init__.py +14 -2
  52. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/_base.py +120 -118
  53. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/_defaults.py +16 -8
  54. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/_enums.py +3 -3
  55. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/_tlv.py +3 -2
  56. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/checksum.py +295 -112
  57. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/flow.py +19 -13
  58. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/__init__.py +2 -0
  59. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/arp.py +59 -29
  60. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/cdp.py +34 -36
  61. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/ethernet.py +35 -18
  62. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/llc.py +44 -30
  63. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/lldp.py +49 -46
  64. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/mpls.py +16 -13
  65. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/stp.py +51 -38
  66. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer2/vlan.py +25 -12
  67. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/__init__.py +2 -0
  68. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/ah.py +51 -23
  69. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/esp.py +35 -18
  70. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/gre.py +47 -16
  71. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/icmp.py +78 -48
  72. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/igmp.py +73 -31
  73. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/ip.py +166 -66
  74. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/ipv6_ext.py +120 -40
  75. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/ospf.py +50 -27
  76. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/pim.py +45 -28
  77. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer3/vrrp.py +28 -19
  78. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer4/__init__.py +2 -0
  79. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer4/_ports.py +2 -2
  80. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer4/sctp.py +77 -55
  81. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer4/tcp.py +43 -24
  82. netprotocols-2.9.0/src/netprotocols/layer4/udp.py +94 -0
  83. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/__init__.py +14 -0
  84. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/bgp.py +78 -55
  85. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/dhcp.py +96 -53
  86. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/dns.py +144 -62
  87. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/hsrp.py +33 -32
  88. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/http.py +149 -83
  89. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/ntp.py +41 -26
  90. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/radius.py +48 -39
  91. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/rip.py +30 -27
  92. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/stun.py +69 -45
  93. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/tftp.py +46 -39
  94. netprotocols-2.9.0/src/netprotocols/layer7/tls.py +1353 -0
  95. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/layer7/vxlan.py +17 -21
  96. netprotocols-2.9.0/src/netprotocols/packet.py +462 -0
  97. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/pcap.py +85 -77
  98. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/registry.py +175 -92
  99. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/utils/__init__.py +2 -0
  100. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/utils/exceptions.py +36 -26
  101. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/utils/ipv4.py +3 -3
  102. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/utils/mac.py +5 -5
  103. netprotocols-2.9.0/src/netprotocols/walk.py +304 -0
  104. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/conftest.py +89 -13
  105. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/MANIFEST.md +217 -40
  106. netprotocols-2.9.0/tests/fixtures/gre6.pcap +0 -0
  107. netprotocols-2.9.0/tests/fixtures/gre_csum.pcap +0 -0
  108. netprotocols-2.9.0/tests/fixtures/tls/tls_session.pcap +0 -0
  109. netprotocols-2.9.0/tests/fixtures/tls.pcap +0 -0
  110. netprotocols-2.9.0/tests/fixtures/vrrp_rfc9568.pcap +0 -0
  111. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fuzz/fuzz_decode_frame.py +12 -8
  112. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fuzz/fuzz_http_decode.py +2 -2
  113. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/strategies.py +58 -0
  114. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ah.py +1 -1
  115. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_bgp.py +34 -3
  116. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_cdp.py +8 -14
  117. netprotocols-2.9.0/tests/test_check_fixtures.py +3587 -0
  118. netprotocols-2.9.0/tests/test_check_markers.py +312 -0
  119. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_checksum.py +226 -46
  120. netprotocols-2.9.0/tests/test_checksum_datagram_extent.py +421 -0
  121. netprotocols-2.9.0/tests/test_conftest.py +89 -0
  122. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_contract.py +262 -4
  123. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_corpus.py +58 -8
  124. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_dhcp.py +1 -1
  125. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_diagnostics.py +16 -17
  126. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_dns.py +14 -17
  127. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_docs.py +23 -26
  128. netprotocols-2.9.0/tests/test_encoding_cookies.py +95 -0
  129. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_esp.py +13 -12
  130. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ethernet.py +1 -1
  131. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_exports.py +3 -3
  132. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_filter_codeql_sarif.py +63 -10
  133. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_fuzz.py +441 -15
  134. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_gre.py +1 -1
  135. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_igmp.py +3 -3
  136. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ip.py +5 -7
  137. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ipip.py +2 -2
  138. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ipv6_ext.py +8 -9
  139. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ipv6_routing_final_dst.py +4 -4
  140. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_llc.py +12 -3
  141. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_lldp.py +7 -20
  142. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_mutmut_gate.py +2 -2
  143. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ospf.py +7 -2
  144. netprotocols-2.9.0/tests/test_packet.py +190 -0
  145. netprotocols-2.9.0/tests/test_packet_checksum_extents.py +293 -0
  146. netprotocols-2.9.0/tests/test_packet_checksums.py +223 -0
  147. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_pattern_matching.py +14 -17
  148. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_pcap.py +9 -13
  149. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_pim.py +63 -30
  150. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_radius.py +47 -20
  151. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_registry.py +309 -15
  152. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_rip.py +13 -6
  153. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_sctp.py +56 -40
  154. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_stp.py +7 -18
  155. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_stun.py +3 -2
  156. netprotocols-2.9.0/tests/test_survey_protocols.py +262 -0
  157. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_tftp.py +21 -8
  158. netprotocols-2.9.0/tests/test_tls.py +2532 -0
  159. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_tlv.py +11 -11
  160. netprotocols-2.9.0/tests/test_trailer.py +591 -0
  161. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_version.py +2 -3
  162. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_vlan.py +1 -1
  163. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_vrrp.py +160 -14
  164. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_vxlan.py +4 -5
  165. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_walk.py +6 -6
  166. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_workflows.py +872 -110
  167. netprotocols-2.9.0/tests/typecheck/withheld.py +40 -0
  168. {netprotocols-2.7.0 → netprotocols-2.9.0}/uv.lock +623 -117
  169. netprotocols-2.7.0/.github/dependabot.yml +0 -65
  170. netprotocols-2.7.0/.github/workflows/ci.yml +0 -173
  171. netprotocols-2.7.0/.github/workflows/docs-lint.yml +0 -75
  172. netprotocols-2.7.0/.github/workflows/fuzz.yml +0 -105
  173. netprotocols-2.7.0/.github/workflows/mutation.yml +0 -115
  174. netprotocols-2.7.0/CONTRIBUTING.md +0 -205
  175. netprotocols-2.7.0/scripts/capture_fixtures_gre.sh +0 -112
  176. netprotocols-2.7.0/src/netprotocols/layer4/udp.py +0 -61
  177. netprotocols-2.7.0/src/netprotocols/packet.py +0 -281
  178. netprotocols-2.7.0/src/netprotocols/walk.py +0 -243
  179. netprotocols-2.7.0/tests/fixtures/staging/ah.pcap +0 -0
  180. netprotocols-2.7.0/tests/fixtures/staging/arp_exchange.pcap +0 -0
  181. netprotocols-2.7.0/tests/fixtures/staging/bgp/bgp_session.pcap +0 -0
  182. netprotocols-2.7.0/tests/fixtures/staging/bgp.pcap +0 -0
  183. netprotocols-2.7.0/tests/fixtures/staging/dhcp.pcap +0 -0
  184. netprotocols-2.7.0/tests/fixtures/staging/dns_tcp.pcap +0 -0
  185. netprotocols-2.7.0/tests/fixtures/staging/esp.pcap +0 -0
  186. netprotocols-2.7.0/tests/fixtures/staging/gre.pcap +0 -0
  187. netprotocols-2.7.0/tests/fixtures/staging/hsrp.pcap +0 -0
  188. netprotocols-2.7.0/tests/fixtures/staging/http.pcap +0 -0
  189. netprotocols-2.7.0/tests/fixtures/staging/icmpv4_echo_lo.pcap +0 -0
  190. netprotocols-2.7.0/tests/fixtures/staging/icmpv4_external.pcap +0 -0
  191. netprotocols-2.7.0/tests/fixtures/staging/icmpv4_ttl_exceeded.pcap +0 -0
  192. netprotocols-2.7.0/tests/fixtures/staging/icmpv6_echo_lo.pcap +0 -0
  193. netprotocols-2.7.0/tests/fixtures/staging/igmp.pcap +0 -0
  194. netprotocols-2.7.0/tests/fixtures/staging/ipip.pcap +0 -0
  195. netprotocols-2.7.0/tests/fixtures/staging/ipv4_fragments.pcap +0 -0
  196. netprotocols-2.7.0/tests/fixtures/staging/ipv6_fragments.pcap +0 -0
  197. netprotocols-2.7.0/tests/fixtures/staging/ipv6_mld.pcap +0 -0
  198. netprotocols-2.7.0/tests/fixtures/staging/ipv6_ndp_mld.pcap +0 -0
  199. netprotocols-2.7.0/tests/fixtures/staging/llc.pcap +0 -0
  200. netprotocols-2.7.0/tests/fixtures/staging/lldp.pcap +0 -0
  201. netprotocols-2.7.0/tests/fixtures/staging/mpls/mpls_snaplen.pcap +0 -0
  202. netprotocols-2.7.0/tests/fixtures/staging/mpls.pcap +0 -0
  203. netprotocols-2.7.0/tests/fixtures/staging/ntp.pcap +0 -0
  204. netprotocols-2.7.0/tests/fixtures/staging/ospf.pcap +0 -0
  205. netprotocols-2.7.0/tests/fixtures/staging/pim.pcap +0 -0
  206. netprotocols-2.7.0/tests/fixtures/staging/radius.pcap +0 -0
  207. netprotocols-2.7.0/tests/fixtures/staging/rip.pcap +0 -0
  208. netprotocols-2.7.0/tests/fixtures/staging/sctp.pcap +0 -0
  209. netprotocols-2.7.0/tests/fixtures/stun/stun_rfc3489.pcap +0 -0
  210. netprotocols-2.7.0/tests/fixtures/stun.pcap +0 -0
  211. netprotocols-2.7.0/tests/fixtures/tcp_http.pcap +0 -0
  212. netprotocols-2.7.0/tests/fixtures/tcp_https.pcap +0 -0
  213. netprotocols-2.7.0/tests/fixtures/tftp.pcap +0 -0
  214. netprotocols-2.7.0/tests/fixtures/udp_dns.pcap +0 -0
  215. netprotocols-2.7.0/tests/fixtures/vlan_icmp.pcap +0 -0
  216. netprotocols-2.7.0/tests/fixtures/vrrp.pcap +0 -0
  217. netprotocols-2.7.0/tests/fixtures/vxlan.pcap +0 -0
  218. netprotocols-2.7.0/tests/test_packet.py +0 -103
  219. {netprotocols-2.7.0 → netprotocols-2.9.0}/.claude/skills/steward/SKILL.md +0 -0
  220. {netprotocols-2.7.0 → netprotocols-2.9.0}/.gitattributes +0 -0
  221. {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/CODEOWNERS +0 -0
  222. {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  223. {netprotocols-2.7.0 → netprotocols-2.9.0}/.github/ISSUE_TEMPLATE/protocol_request.yml +0 -0
  224. {netprotocols-2.7.0 → netprotocols-2.9.0}/LICENSE +0 -0
  225. {netprotocols-2.7.0 → netprotocols-2.9.0}/benchmarks/baseline.json +0 -0
  226. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_dhcp.sh +0 -0
  227. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_dns_tcp.sh +0 -0
  228. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_hsrp.sh +0 -0
  229. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_http.sh +0 -0
  230. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_llc.sh +0 -0
  231. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_lldp.sh +0 -0
  232. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_mpls.sh +0 -0
  233. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_ntp.sh +0 -0
  234. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_pim.sh +0 -0
  235. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_radius.sh +0 -0
  236. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_rip.sh +0 -0
  237. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_sctp.sh +0 -0
  238. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_tftp.sh +0 -0
  239. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_vlan.sh +0 -0
  240. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_vrrp.sh +0 -0
  241. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/capture_fixtures_vxlan.sh +0 -0
  242. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/check_mutmut_survivors.py +0 -0
  243. {netprotocols-2.7.0 → netprotocols-2.9.0}/scripts/pyodide/package-lock.json +0 -0
  244. {netprotocols-2.7.0 → netprotocols-2.9.0}/src/netprotocols/py.typed +0 -0
  245. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ah.pcap +0 -0
  246. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/arp_exchange.pcap +0 -0
  247. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/bgp/bgp_session.pcap +0 -0
  248. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/bgp.pcap +0 -0
  249. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/codeql/python.sarif +0 -0
  250. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/dhcp.pcap +0 -0
  251. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/dns_tcp.pcap +0 -0
  252. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/esp.pcap +0 -0
  253. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/gre.pcap +0 -0
  254. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/hsrp.pcap +0 -0
  255. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/01.request +0 -0
  256. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/01.response +0 -0
  257. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/02.request +0 -0
  258. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/02.response +0 -0
  259. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/03.request +0 -0
  260. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/03.response +0 -0
  261. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/04.request +0 -0
  262. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/04.response +0 -0
  263. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/05.request +0 -0
  264. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/05.response +0 -0
  265. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/06.request +0 -0
  266. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/06.response +0 -0
  267. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/07.request +0 -0
  268. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/07.response +0 -0
  269. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/http/http.pcap +0 -0
  270. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/icmpv4_echo_lo.pcap +0 -0
  271. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/icmpv4_external.pcap +0 -0
  272. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/icmpv4_ttl_exceeded.pcap +0 -0
  273. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/icmpv6_echo_lo.pcap +0 -0
  274. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/igmp.pcap +0 -0
  275. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipip.pcap +0 -0
  276. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipv4_fragments.pcap +0 -0
  277. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipv6_fragments.pcap +0 -0
  278. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipv6_mld.pcap +0 -0
  279. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ipv6_ndp_mld.pcap +0 -0
  280. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/llc.pcap +0 -0
  281. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/lldp.pcap +0 -0
  282. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/mpls/mpls_snaplen.pcap +0 -0
  283. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/mpls.pcap +0 -0
  284. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ntp.pcap +0 -0
  285. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/ospf.pcap +0 -0
  286. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/pim.pcap +0 -0
  287. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/radius.pcap +0 -0
  288. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/rip.pcap +0 -0
  289. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/fixtures/sctp.pcap +0 -0
  290. {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/stun/stun_rfc3489.pcap +0 -0
  291. {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/stun.pcap +0 -0
  292. {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/tcp_http.pcap +0 -0
  293. {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/tcp_https.pcap +0 -0
  294. {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/tftp.pcap +0 -0
  295. {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/udp_dns.pcap +0 -0
  296. {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/vlan_icmp.pcap +0 -0
  297. {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/vrrp.pcap +0 -0
  298. {netprotocols-2.7.0/tests/fixtures/staging → netprotocols-2.9.0/tests/fixtures}/vxlan.pcap +0 -0
  299. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_arp.py +0 -0
  300. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_enums.py +0 -0
  301. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_extract_http_streams.py +0 -0
  302. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_flow.py +0 -0
  303. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_hsrp.py +0 -0
  304. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_http.py +0 -0
  305. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_icmp.py +0 -0
  306. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_mpls.py +0 -0
  307. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_ntp.py +0 -0
  308. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_tcp.py +0 -0
  309. {netprotocols-2.7.0 → netprotocols-2.9.0}/tests/test_udp.py +0 -0
  310. {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 stay enabled (the roadmap and design discussions don't
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. All four gates run in CI. -->
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
- # Advanced-setup workflow (a checked-in file) rather than GitHub's
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
- # Arbitrary; weekly on Sundays, clear of fuzz.yml's and mutation.yml's
17
- # daily 03:00/04:00 UTC slots and scorecard.yml's own Sunday 05:00
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
- # Python is interpreted, so there is nothing for autobuild (or a
40
- # manual build step) to do: build-mode: none has CodeQL extract
41
- # the database straight from source instead. This is the build
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 (#265) and STUN (#267) mandate, which their tests and
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
- # The CodeQL config can't scope a query to paths: query-filters
57
- # drops it everywhere, src/ included, and paths-ignore drops the
58
- # paths from every query. So the filter removes only that query's
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@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
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@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
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` (not `pull_request_target`) so it only ever sees
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]