diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7f95b9fc8d6..973824b1fed 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -439,7 +439,7 @@ pep-0590.rst @markshannon pep-0591.rst @ilevkivskyi pep-0592.rst @dstufft pep-0593.rst @ilevkivskyi -pep-0594.rst @tiran +pep-0594.rst @tiran @brettcannon pep-0595.rst @ezio-melotti @berkerpeksag pep-0596.rst @ambv pep-0597.rst @methane diff --git a/pep-0594.rst b/pep-0594.rst index 3cb41288ba0..cf63892b2d2 100644 --- a/pep-0594.rst +++ b/pep-0594.rst @@ -1,11 +1,13 @@ PEP: 594 Title: Removing dead batteries from the standard library -Author: Christian Heimes +Author: Christian Heimes , + Brett Cannon Discussions-To: https://discuss.python.org/t/pep-594-removing-dead-batteries-from-the-standard-library/1704 Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 20-May-2019 +Python-Version: 3.11 Post-History: 21-May-2019 @@ -18,7 +20,7 @@ and SUN file formats), APIs and operating systems that have been superseded a long time ago (e.g. Mac OS 9), or modules that have security implications and better alternatives (e.g. password and login). -The PEP follows in the foot steps of other PEPS like :pep:`3108`. The +The PEP follows in the footsteps of other PEPS like :pep:`3108`. The *Standard Library Reorganization* proposal removed a bunch of modules from Python 3.0. In 2007, the PEP referred to maintenance burden as: @@ -29,7 +31,7 @@ Python 3.0. In 2007, the PEP referred to maintenance burden as: up an undue amount of time and effort." The withdrawn :pep:`206` from 2000 expresses issues with the Python standard -library unvarnished and fortright: +library in an unvarnished and forthright manner: "[...] the standard library modules aren't always the best choices for a job. Some library modules were quick hacks (e.g. ``calendar``, @@ -47,13 +49,13 @@ philosophy and was one of the cornerstones to Python's success story. Users didn't have to figure out how to download and install separate packages in order to write a simple web server or parse email. -Times have changed. The introduction of the cheese shop (PyPI), setuptools, +Times have changed. The introduction of PyPI (née Cheeseshop), setuptools, and later pip, it became simple and straightforward to download and install packages. Nowadays Python has a rich and vibrant ecosystem of third-party packages. It's pretty much standard to either install packages from PyPI or use one of the many Python or Linux distributions. -On the other hand, Python's standard library is piling up cruft, unnecessary +On the other hand, Python's standard library is piling up with cruft, unnecessary duplication of functionality, and dispensable features. This is undesirable for several reasons. @@ -71,7 +73,7 @@ for several reasons. Micro:bit). Python on mobile platforms like BeeWare or WebAssembly (e.g. pyodide) also benefit from reduced download size. -The modules in the PEP have been selected for deprecation because their +The modules in this PEP have been selected for deprecation because their removal is either least controversial or most beneficial. For example, least controversial are 30-year-old multimedia formats like the ``sunau`` audio format, which was used on SPARC and NeXT workstations in the late @@ -91,7 +93,7 @@ code is not permitted without legal approval. * The ``optparse`` and ``getopt`` modules are widely used. They are mature modules with very low maintenance overhead. * According to David Beazley [5]_ the ``wave`` module is easy to teach to - kids and can make crazy sounds. Making a computer generate crazy sounds is + kids and can make crazy sounds. Making a computer generate sounds is a powerful and highly motivating exercise for a nine-year-old aspiring developer. It's a fun battery to keep. @@ -99,59 +101,22 @@ code is not permitted without legal approval. Deprecation schedule ==================== -3.8 ---- - -This PEP targets Python 3.8. Version 3.8.0 final is scheduled to be released -a few months before Python 2.7 will reach its end of lifetime. We expect that -Python 3.8 will be targeted by users that migrate to Python 3 in 2019 and -2020. To reduce churn and to allow a smooth transition from Python 2, -Python 3.8 will neither raise ``DeprecationWarning`` nor remove any -modules that have been scheduled for removal. Instead deprecated modules will -just be *documented* as deprecated. Optionally modules may emit a -``PendingDeprecationWarning``. - -All deprecated modules will also undergo a feature freeze. No additional -features should be added *unless* python-dev agrees that the deprecation of -the module is reverted and the code will not be removed. Bug should still be -fixed. - -3.9 ---- - -Starting with Python 3.9, deprecated modules will start issuing -``DeprecationWarning``. The `parser`_ module is removed and potentially -replaced with a new module. - -All other deprecated modules are fully supported and will receive security -updates until Python 3.9 reaches its end-of-life. Python 3.9.0 will -be released about 18 months after 3.8.0 (April 2021?) and most likely -be supported for five years after the release. The estimated EOL of Python 3.9 -is in 2026. - -3.10 +3.11 ---- -In 3.10 all deprecated modules will be removed from the CPython repository -together with tests, documentation, and autoconf rules. +Starting with Python 3.11, deprecated modules will start issuing +``DeprecationWarning``. The estimated EOL of Python 3.11 is October 2027. +3.12 +---- -PEP acceptance process -====================== - -3.8.0b1 is scheduled to be release shortly after the PEP is officially -submitted. Since it's improbable that the PEP will pass all stages of the -PEP process in time, I propose a two-step acceptance process that is -analogous to Python's two-release deprecation process. +There should be no specific change compared to Python 3.11. -The first *provisionally-accepted* phase targets Python 3.8.0b1. In the first -phase no code is changed or removed. Modules are only documented as -deprecated. The only exception is the `parser`_ module. It has been -documented as deprecated since Python 2.5 and is scheduled for removal for -3.9 to make place for a more advanced parser. +3.13 +---- -The final decision, which modules will be removed and how the removed code -is preserved, can be delayed for another year. +All modules deprecated by this PEP are removed from the ``main`` branch +of the CPython repository and are no longer distributed as part of Python. Deprecated modules @@ -167,36 +132,35 @@ audio processing. :header: "Module", "Deprecated in", "To be removed", "Added in", "Has maintainer?", "Replacement" :widths: 2, 1, 1, 1, 1, 2 - aifc,3.8 (3.0\*),3.10,1993,**yes (inactive)**,\- - asynchat,**3.6** (3.0\*),3.10,1999,**yes**,asyncio_ - asyncore,**3.6** (3.0\*),3.10,1999,**yes**,asyncio_ - audioop,3.8 (3.0\*),3.10,1992,**yes**,\- - binhex,3.8,3.10,1995,no,\- - cgi,3.8 (2.0\*\*),3.10,1995,no,\- - cgitb,3.8 (2.0\*\*),3.10,1995,no,\- - chunk,3.8,3.10,1999,no,\- - crypt,3.8,3.10,1994,**yes (inactive)**,"legacycrypt_, bcrypt_, argon2cffi_, hashlib_, passlib_" + aifc,3.11 (3.0\*),3.13,1993,**yes (inactive)**,\- + asynchat,**3.6** (3.0\*),3.12,1999,**yes**,asyncio_ + asyncore,**3.6** (3.0\*),3.12,1999,**yes**,asyncio_ + audioop,3.11 (3.0\*),3.13,1992,**yes**,\- + binhex,3.11,3.13,1995,no,\- + cgi,3.11 (2.0\*\*),3.13,1995,no,\- + cgitb,3.11 (2.0\*\*),3.13,1995,no,\- + chunk,3.11,3.13,1999,no,\- + crypt,3.11,3.13,1994,**yes (inactive)**,"legacycrypt_, bcrypt_, argon2-cffi_, hashlib_, passlib_" formatter,**3.4**,3.10,1995,no,\- fpectl,**3.7**,**3.7**,1997,n/a,\- - imghdr,3.8,3.10,1992,no,"filetype_, puremagic_, python-magic_" - imp,**3.4**,3.10,1990/1995,no,importlib_ - macpath,**3.7**,**3.8**,1990,n/a,\- - msilib,3.8,3.10,2006,no,\- - nntplib,3.8,3.10,1992,no,\- - nis,3.8 (3.0\*),3.10,1992,no,\- - ossaudiodev,3.8,3.10,2002,no,\- - parser,**2.5**,**3.9**,1993,**yes**,"ast_, astroid_, lib2to3.pgen2" - pipes,3.8,3.10,1992,no,"subprocess_" - smtpd,"**3.4.7**, **3.5.4**",3.10,2001,**yes**,"aiosmtpd_" - sndhdr,3.8,3.10,1994,no,"filetype_, puremagic_, python-magic_" - spwd,3.8,3.10,2005,no,"python-pam_, simplepam_" - sunau,3.8 (3.0\*),3.10,1993,no,\- - telnetlib,3.8 (3.0\*),3.10,1997,no,"telnetlib3_, Exscript_" - uu,3.8,3.10,1994,no,\- - xdrlib,3.8,3.10,1992/1996,no,\- + imghdr,3.11,3.13,1992,no,"filetype_, puremagic_, python-magic_" + imp,**3.4**,3.12,1990/1995,no,importlib_ + macpath,**3.7**,**3.11**,1990,n/a,\- + msilib,3.11,3.13,2006,no,\- + nntplib,3.11,3.13,1992,no,\- + nis,3.8 (3.0\*),3.13,1992,no,\- + ossaudiodev,3.11,3.13,2002,no,\- + pipes,3.11,3.13,1992,no,"subprocess_" + smtpd,"**3.4.7**, **3.5.4**",3.12,2001,**yes**,"aiosmtpd_" + sndhdr,3.11,3.13,1994,no,"filetype_, puremagic_, python-magic_" + spwd,3.11,3.13,2005,no,"python-pam_" + sunau,3.11 (3.0\*),3.13,1993,no,\- + telnetlib,3.11 (3.0\*),3.13,1997,no,"telnetlib3_, Exscript_" + uu,3.11,3.13,1994,no,\- + xdrlib,3.11,3.13,1992/1996,no,\- .. _aiosmtpd: https://pypi.org/project/aiosmtpd/ -.. _argon2cffi: https://pypi.org/project/argon2-cffi/ +.. _argon2-cffi: https://pypi.org/project/argon2-cffi/ .. _ast: https://docs.python.org/3/library/ast.html .. _astroid: https://pypi.org/project/astroid/ .. _asyncio: https://docs.python.org/3/library/hashlib.html @@ -235,9 +199,9 @@ encode binary email attachments. Module type pure Python Deprecated in - 3.8 + 3.11 To be removed in - 3.10 + 3.13 Has a designated expert no Substitute @@ -252,16 +216,6 @@ format has been replaced by MIME. The uu codec is provided by the ``binascii`` module. There's also ``encodings/uu_codec.py`` which is a codec for the same encoding; it should also be deprecated. -Module type - pure Python -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** xdrlib ~~~~~~ @@ -271,17 +225,6 @@ the Sun External Data Representation Standard. XDR is an old binary serialization format from 1987. These days it's rarely used outside specialized domains like NFS. -Module type - pure Python -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** - Multimedia modules ------------------ @@ -302,16 +245,6 @@ may be a compelling argument to keep the ``aifc`` module in the standard library. The file format is stable and the module does not require much maintenance. The strategic benefits for Python may outmatch the burden. -Module type - pure Python (depends on some functions from `audioop`_ C extension) -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - yes, but expert is currently inactive. -Substitute - **none** audioop ~~~~~~~ @@ -328,16 +261,6 @@ the ``audioop`` module is converted into a private implementation detail, e.g. ``_audioop`` with ``byteswap``, ``alaw2lin``, ``ulaw2lin``, ``lin2alaw``, ``lin2ulaw``, and ``lin2adpcm``. -Module type - C extension -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - yes -Substitute - **none** chunk ~~~~~ @@ -347,16 +270,6 @@ support for reading and writing Electronic Arts' Interchange File Format. IFF is an old audio file format originally introduced for Commodore and Amiga. The format is no longer relevant. -Module type - pure Python -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** imghdr ~~~~~~ @@ -366,18 +279,6 @@ simple tool to guess the image file format from the first 32 bytes of a file or buffer. It supports only a limited number of formats and neither returns resolution nor color depth. -Module type - pure Python -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - `puremagic `_, - `filetype `_, - `python-magic `_ ossaudiodev ~~~~~~~~~~~ @@ -400,16 +301,6 @@ The standard library used to have more audio-related modules. The other audio device interface (``audiodev``, ``linuxaudiodev``, ``sunaudiodev``) were removed in 2007 as part of the :pep:`3108` stdlib re-organization. -Module type - C extension -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** sndhdr ~~~~~~ @@ -420,18 +311,6 @@ format, channels, frame rate, and sample widths from the first 512 bytes of a file or buffer. The module only supports AU, AIFF, HCOM, VOC, WAV, and other ancient formats. -Module type - pure Python (depends on `audioop`_ C extension for some operations) -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - `puremagic `_, - `filetype `_, - `python-magic `_ sunau ~~~~~ @@ -439,17 +318,6 @@ sunau The `sunau `_ module provides support for Sun AU sound format. It's yet another old, obsolete file format. -Module type - pure Python (depends on `audioop`_ C extension for some operations) -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** - Networking modules ------------------ @@ -460,16 +328,6 @@ asynchat The `asynchat `_ module is built on top of `asyncore`_ and has been deprecated since Python 3.6. -Module type - pure Python -Deprecated in - 3.6 -Removed in - 3.10 -Has a designated expert - yes -Substitute - asyncio asyncore ~~~~~~~~ @@ -483,17 +341,6 @@ The ``asyncore`` module is also used in stdlib tests. The tests for based on ``asyncore``. These tests must be updated to use asyncio or threading. -Module type - pure Python -Deprecated in - 3.6 -Removed in - 3.10 -Has a designated expert - yes -Substitute - asyncio - cgi ~~~ @@ -513,17 +360,6 @@ deprecated for a while and are actually aliases for function ``cgi.quote`` has been deprecated in favor of ``html.quote`` with secure default values. -Module type - pure Python -Deprecated in - 3.8 (originally proposed for 2.0 by :pep:`206`) -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** - cgitb ~~~~~ @@ -535,16 +371,6 @@ The ``cgitb`` module is not used by any major Python web framework (Django, Pyramid, Plone, Flask, CherryPy, or Bottle). Only Paste uses it in an optional debugging middleware. -Module type - pure Python -Deprecated in - 3.8 (originally proposed for 2.0 by :pep:`206`) -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** smtpd ~~~~~ @@ -554,16 +380,6 @@ a simple implementation of a SMTP mail server. The module documentation marks the module as deprecated and recommends ``aiosmtpd`` instead. The deprecation message was added in releases 3.4.7, 3.5.4, and 3.6.1. -Module type - pure Python -Deprecated in - **3.4.7**, **3.5.4**, **3.6.1** -To be removed in - 3.10 -Has a designated expert - yes -Substitute - aiosmtpd nntplib ~~~~~~~ @@ -584,16 +400,6 @@ external news server. The servers are sometimes unavailable, too slow, or do not work correctly over IPv6. The situation causes flaky test runs on buildbots. -Module type - pure Python -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** telnetlib ~~~~~~~~~ @@ -601,16 +407,6 @@ telnetlib The `telnetlib `_ module provides a Telnet class that implements the Telnet protocol. -Module type - pure Python -Deprecated in - 3.8 -To be removed in - 3.10 -Substitute - telnetlib3_, - Exscript_ - Operating system interface -------------------------- @@ -638,20 +434,6 @@ quality and insecure. Users are discouraged to use them. password modification operations must go through PAM (pluggable authentication module), see `spwd`_ deprecation. -Module type - C extension + Python module -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - yes, but expert is currently inactive. -Substitute - `legacycrypt `_ (ctypes wrapper), - `bcrypt `_, - `passlib `_, - `argon2cffi `_, - hashlib module (PBKDF2, scrypt) macpath ~~~~~~~ @@ -660,16 +442,6 @@ The `macpath `_ module provides Mac OS 9 implementation of ``os.path`` routines. Mac OS 9 is no longer supported. -Module type - pure Python -Deprecated in - 3.7 -Removed in - 3.8 -Has a designated expert - n/a -Substitute - **none** nis ~~~ @@ -681,16 +453,6 @@ designed successor NIS+ from 1992 never took off. For a long time, libc's Name Service Switch, LDAP, and Kerberos/GSSAPI are considered a more powerful and more secure replacement of NIS. -Module type - C extension -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** spwd ~~~~ @@ -710,17 +472,6 @@ Functions like ``getspnam(3)`` access the ``/etc/shadow`` file directly. This is dangerous and even forbidden for confined services on systems with a security engine like SELinux or AppArmor. -Module type - C extension -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - `python-pam `_, - `simpleplam `_ Misc modules ------------ @@ -731,16 +482,6 @@ formatter The `formatter `_ module is an old text formatting module which has been deprecated since Python 3.4. -Module type - pure Python -Deprecated in - 3.4 -To be removed in - 3.10 -Has a designated expert - no -Substitute - *n/a* imp ~~~ @@ -751,16 +492,6 @@ predecessor of the functions have been deprecated since Python 3.3 and the module since Python 3.4. -Module type - C extension -Deprecated in - 3.4 -To be removed in - 3.10 -Has a designated expert - yes, experts have deprecated the module -Substitute - importlib msilib ~~~~~~ @@ -775,47 +506,6 @@ Windows installer, too. Microsoft is slowly moving away from MSI in favor of Windows 10 Apps (AppX) as new deployment model [3]_. -Module type - C extension + Python code -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - **none** - -parser -~~~~~~ - -The `parser `_ module provides -an interface to Python’s internal parser and bytecode compiler. The stdlib -has superior ways to interact with the parse tree. From Python 2.5 onward, -it's much more convenient to cut in at the Abstract Syntax Tree (AST) -generation and compilation stage. - -The ``parser`` module causes additional work. It's C code that must be -kept in sync with any change to Python's grammar and internal parser. -Pablo wants to remove the parser module and promote lib2to3's pgen2 instead -[6]_. - -Most importantly the presence of the ``parser`` module makes it harder to -switch to something more powerful than a LL(1) parser [7]_. Since the -``parser`` module is documented as deprecated since Python 2.5 and a new -parsing technology is planned for 3.9, the ``parser`` module is scheduled for -removal in 3.9. - -Module type - C extension -Deprecated in - 3.8, documented as deprecated since **2.5** -To be removed in - **3.9** -Has a designated expert - yes, experts have deprecated the module. -Substitute - ast, lib2to3.pgen2 pipes ~~~~~ @@ -825,16 +515,6 @@ helpers to pipe the input of one command into the output of another command. The module is built on top of ``os.popen``. Users are encouraged to use the subprocess module instead. -Module type - pure Python -Deprecated in - 3.8 -To be removed in - 3.10 -Has a designated expert - no -Substitute - subprocess module Removed modules =============== @@ -848,17 +528,6 @@ It also required a configure flag that caused an ABI incompatibility. The module was removed in 3.7 by Nathaniel J. Smith in `bpo-29137 `_. -Module type - C extension + CAPI -Deprecated in - 3.7 -Removed in - 3.7 -Has a designated expert - n/a -Substitute - **none** - Modules to keep =============== @@ -892,15 +561,6 @@ The PyPI packages ``colormath``, ``colour``, and ``colorspacious`` provide more advanced features. The Pillow library is better suited to transform images between color systems. -Module type - pure Python -Has a designated expert - no -Substitute - `colormath `_, - `colour `_ - `colorspacious `_, - `Pillow `_ fileinput --------- @@ -913,10 +573,6 @@ can be implemented with the ``argparser`` module. Several core developers expressed their interest to keep the module in the standard library, as it is handy for quick scripts. -Module type - pure Python -Has a designated expert - no lib2to3 ------- @@ -927,10 +583,6 @@ the ``2to3`` command to transpile Python 2 code to Python 3 code. The package is useful for other tasks besides porting code from Python 2 to 3. For example, `Black`_ uses it for code reformatting. -Module type - pure Python -Has a designated expert - no getopt ------ @@ -942,12 +594,6 @@ Although users are encouraged to use ``argparse`` instead, the ``getopt`` module still widely used. The module is small, simple, and handy for C developers to write simple Python scripts. -Module type - pure Python -Has a designated expert - no -Substitute - argparse optparse -------- @@ -958,14 +604,6 @@ the predecessor of the ``argparse`` module. Although it has been deprecated for many years, it's still too widely used to remove it. -Module type - pure Python -Deprecated in - 3.2 -Has a designated expert - yes -Substitute - argparse wave ---- @@ -984,42 +622,6 @@ module. To remove ``wave``'s dependency on ``audioop``, the byte swap function could be either be moved to another module (e.g. ``operator``) or the ``array`` module could gain support for 24-bit (3-byte) arrays. -Module type - pure Python (depends on *byteswap* from `audioop`_ C extension) -Has a designated expert - no - - -Future maintenance of removed modules -===================================== - -The main goal of the PEP is to reduce the burden and workload on the Python -core developer team. Therefore, removed modules will not be maintained by -the core team as separate PyPI packages. However the removed code, tests and -documentation may be moved into a new Git repository, so community members -have a place from which they can pick up and fork code. - -A first draft of a `legacylib `_ -repository is available on my private GitHub account. The modules could be -made available on PyPI. The Python core team will not publish or maintain -the packages. It is my hope that members of the Python community will -adopt, maintain, and perhaps improve the deprecated modules. - -It's my hope that some of the deprecated modules will be picked up and -adopted by users that actually care about them. For example, ``colorsys`` and -``imghdr`` are useful modules, but have limited feature set. A fork of -``imghdr`` can add new features and support for more image formats, without -being constrained by Python's release cycle. - -Most of the modules are in pure Python and can be easily packaged. Some -depend on a simple C module, e.g. `audioop`_ and `crypt`_. Since `audioop`_ -does not depend on any external libraries, it can be shipped as binary -wheels with some effort. Other C modules can be replaced with ``ctypes`` or ``cffi``. -For example, I created `legacycrypt`_, which provides a full implementation of -``crypt``. It is implemented on top of a ctypes wrapper around ``libxcrypt`` -and ``libcrypt`` instead of a C extension like the original ``_crypt`` -module. - Discussions =========== @@ -1045,13 +647,29 @@ Discussions stdlib doesn't have a replacement for the servers, yet. +Rejected Ideas +============== + +Creating/maintaining a separate repo for the deprecated modules +--------------------------------------------------------------- + +It was previously proposed to create a separate repository containing the +deprecated modules packaged for installation. One of the PEP authors went so far +as to create a `demo repository `_ . In the +end, though, it was decided that the added workload to create and maintain such +a repo officially wasn't justified, as the source code will continue to be +available in the CPython repository for people to vendor as necessary. Similar +work has also not been done when previous modules were deprecated and removed, +and it seemingly wasn't an undue burden on the community. + + Update history ============== Update 1 -------- -* Deprecate `parser`_ module +* Deprecate parser module * Keep `fileinput`_ module * Elaborate why ``crypt`` and ``spwd`` are dangerous and bad * Improve sections for `cgitb`_, `colorsys`_, `nntplib`_, and `smtpd`_ modules @@ -1079,6 +697,11 @@ Update 3 * Keep the legacy email API modules. Internal deprecations will be handled separately. +Update 4 +-------- +* Add Brett as a co-author. +* Retarget the PEP for Python 3.11. + References ========== @@ -1096,7 +719,8 @@ References Copyright ========= -This document has been placed in the public domain. +This document is placed in the public domain or under the +CC0-1.0-Universal license, whichever is more permissive.