You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We plan to migrate python-zeroconf from LGPL-2.1-or-later to Apache 2.0, as requested in #1123. 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 rewritten 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 was originally named here and asked not to be attributed; that request is honored.) 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.
贡献者
Below is a list of contributors sorted by their active lines of code in the current tree. Note that trivial 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. 贡献者 whose code no longer appears in the current tree, and bot accounts (pre-commit autofixes, dependency pins, release automation), are not listed.
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
❌ 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
* zero surviving copyrightable lines, not zero blame attributed lines: move and copy aware blame attributes 52 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.
Removal history
Twelve removal rounds plus a confirming independent re-audit (click to expand)
Twelve removal rounds plus a confirming independent re-audit, each driven by a stronger audit than the last; deletions landed in revert PRs (three of them carried a handful of incidental insertion lines) and every replacement was freshly written and verified against the originals:
a ninth audit of string literals and identifier names found nothing further in src/; the shared names there are the public API classes and RFC constant names, uncopyrightable short phrases and load bearing API surface (four 2009 test class names it missed were retired in round 12)
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
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
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 2009's near alphabetical layout; 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
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 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 similarity to the sentence they replaced. 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), 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.
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 with a fresh angle bracket format in chore: fresh record display formats #1880, 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
All rounds through fifteen are merged or in review. Every finding from both 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.
the audit counted 185 lines including shared header text; outside the header, 85 lines are docstrings and comments, his actual surviving prose, and 85 lines are single statement textual matches (assignments, raises, constant definitions) that any implementation would share and are listed only for completeness; all trace to the 2009 root commit
wmcbrine expanded audit performed due to non-consent: exact surviving lines (2 prose, 10 edits, 5 header lines)
the audit traced 12 substantive lines outside the shared header, 5 header lines replicated in 36 files, and a few test and example fragments; only 2 lines are his own prose, the rest are edits to 2009 text or artifacts, classified below
mechanical configuration (retained as uncopyrightable):L322-L333 the twelve riscv64 wheel matrix entries (removed with revert: drop riscv64 wheel builds #1841 regardless) and the ref: expression fragments at L188-L189 and L223-L224, workflow syntax any implementation would share
We plan to migrate python-zeroconf from LGPL-2.1-or-later to Apache 2.0, as requested in #1123. 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:
(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 blameline 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 rewritten 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 was originally named here and asked not to be attributed; that request is honored.) 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.
贡献者
Below is a list of contributors sorted by their active lines of code in the current tree. Note that trivial 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. 贡献者 whose code no longer appears in the current tree, and bot accounts (pre-commit autofixes, dependency pins, release automation), are not listed.
ref:expression fragments itemized in the expanded audit remain* zero surviving copyrightable lines, not zero blame attributed lines: move and copy aware blame attributes 52 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.
Removal history
Twelve removal rounds plus a confirming independent re-audit (click to expand)
Twelve removal rounds plus a confirming independent re-audit, each driven by a stronger audit than the last; deletions landed in revert PRs (three of them carried a handful of incidental insertion lines) and every replacement was freshly written and verified against the originals:
src/(its coverage oftests/was incomplete; see round 12)src/; the shared names there are the public API classes and RFC constant names, uncopyrightable short phrases and load bearing API surface (four 2009 test class names it missed were retired in round 12)DNSRecordandDNSOutgoingkeep substantially the 2009 public method order and_dns.pykeeps the 2009 class order, which is API surface and ordering rather than prose, noted here for transparency_dns.pyclass order went 8/8 to 7/8 shared name LCS, with the residual overlap being the alphabetical rule coinciding with 2009's near alphabetical layout; 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 remainingOn replacement docstrings: five one sentence replacements measure 0.62 to 0.81 similarity to the sentence they replaced. 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), the
import zeroconf as ridiom and theUnit tests for zeroconf.Xdocstring template across the test suite, and the compelled API surface itemized in the expanded audits._dns.pywhose 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 with a fresh angle bracket format in chore: fresh record display formats #1880, 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: thegeneratedandparsedtest variable idiom (a naming convention, not expression) and the compelled identifier surfaceAll rounds through fifteen are merged or in review. Every finding from both 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)
const.py(11): L111, L114-L116, L119-L121, L123-L125, L158_dns.py(24): L91, L96, L100, L125, L186, L193-L194, L202-L203, L207-L208, L222, L237, L241, L280, L284, L299, L355, L394, L410, L438, L454, L502, L509_core.py(13): L153, L155-L156, L166, L324, L331, L337, L657-L658, L697, L719, L811, L829_protocol/outgoing.py(7): L148, L152, L163, L244, L332, L344, L418_services/info.py(2): L425, L454_listener.py(6): L58-L60, L62, L243-L244_protocol/incoming.py(3): L75, L107, L450asyncio.py(5): L138, L140, L155, L244-L245_handlers/record_manager.py(4): L56, L67, L80, L174_utils/net.py(4): L64, L215-L217_cache.py(3): L261-L262, L306_services/browser.py(3): L672, L767, L771const.pytables were nonetheless rewritten and resorted in chore: restore behavior with freshly authored replacements #1844):const.py(48): L127-L134, L137-L154, L156, L162-L165, L171-L187_dns.py(14): L187, L209, L238, L246, L300, L311, L359, L414, L455, L460, L494-L497_core.py(5): L544, L550, L614, L669, L674_protocol/outgoing.py(11): L121, L125, L149, L160, L164, L202, L246-L248, L257, L343_services/info.py(5): L230, L244-L246, L1103_protocol/incoming.py(2): L147, L151wmcbrine expanded audit performed due to non-consent: exact surviving lines (2 prose, 10 edits, 5 header lines)
_protocol/incoming.py(2): L451-L452, the skip unknown record payloads comment, from 488de882_dns.pyandincoming.pywas rewritten in revert: remove non-consented prose and code from the library #1843 and chore: restore behavior with freshly authored replacements #1844, the rest retained as uncopyrightable):_dns.py(1): L204, collapsed the 2009if/return 1/return 0into onereturn, the predicate is verbatim 2009 line 299, from 173350e4_protocol/incoming.py(3): L317-L318 line wrapping of a 2009 sentence from e5d930bb, L453self.offset += lengthfrom b8baed3a_protocol/outgoing.py(3): L240-L241 simplified the 2009 pack call from e814dd1e, L266 a blank line inside a 2021 docstring, blame artifact_utils/net.py(1): L219, truncation of a longer 2009 comment from eee71966, the surviving words are 2009 textconst.py(2): L58-L59, removed trailing semicolons from the 2009 port constants, from f6615a9dtests/test_init.py(removed in chore: delete tests and examples containing non-consented work #1842): L1 docstring, from 0884d6a5examples/registration.py(2): L3 docstring, L37 service name string, from 0884d6a5 and 0f3b413bexamples/browser.py(1): L33if info:, from 0a05f423v0.14-wmcbrinetitle and copyright line), 4e396025 (FSF address), 21d7c950 (one reflow); the whole banner was removed in revert: remove the legacy license banner from every module #1860 and replaced with a short license header in chore: add a short license header pointing at COPYING #1861eshattow expanded audit: 0 surviving prose lines (riscv64 wheel work removed in #1841, workflow step names removed in #1852; only mechanical ref fragments remain)
.github/workflows/ci.yml; only 1 line is his own prose, the rest are mechanical workflow configurationref:expression fragments at L188-L189 and L223-L224, workflow syntax any implementation would share