Skip to content

[Previous Contributors Response Needed] Transition python-zeroconf to the Apache-2.0 License #1835

Description

@bdraco

Why

python-zeroconf sits under a long list of Python projects. #1123 asked for a permissive license in 2023, and the same request has reached me many times since, mostly in private conversations with developers in the Matter and smart home space. When #1123 was raised I discussed it with jstasiak, the only other active maintainer at the time, and they agreed a permissive license would be fine for their contributions; this issue proposes Apache 2.0, one of the two licenses that request named.

The LGPL's relinking requirement is deliberate: it guarantees users can swap in their own build of the library. That is easy for ordinary Python deployments and hard for frozen binaries and other sealed distributions (#276, #1363 and #1385 are all people shipping the library inside frozen executables, none of whom raised the license), so projects in those settings avoid the dependency or go without. In practice it mostly gets lumped into a blanket no-LGPL policy rather than weighed on its own, and projects only notice when it becomes a problem, so little of this is public; an example is OpenVoiceOS's license checks flagging the dependency (OpenVoiceOS/ovos-core#546). As maintainer, my call is that this protection is not worth the users it costs. The change has a price too: some contributors declined, and all of their surviving expression had to be removed and replaced (tracked below, down to a disclosed set of single-statement lines any implementation would share). This is the consent-based approach LLVM used, with declined contributions removed rather than relicensed; nothing already released changes license.

To be clear about what this is not (since it was asked below): I am self-employed, no company employs me or directs my work, all my time on this project is volunteer time given freely with as few strings attached as possible, and I do not profit from it. No company asked me for this, I personally deliberately accept no sponsorships of any kind to avoid even a potential misalignment (I do not have GitHub Sponsors enabled), and any legal review gets paid out of my own pocket. Nobody wants to be the person asking everyone for relicensing consent; I just happen to be the one maintaining the project now.

The ask

We plan to migrate python-zeroconf from LGPL-2.1-or-later to Apache 2.0. To do this we need every contributor's permission to relicense their contributions.

If you are a contributor, please respond to this issue with something along the lines of:

I consent to my contributions to the python-zeroconf repository being relicensed under Apache 2.0 in place of the current LGPL license.

(Future contributions will simply be made under the repository's Apache 2.0 license, as with any permissively licensed project; no ongoing obligation is created by consenting here.)

I'd also recommend turning off notifications afterwards so GH does not needlessly ping you!

pyzeroconf heritage

python-zeroconf exists thanks to pyzeroconf, created by Paul Scott-Murphy in 2003 and carried forward by William McBrine. This project would not be here without their work, and their names will stay in the project's history and acknowledgements regardless of the license. An initial git blame line audit understated what survives from that era; blame credits whoever moved code in the 2021 package split. An expanded audit with move and copy detection, run after @wmcbrine's comment below, found that a meaningful amount of Paul's 2009 expression was still in the tree, mostly docstrings, so he was added to the table. After both declined, all of that expression was removed and replaced through successive rounds of progressively stronger audits (blame, move aware blame, word n-grams, character level, fuzzy paraphrase, block level, AST structure, exact whole unit, arrangement comparison, and an independent adversarial re-audit); the removal history below lists every round. The original line by line findings are preserved in the expanded audit sections as a historical record.

We thank Paul Scott-Murphy, William McBrine, and Michał Górny for their historical contributions to the earlier LGPL licensed versions. (A fourth contributor asked not to be attributed; that request is honored in this acknowledgement. The consent tracking rows and audit records below necessarily keep usernames, since they are working records rather than attribution.) Their work has been removed from the current tree and will not be part of any Apache licensed release. This acknowledgement is a thank you, not an implication of consent to relicensing.

Contributors

Below is a list of contributors sorted by their active lines of code. The counts in this table are the plain blame snapshot taken when this issue was opened, kept stable for continuity; the move and copy aware counts at current HEAD live in the pending consent audit section below and are the authoritative ones (rows added later, marked with a dagger, use the HEAD counts directly). Note that small mechanical changes (e.g. bumping a dependency pin or fixing a typo) are generally not copyrightable and would not require consent. For now we are tracking all contributors with surviving lines regardless; if we don't hear back from someone, we will evaluate their actual contributions case by case. Contributors whose code no longer appears in the current tree, and bot accounts (pre-commit autofixes, dependency pins, release automation), are not listed.

Contributor Active lines Consent
@bdraco 27,694
@Rotzbua 412
@agners 339
@jstasiak 293
@apworks1 80
@bboe 71
@Tenebrosus3141 68
@azogue 64
@pawlizio 52†
@humingchun 50†
@emontnemery 47†
@ibygrave 46
@dtantsur 45
@stephenrauch 42
@nocarryr 29†
@cdce8p 25
@che0 19
@andrewbonney 17†
@smcv 16
@inwotep 14†
@stevencrader 10
@shenek 7†
@schmittner 9†
@jpbede 8
@jacobtomlinson 8
@ZLJasonG 5
@scop 5
@mattsaxon 5
@foralesergi 4†
@jmpcm 4†
@machinekoder 4†
@gjbadros 3
@lokesh2019 3†
@mtdcr 3†
@bachp 2
@rima1881 2
@marcosdiez 2†
@Pack3tL0ss 1
@devbanu 1†
@PhilippSelenium 1†
@xandey 1†
Giovanni Harting (no GitHub login resolvable from the commit) 1†
@paulsm 0* declined; all surviving expression removed and replaced (subject to audit), see removal history and expanded audit below
@wmcbrine 0* declined; all surviving expression removed and replaced (subject to audit), see removal history and expanded audit below
@eshattow 0* defers to @wmcbrine; riscv64 wheel work reverted in #1841, workflow step names removed in #1852; only the two mechanical ref: expression fragments itemized in the expanded audit remain
@mgorny 0 declined; his two contributions, a six line sdist include block and one Cython parameter type, are uncopyrightable configuration and type annotations; #1838 reverted them and #1839 re-added the include list re-keyed and the type annotation as written, since a one token type declaration has exactly one spelling

† added after the original snapshot; the count is move and copy aware blame at current HEAD, the method used in the pending consent audit below.

* zero surviving copyrightable lines, not zero blame attributed lines: move and copy aware blame attributes 48 non blank single statement code lines to the pyzeroconf authors at HEAD (some itemized mechanical lines now blame to later commits because the delete and re-add rounds moved attribution; the itemized lists in the expanded audits remain the authoritative inventory) (RFC constant assignments, attribute stores, bare raises, flag mask returns) plus the LGPL text in COPYING, every one itemized in the expanded audits below as retained non expression, so the number a reader's own blame produces matches the number written here. The original line audit missed code that moved in the 2021 package split, which is why these rows carry expanded audits at all.

Pending consent audit

Surviving lines of the thirty contributors who have not yet responded (click to expand)

Move and copy aware blame at current HEAD, non blank lines, so the case by case evaluation is already done if anyone does not respond by round close. Dispositions: substantive means consent matters or a rewrite round is needed; small rewrite means a short delete and replace round like the earlier ones; below threshold means the surviving lines are single statements, parameters or boilerplate that would be evaluated as falling under the originality threshold.

Contributor Non blank lines Where Character Disposition if unresponsive
@stephenrauch 209 _utils/name.py (the service name validator), _services/types.py (ZeroconfServiceTypes), _protocol/outgoing.py, test helpers in test_init.py, .gitignore substantive validator and class logic plus test helpers substantive; needs consent or a dedicated rewrite round
@dtantsur 135 _utils/net.py (IPv6 socket setup), the readme IPv6 section, ipv6 parameters across _core/info/asyncio substantive IPv6 support incl. readme prose substantive; needs consent or a dedicated rewrite round
@mattsaxon 65 mostly tests/ (browser, protocol), a few signature parameter lines in src test code and parameter plumbing small rewrite
@scop 75 test module logging boilerplate across seven files, one class statement line idiomatic setup/teardown boilerplate mostly below threshold
@apworks1 51 record_manager.py (one five line comprehension), browser/services tests one src expression plus test code small rewrite
@azogue 35 signature parameter lines in _core/asyncio, test_name.py tests parameters and tests small rewrite
@Tenebrosus3141 20 context manager dunders in browser.py, tests boilerplate dunders below threshold to small rewrite
@che0 19 IPv6 address probing lines in net.py, tests small focused fix small rewrite
@gjbadros 14 packet offset bookkeeping in outgoing.py incl. one comment small focused fix with one prose comment small rewrite
@smcv 8 examples/resolver.py an example file delete the file whole and write a new example, per the established pattern
@jacobtomlinson 5 one test in test_asyncio.py single test small rewrite
@ZLJasonG 2 an errno branch in net.py two lines below threshold
@Pack3tL0ss 1 one docs link line single line below threshold
@pawlizio 52 services/test_info.py (a threaded get_service_info test pair), tests/__init__.py test code small rewrite
@humingchun 50 services/test_browser.py, test_core.py update event test code small rewrite
@emontnemery 47 test_protocol.py, test_handlers.py, test_cache.py test assertions across four files small rewrite
@nocarryr 29 test_asyncio.py, close_async plumbing lines in _core/asyncio test code plus a few src lines small rewrite
@andrewbonney 17 test_handlers.py, question type plumbing in _core/info/const parameters and tests small rewrite
@inwotep 14 test_handlers.py, three lines in query_handler.py small focused fix with tests small rewrite
@shenek 7 test_asyncio.py, test_core.py test code small rewrite
@schmittner 9 interface index lines in net.py/_core/asyncio small focused fix small rewrite
@foralesergi 4 a comment block in _utils/net.py prose comment small rewrite
@jmpcm 4 tests/test_dns.py test code small rewrite
@machinekoder 4 tests/services/test_types.py test code small rewrite
@lokesh2019 3 a comment in _core.py prose comment small rewrite
@mtdcr 3 _services/info.py single statements below threshold
@marcosdiez 2 two lines in _utils/net.py single statements below threshold
@PhilippSelenium 1 one _utils/net.py line single line below threshold
@xandey 1 one _utils/net.py line single line below threshold
Giovanni Harting 1 one _utils/net.py line single line below threshold

Removal history

Twenty two removal and hardening rounds, verified by ten independent audits (click to expand)

Twenty two rounds, each driven by a stronger audit than the last; deletions landed in revert PRs (five of them carried a handful of incidental insertion lines, one being the revert's own inverse hunk) and every replacement was freshly written and verified against the originals (two early replacements initially carried old text forward, the flag comments in #1844 and one test in #1853, and two code scaffolding lines re added by #1866 and #1873 carried old shapes; all were caught and removed by later rounds):

  1. revert: drop riscv64 wheel builds #1841 reverted the riscv64 wheel work (eshattow); chore: delete tests and examples containing non-consented work #1842 deleted the affected tests and examples
  2. revert: remove non-consented prose and code from the library #1843 deleted the blame attributed prose and code, chore: restore behavior with freshly authored replacements #1844 replaced the behavior with fresh code
  3. revert: remove derivative prose from the pyzeroconf era #1847 deleted derivative docstrings that blame had misattributed to later editors, found by a blame independent n-gram audit; chore: add freshly written docstrings and async examples #1848 replaced them and recreated the two async examples
  4. revert: remove wmcbrine's readme fork note and six short derivative docstrings #1849 deleted the readme fork note and seven short docstring lines (the loopback line appears in two classes); revert: remove prose echoing pyzeroconf sentence patterns #1851 deleted sentence pattern echoes; chore: fresh docstrings for the short-prose sites and readme rewords #1850 added the fresh replacements
  5. revert: remove short prose found by the character level audit #1852 deleted prose caught by a character level audit (four word class docstrings, test helper docstrings, a zunittest test string, workflow step names); chore: fresh docstrings, test name string and workflow step names #1853 replaced them
  6. revert: remove prose found by the fuzzy paraphrase audit #1854 deleted lines caught by a fuzzy paraphrase audit (production send docstrings, unregister docstrings, the remaining equality family); chore: fresh docstrings for the fuzzy audit sites #1855 replaced them
  7. revert: remove two docstrings echoing 2009 phrasing #1856 deleted two docstrings caught by a block level audit; chore: fresh docstrings for the block audit sites #1857 replaced them; an AST structure comparison found no large scale structural matches in src/ (its coverage of tests/ was incomplete, see round 12; roughly twenty small bodies of two to seven statements (field writes, flag mask tests, equality one liners, length prefixed string writes, the TTL formula) necessarily keep the 2009 statement sequence because the operation each performs admits essentially one expression, retained as compelled and confirmed by the fourth and fifth audits)
  8. revert: remove short verbatim prose caught by the whole unit audit #1858 deleted the two to four word verbatim docstrings caught by an exact whole unit audit with no length floor (accessor and entry docstrings, the unregister and listener family, the packets docstring); chore: fresh docstrings for the whole unit audit sites #1859 replaced them (an arrangement claim originally made here was later found to rest on a broken comparison and is corrected in round 12)
  9. a ninth audit of string literals and identifier names found nothing further in src/; the shared names there are the API classes (seven exported in __all__, the DNS record and codec classes importable and relied on by downstream projects) and RFC constant names, uncopyrightable short phrases and load bearing API surface (four 2009 test class names it missed were retired in round 12)
  10. revert: remove the legacy license banner from every module #1860 removed the legacy 21 line banner from all 36 modules (the v0.14-wmcbrine title, the vestigial 2003/2014 copyright line, the original description prose, and the FSF boilerplate) and chore: add a short license header pointing at COPYING #1861 replaced it with a short LGPL header pointing at COPYING; with the banner gone the prose audits run with no exclusions and report zero shared five word prose runs with any pyzeroconf era blob; five word runs in code lines remain and are the mechanical matches documented in the expanded audits
  11. a 30 character audit over every tracked file, including the pxd files and changelog earlier passes skipped, found one last derivative docstring, removed in revert: remove a derivative notify docstring #1862 and replaced in chore: fresh docstring for notify_all #1863; every other match classified as mechanical, factual attribution, or the project name phrase
  12. an independent adversarial audit of all the claims above found that Paul's 2009 ZeroconfTest.py survived as a mechanically modernized port in test_init, test_protocol and test_core (same class names, method sequence, fixtures and assertions; blame lost the lineage at the 2021 test split, and the earlier structural audits did not cover tests). revert: remove the modernized port of the 2009 test suite #1865 deleted sixteen test methods whole (the eleven the audit scored plus five sibling methods in the same 2009 descended families) and chore: fresh bare pytest tests, de-classed suites and new fixture values #1866 replaced the coverage with freshly authored bare pytest functions, retired the 2009 class names by converting the surviving class based tests to bare functions, and replaced the 2009 descended fixture values across the whole suite. The same audit corrected three earlier overclaims, reflected above: the working method order comparison shows DNSRecord and DNSOutgoing keep substantially the 2009 public method order and _dns.py keeps the 2009 class order, which is API surface and ordering rather than prose, noted here for transparency
  13. the independent auditor re-ran all eight of their audits against the round 12 tree and confirmed the revision holds: none of the 2009 test suite's def or class names remain (the public API class and exception names remain deliberately, per round 9: uncopyrightable short phrases and load bearing API surface), the ported fixtures are at zero occurrences, and the fresh tests are non derivative. Since that re-audit: chore: order classes and methods by the repo convention #1867 reordered the classes and methods to a stated deterministic convention; by the third audit's reproducible metric (ordered LCS over shared snake cased method names) DNSRecord went 1.00 to 0.78 and DNSOutgoing 1.00 to 0.67, and the _dns.py class order went 8/8 to 7/8 shared name LCS, with the residual overlap being the alphabetical rule coinciding with the 2009 ordering of the shared DNSRecord accessor run (2009's layout is not near alphabetical in general); chore: refresh the stale package author and maintainer metadata #1868 refreshed the stale __author__ and __maintainer__ metadata; chore: replace the remaining 2009 era path fixture values #1869 replaced the remaining 2009 era path fixture values in the tests. A third independent re-audit against that tree confirmed all three PRs hold as described, with zero shared def or class names and only mechanical single statement matches remaining
  14. a second independent adversarial audit, run with a wider corpus (every intermediate pyzeroconf blob), confirmed every removal round as real and surfaced the last blind spots of blame driven scoping: two 2021 example files carrying wmcbrine's 2014 display block by copy paste, the readme usage example descended from the 2009 Browser.py, and the arbitrary DNSText repr truncation, all deleted whole in revert: remove examples and repr inherited from the 2014 browser example #1872 and replaced brand new in chore: brand new async examples, fresh readme example and DNSText repr #1873 (the recreated readme example necessarily reuses five lines byte for byte: the import, three listener method signatures and the service info lookup call, compelled API surface); the ordering convention was extended to the remaining large classes in chore: extend the ordering convention to the remaining large classes #1874; by the same third audit metric Zeroconf went 1.00 to 0.42, ServiceInfo 1.00 to 0.75 and DNSCache 1.00 to 0.75, while DNSIncoming and ServiceBrowser keep their two to three shared names in coincidental rule generated order

On replacement docstrings: five one sentence replacements measure 0.62 to 0.81 against the 2009 blobs; measured against the exact removed lines, nine sites reach 0.62 to 0.86, three of them sharing only the compelled 16 bit type name. The highest scoring lines were reworded again in #1886. A docstring that accurately names the fields a method compares can only be phrased so many ways; the position taken here is that such functional one liners are unprotectable however phrased, and the similarity is disclosed rather than claimed away. Retained as non expression and disclosed likewise: the const.py scalar constant block in numeric order (numeric order is the canonical arrangement of RFC values, and coincides with the 2009 arrangement, which is therefore unchanged), the import zeroconf as r idiom and the Unit tests for zeroconf.X docstring template across the test suite, and the compelled API surface itemized in the expanded audits.

  1. a third independent audit re-derived every claim from the object store, confirming the prose removal, the revert fidelity and the test rewrite, and correcting the overstatements now fixed above; it surfaced the last structural port, the record display family in _dns.py whose hdr[type,class,name] layout, ?(x) fallback and ttl/remaining prefix reproduce the 2009 toString family, removed whole in revert: remove the 2009 record display formats #1878 and replaced in chore: fresh record display formats #1880 with an independently designed architecture: one module level formatter over structured field collections with label properties, no restored delegation chain, and the four public names kept as thin compatibility shims since API names are not copyrightable and downstream consumers depend on them, along with a 2021 comment paraphrase in the name compressor; the five surviving testname fixture stems it caught were replaced in chore: replace the last testname fixture stems #1881. Retained and disclosed per its inventory: the generated and parsed test variable idiom (a naming convention, not expression) and the compelled identifier surface

  2. a fourth independent audit confirmed all 205 expanded audit citations resolve exactly and every ordering metric reproduces, and found the last blind spot: the changelog, where semantic release had quoted mgorny's commit body verbatim outside blame's reach; chore: refresh changelog prose, metadata and test listener naming #1884 rewrites that entry and eshattow's PR title as neutral summaries, gives the pyproject authors metadata the chore: refresh the stale package author and maintainer metadata #1868 treatment, renames the 2009 MyListener test class name, and rewords two remaining phrase echoes. chore: add modification notices to headers and require affirmative consent for past contributions #1885 hardens two governance items from the same review: the module headers now carry the modification notice LGPL section 2 calls for, and the pull request license notice no longer treats continuing a PR as consent for previous contributions, which now requires the explicit statement on this issue. The audit also corrected the eshattow record in the maintainer's favor (the qemu comment was the maintainer's own text he had copied), and authorship checks resolved every conditional it raised: the _fast_init family and test_interface_update are the current maintainer's own 2025 and 2026 work, and the test_init helper functions are Stephen Rauch's 2016 work, tracked in the table as pending consent. For clarity: the ordering rounds (chore: order classes and methods by the repo convention #1867, chore: extend the ordering convention to the remaining large classes #1874) only ever addressed arrangement; method bodies were addressed by the earlier delete and rewrite rounds, and the display subsystem was compared holistically (field selection is the record's own field set, while the fallback text, ttl presentation and composition mechanism all differ)

  3. a fifth independent audit verified all 205 citations, the 50 line blame count and the fixture zeroes, and caught regressions and gaps now fixed: chore: fresh record display formats #1880 had silently broken the ordering convention in two classes while rebuilding the display family, and a third, DNSRRSet, had never conformed (all three brought to the convention in chore: restore the ordering convention broken by the repr rebuild and alphabetize the remaining const blocks #1886, with DNSRecord measuring 0.78 against the 2009 sequence under the audit's shared name matching, 0.70 when the renamed private suppression method is also counted, and the timing and flag constant blocks alphabetized under the same rule); four docstrings scoring 0.65 to 0.86 against removed text were reworded and the known answer suppression docstring now cites RFC 6762 section 7.1; the similarity figures previously quoted in the chore: order classes and methods by the repo convention #1867 and chore: extend the ordering convention to the remaining large classes #1874 PR bodies came from an earlier metric and are superseded by the audit verified figures in this issue; and eight contributors with surviving lines had no table row, now added with daggered HEAD counts (pawlizio, humingchun, emontnemery, nocarryr, andrewbonney, inwotep, shenek, schmittner). Three blame attributed lines not previously itemized (a loop counter initialization and two test scaffolding lines) are noted in the expanded audit as part of the retained single statement set

  4. a sixth independent audit reproduced the 50 line blame count, the byte exact reverts and the zero prose result, and flagged the remaining residue and overstatements, all now addressed: the registration probe pacing loop, whose clock and counter skeleton descended from the 2009 checkService at a larger scale than the four statement bodies round 7 disclosed (simplified and renamed in refactor: compute probe pacing from fresh clock reads #1888, which flattens the conflict loop, inverts the wait arithmetic and retires the 2009 blamed loop counter line, taking the itemized blame count from 50 to 49; the step sequence that remains implements the RFC 6762 section 8.1 probe and conflict handling behavior; the RFC compels the timing and the rename on conflict rather than the loop shape, which is retained and disclosed), the DNSOutgoing field initialization sequence at 0.83 token similarity (regenerated in chore: rework the remaining shapes flagged by the sixth independent audit #1889 under the alphabetical within groups rule, with the four section lists kept in RFC 1035 section 4.1 order), one five word prose run the round 17 reword had left in place, contradicting the round 10 zero claim at current HEAD ("is at least half of", reworded again in chore: rework the remaining shapes flagged by the sixth independent audit #1889), and the docstrings still measuring 0.60 to 0.65 against removed text (reworded or deleted in chore: rework the remaining shapes flagged by the sixth independent audit #1889; the ipaddress property and _cache.py docstrings the audits also scored are measured against removed 2021 text by the current maintainer, not pyzeroconf era text, and are retained (the ninth audit later traced one _cache.py line to a 2009 docstring; reworded in chore: drop the equality docstring family and reword the cache lookup docstring #1892, see round 21)). Ten more contributors with one to four surviving lines were added to the table with daggered HEAD counts. The audit's inventory of shared internal identifier names (method, local and constant names beyond the public API surface round 9 covered, including the preserved add_authorative_answer spelling) and the test_launch_and_close naming stem in test_core are retained and disclosed under the same rationale as the other idioms: names and naming conventions, not expression. The wmcbrine example line attribution below was also corrected: the registration and browser example lines were removed when revert: remove non-consented prose and code from the library #1843 deleted those files whole and chore: restore behavior with freshly authored replacements #1844 recreated them, not in chore: delete tests and examples containing non-consented work #1842

  5. a seventh independent audit re-derived every figure in this issue from the object store (the 49 line blame count, all 205 citations, the byte exact reverts, the banner and test method counts, and the ordering ratios) and confirmed them, while grading two sentences above as overstated, now reworded: refactor: compute probe pacing from fresh clock reads #1888 is described as a simplification and rename rather than a restructure, since the step sequence it keeps is the RFC 6762 section 8.1 probe and conflict algorithm, and the chore: restore behavior with freshly authored replacements #1844 constant table work is described as re-spacing and resorting, since the key to mnemonic pairs are RFC facts. Its remaining findings are addressed in chore: rework the remaining echoes flagged by the seventh independent audit #1890: the readme fork note had been quoting the 2009 project description sentence beyond plain attribution and no longer does, the launch and close test family (the naming stem round 18 disclosed as retained, plus a 2021 adapted unicast body that the round 12 claim of fresh replacements did not cover) was replaced with parametrized tests with fresh names (also retiring the rv.close() scaffolding line and taking the itemized blame count from 49 to 48), and the last docstring measuring 0.67 against removed text was reworded. The audit also noted 13 baseline prose lines the itemized paulsm list does not carry, covered by the 82 further docstrings sentence and all removed at HEAD, and confirmed that git ignored build output on the maintainer's disk (generated C files and an old docs build) still carried removed text; those artifacts are not in the tree and have been regenerated or deleted

  6. an eighth independent audit confirmed every count, revert fidelity and ordering ratio again, and its peripheral findings are now addressed: a stale const.py comment still describing the removed 2009 display fallback, one more docstring at 0.67 against a removed line, and two docstrings matching a 2009 docstring tail at up to 0.89 are fixed in chore: fix the stale fallback comment and reword docstrings flagged by the eighth audit #1891; the round 7 size bound is restated above as two to seven statements since four same shape bodies exceed four; round 9's wording now notes that eleven shared DNS class names are importable but not exported in __all__; the freshly written claim above carries the caveat about the two early replacements later rounds caught; the _cache.py docstrings scoring against the maintainer's own removed 2021 text are disclosed alongside the ipaddress ones; the shenek and five pending counts are refreshed to current HEAD; and the build output statement is now verified true for the checkout the removal rounds are made from: every git ignored generated file there (C files, bytecode caches, egg-info, ruff caches) was deleted and regenerated from the clean sources, with a sweep over all ignored files finding zero matches for the removed text (sibling clones used for the independent audits retain their own stale build output, which is not tree content). The 2009 era timing values (_LISTENER_TIME, _REGISTER_TIME, _UNREGISTER_TIME) are retained and disclosed as functional interop parameters rather than expression; changing them would change wire behavior

  7. a ninth independent audit re-derived the full record from the object store (all 205 citations, every count and ratio, both byte exact reverts, the 48 line blame list, zero surviving corpus prose outside the disclosed readme lines) and confirmed it, and its findings are addressed: the _cache.py lookup docstring, previously classed as scoring only against the maintainer's own removed 2021 text, traces to a 2009 docstring and is reworded in chore: drop the equality docstring family and reword the cache lookup docstring #1892, which also deletes the eight equality docstrings that still measured 0.60 to 0.69 rather than rewording them again; the round 13 alphabetical coincidence rationale is narrowed above to the DNSRecord accessor run; the round 14 brand new readme example claim now notes its five byte identical API surface lines; the round 20 disk statement is scoped to the checkout the rounds are made from; the paulsm expanded audit's 185 line figure is marked unreproduced with the itemized inventory remaining authoritative; and the numeric order disclosure now states that the constant block arrangement coincides with, and is therefore unchanged from, the 2009 arrangement

  8. a tenth independent audit reproduced the whole record again and corrected the record about itself in both directions: the 185 line figure reproduces exactly after all (the round 21 could-not-reproduce note was wrong and is fixed above), the recreated readme example shares five byte identical API surface lines rather than three, chore: fresh record display formats #1880 broke two ordering classes with a third never having conformed, and the probe loop disclosure no longer calls the loop shape compelled since the RFC compels the timing and rename behavior rather than the shape. Its code findings are addressed in three PRs: fix: correct the recursion available header flag to the rfc 1035 value #1893 corrects the recursion available flag to the RFC 1035 value, retiring a wrong constant inherited from 2009 that no packet ever used; chore: regenerate the incoming field order and retire remaining 2009 fingerprints #1894 regenerates the DNSIncoming field initialization order under the same rule as chore: rework the remaining shapes flagged by the sixth independent audit #1889's DNSOutgoing work, folds the optional data payload of the two display compatibility shims into the modern formatter with fresh parameter names, aligns the TTL test double with the production formula, and drops a stale 2009 global from the lint allow list; the ServiceInfo request polling loop the audit flagged alongside is restructured the same way as the probe loop in refactor: compute service info request pacing from fresh clock reads #1895. Newly disclosed from its inventory: fourteen 2009 method names survive as underscore prefixed private helpers, a fuller similarity sweep finds further docstrings at 0.60 to 0.97 against the maintainer's own or consented era removed text (the highest being an RFC 6763 section 12 quotation), none pyzeroconf era, and the 2021 package split's module boundaries track the 2009 file's section order, retained as dependency driven architecture rather than prose

All twenty two rounds are merged (plus #1883, which names the repr threshold constant).

A note on scope, since outside reviews have raised it: two different kinds of changes appear in this history and they carry different claims. The removal rounds above deleted expression belonging to the contributors who declined and replaced it with freshly authored material; independence is claimed there and has been verified by four independent audits. Separately, ordinary refactoring (converting test classes to functions, extracting helpers, reordering declarations, renaming fixtures) touched code belonging to consented or pending consent contributors; no independent authorship is claimed for that code, none is needed, and it remains under the current license with its authorship intact, tracked per contributor in the table and the pending consent audit above. Modernizing a pending contributor's test does not and is not meant to change whose work it is. Every finding from all three independent adversarial audits is now either removed from the tree, replaced with rule generated or freshly written material, or disclosed above with the retained rationale; the summary comments on this issue were edited to match what an independent blame run produces.

What remains from that era: the factual attribution line and LGPL statement in the readme (replaced by the relicense itself) and single statement textual matches any implementation would share (including a test double in test_browser.py that re-implements the TTL expiry arithmetic, the same mechanical class as the production formula). The __author__ metadata line was refreshed in #1868 and the declaration ordering was regenerated from a stated convention in #1867, so neither remains.

Expanded audits

The two blocks below are the original findings at commit f491259 (the pre squash head of #1839; its tree content landed as 6b2a040, which is where the line links resolve for anyone auditing from a clone), kept as a historical record; every prose line listed has since been removed by the rounds above.

paulsm expanded audit: exact surviving lines (85 prose, 85 textual matches)
wmcbrine expanded audit performed due to non-consent: exact surviving lines (2 prose, 10 edits, 5 header lines)
eshattow expanded audit: 0 surviving prose lines (riscv64 wheel work removed in #1841, workflow step names removed in #1852; only mechanical ref fragments remain)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions