Skip to content

Unable to execute str(importlib.metadata.metadata("x'x'x")) #148944

@Jesse205

Description

@Jesse205

Bug report

Bug description:

Unable to parse the metadata of many packages that have a Description field.

Packages I tested: pyright, pytest, pyyaml, requests, ruff, urllib3, poethepoet. Among them, pyright, pytest,pyinstaller, and pyyaml are problematic.

pyright
>>> import importlib.metadata
>>> importlib.metadata.metadata("pyright")
<importlib.metadata._adapters.Message object at 0x000005DBF8597690>
>>> str(importlib.metadata.metadata("pyright"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    str(importlib.metadata.metadata("pyright"))
    ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\message.py", line 171, in __str__
    return self.as_string()
           ~~~~~~~~~~~~~~^^
  File "C:\Program Files\Python314\Lib\email\message.py", line 194, in as_string
    g.flatten(self, unixfrom=unixfrom)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 118, in flatten
    self._write(msg)
    ~~~~~~~~~~~^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 201, in _write
    self._write_headers(msg)
    ~~~~~~~~~~~~~~~~~~~^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 228, in _write_headers
    folded = self.policy.fold(h, v)
  File "C:\Program Files\Python314\Lib\email\_policybase.py", line 344, in fold
    return self._fold(name, value, sanitize=True)
           ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\_policybase.py", line 387, in _fold
    parts.append(h.encode(linesep=self.linesep, maxlinelen=maxlinelen))
                 ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\header.py", line 394, in encode
    raise HeaderParseError("header value appears to contain "
        "an embedded header: {!r}".format(value))
email.errors.HeaderParseError: header value appears to contain an embedded header: '# Pyright for Python\n[![Downloads](https://pepy.tech/badge/pyright)](https://pepy.tech/project/pyright)\n![PyPI](https://img.shields.io/pypi/v/pyright)\n![Supported python versions](https://img.shields.io/pypi/pyversions/pyright)\n> This project is not affiliated with Microsoft in any way, shape, or form\nPyright for Python is a Python command-line wrapper over [pyright](https://github.com/microsoft/pyright), a static type checker for Python.\n## Installation\nUse the package manager [pip](https://pip.pypa.io/en/stable/) to install pyright.\n```bash\npip install pyright\n```\n> [!TIP]\n> It\'s highly recommended to install `pyright` with the `nodejs` extra which uses [`nodejs-wheel`](https://pypi.org/project/nodejs-wheel-binaries/) to\n> download Node.js binaries as it is more reliable than the default [`nodeenv`](https://pypi.org/project/nodeenv/) solution.\n>\n> ```bash\n> pip install pyright[nodejs]\n> ```\n## Usage\nPyright can be invoked using two different methods\n```bash\npyright --help\n```\nor\n```bash\npython3 -m pyright --help\n```\nPyright for Python should work exactly the same as pyright does, see the [pyright documentation](https://github.com/microsoft/pyright/blob/main/docs/getting-started.md) for details on how to make use of pyright.\n### Pre-commit\nYou can also setup pyright to run automatically before each commit by setting up [pre-commit](https://pre-commit.com) and registering pyright in your `.pre-commit-config.yaml` file\n```yaml\nrepos:\n  - repo: https://github.com/RobertCraigie/pyright-python\n    rev: v1.1.409\n    hooks:\n    - id: pyright\n```\nPre-commit will install pyright-python in its own virtual environment which can cause pyright to not be able to detect your installed dependencies.\nTo fix this you can either [tell pre-commit](https://pre-commit.com/#config-additional_dependencies) to also install those dependencies or explicitly tell pyright which virtual environment to use by updating your [pyright configuration file](https://github.com/microsoft/pyright/blob/main/docs/configuration.md):\n```toml\n[tool.pyright]\n# ...\nvenvPath = "."\nvenv = ".venv"\n```\n## Motivation\n[Pyright](https://github.com/microsoft/pyright) is written in TypeScript, requiring node to be installed, and is normally installed with npm. This could be an entry barrier for some Python developers as they may not have node or npm installed on their machine; I wanted to make pyright as easy to install as any normal Python package.\n## How Pyright for Python Works\nThis project works by first checking if node is in the `PATH`. If it is not, then we download node at runtime using [nodeenv](https://github.com/ekalinin/nodeenv), then install the pyright npm package using `npm` and finally, run the downloaded JS with `node`.\n## Automatically keeping pyright up to date\nBy default Pyright for Python is set to target a specific pyright version and new releases will be automatically created whenever a new pyright version is released. It is highly recommended to use an automatic dependency update tool such as [dependabot](https://docs.github.com/en/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/configuring-dependabot-security-updates).\nIf you would rather not have to update your installation every time a new pyright release is created then you can automatically use the latest available pyright version by setting the environment variable `PYRIGHT_PYTHON_FORCE_VERSION` to `latest`.\n## Configuration\nYou can configure Pyright for Python using environment variables.\n### Debugging\nSet `PYRIGHT_PYTHON_DEBUG` to any value.\n### Modify Pyright Version\nSet `PYRIGHT_PYTHON_FORCE_VERSION` to the desired version, e.g. `1.1.156`, `latest`\n### Keeping Pyright and Pylance in sync\nSet `PYRIGHT_PYTHON_PYLANCE_VERSION` to your Pylance version, e.g. `2023.11.11`, `latest-release`, `latest-prerelease`. The corresponding Pyright version will be used. See [Pylance\'s changelog](https://github.com/microsoft/pylance-release/blob/main/CHANGELOG.md) for details on recent releases. Note that `PYRIGHT_PYTHON_FORCE_VERSION` takes precedence over `PYRIGHT_PYTHON_PYLANCE_VERSION`, so you\'ll want to set one or the other, not both.\n### Show NPM logs\nBy default, Pyright for Python disables npm error messages, if you want to display the npm error messages then set `PYRIGHT_PYTHON_VERBOSE` to any truthy value.\n### Modify NPM Package Location\nPyright for Python will resolve the root cache directory by checking the following environment variables, in order:\n- `PYRIGHT_PYTHON_CACHE_DIR`\n- `XDG_CACHE_HOME`\nIf neither of them are set it defaults to `~/.cache`\n### Force Node Env\nSet `PYRIGHT_PYTHON_GLOBAL_NODE` to any non-truthy value, i.e. anything apart from 1, t, on, or true.\ne.g. `off`\nYou can optionally choose the version of node used by setting `PYRIGHT_PYTHON_NODE_VERSION` to the desired version\n### Modify Node Env Location\nSet `PYRIGHT_PYTHON_ENV_DIR` to a valid [nodeenv](https://github.com/ekalinin/nodeenv) directory. e.g. `~/.cache/nodeenv`\n### Ignore Warnings\nSet `PYRIGHT_PYTHON_IGNORE_WARNINGS` to a truthy value, e.g. 1, t, on, or true.\nPyright for Python will print warnings for the following case(s)\n- There is a new Pyright version available.\n## Contributing\nAll pull requests are welcome.\n## License\n[MIT](https://choosealicense.com/licenses/mit/)'
>>> 
pytest
>>> str(importlib.metadata.metadata("pytest")) 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    str(importlib.metadata.metadata("pytest"))
    ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\message.py", line 171, in __str__
    return self.as_string()
           ~~~~~~~~~~~~~~^^
  File "C:\Program Files\Python314\Lib\email\message.py", line 194, in as_string
    g.flatten(self, unixfrom=unixfrom)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 118, in flatten
    self._write(msg)
    ~~~~~~~~~~~^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 201, in _write
    self._write_headers(msg)
    ~~~~~~~~~~~~~~~~~~~^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 235, in _write_headers
    raise HeaderWriteError(
        f'folded header contains newline: {folded!r}')
email.errors.HeaderWriteError: folded header contains newline: "Description: .. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg\n   :target: https://docs.pytest.org/en/stable/\n   :align: center\n   :height: 200\n   :alt: pytest\n------\n.. image:: https://img.shields.io/pypi/v/pytest.svg\n    :target: https://pypi.org/project/pytest/\n.. image:: https://img.shields.io/conda/vn/conda-forge/pytest.svg\n    :target: https://anaconda.org/conda-forge/pytest\n.. image:: https://img.shields.io/pypi/pyversions/pytest.svg\n    :target: https://pypi.org/project/pytest/\n.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg\n    :target: https://codecov.io/gh/pytest-dev/pytest\n    :alt: Code coverage Status\n.. image:: https://github.com/pytest-dev/pytest/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest\n.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg\n   :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main\n   :alt: pre-commit.ci status\n.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg\n    :target: https://www.codetriage.com/pytest-dev/pytest\n.. image:: https://readthedocs.org/projects/pytest/badge/?version=latest\n    :target: https://pytest.readthedocs.io/en/latest/?badge=latest\n    :alt: Documentation Status\n.. image:: https://img.shields.io/badge/Discord-pytest--dev-blue\n    :target: https://discord.com/invite/pytest-dev\n    :alt: Discord\n.. image:: https://img.shields.io/badge/Libera%20chat-%23pytest-orange\n    :target: https://web.libera.chat/#pytest\n    :alt: Libera chat\nThe ``pytest`` framework makes it easy to write small tests, yet\nscales to support complex functional testing for applications and libraries.\nAn example of a simple test:\n.. code-block:: python\n    # content of test_sample.py\n    def inc(x):\n        return x + 1\n    def test_answer():\n        assert inc(3) == 5\nTo execute it::\n    $ pytest\n    ============================= test session starts =============================\n    collected 1 items\n    test_sample.py F\n    ================================== FAILURES ===================================\n    _________________________________ test_answer _________________________________\n        def test_answer():\n    >       assert inc(3) == 5\n    E       assert 4 == 5\n    E        +  where 4 = inc(3)\n    test_sample.py:5: AssertionError\n    ========================== 1 failed in 0.04 seconds ===========================\nThanks to ``pytest``'s detailed assertion introspection, you can simply use plain ``assert`` statements. See `getting-started <https://docs.pytest.org/en/stable/getting-started.html#our-first-test-run>`_ for more examples.\nFeatures\n--------\n- Detailed info on failing `assert statements <https://docs.pytest.org/en/stable/how-to/assert.html>`_ (no need to remember ``self.assert*`` names)\n- `Auto-discovery\n  <https://docs.pytest.org/en/stable/explanation/goodpractices.html#python-test-discovery>`_\n  of test modules and functions\n- `Modular fixtures <https://docs.pytest.org/en/stable/explanation/fixtures.html>`_ for\n  managing small or parametrized long-lived test resources\n- Can run `unittest <https://docs.pytest.org/en/stable/how-to/unittest.html>`_ (or trial)\n  test suites out of the box\n- Python 3.10+ or PyPy3\n- Rich plugin architecture, with over 1300+ `external plugins <https://docs.pytest.org/en/latest/reference/plugin_list.html>`_ and thriving community\nDocumentation\n-------------\nFor full documentation, including installation, tutorials and PDF documents, please see https://docs.pytest.org/en/stable/.\nBugs/Requests\n-------------\nPlease use the `GitHub issue tracker <https://github.com/pytest-dev/pytest/issues>`_ to submit bugs or request features.\nChangelog\n---------\nConsult the `Changelog <https://docs.pytest.org/en/stable/changelog.html>`__ page for fixes and enhancements of each version.\nSupport pytest\n--------------\n`Open Collective`_ is an online funding platform for open and transparent communities.\nIt provides tools to raise money and share your finances in full transparency.\nIt is the platform of choice for individuals and companies that want to make one-time or\nmonthly donations directly to the project.\nSee more details in the `pytest collective`_.\n.. _Open Collective: https://opencollective.com\n.. _pytest collective: https://opencollective.com/pytest\npytest for enterprise\n---------------------\nAvailable as part of the Tidelift Subscription.\nThe maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and\nmaintenance for the open source dependencies you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.\n`Learn more. <https://tidelift.com/subscription/pkg/pypi-pytest?utm_source=pypi-pytest&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`_\nSecurity\n^^^^^^^^\npytest has never been associated with a security vulnerability, but in any case, to report a\nsecurity vulnerability please use the `Tidelift security contact <https://tidelift.com/security>`_.\nTidelift will coordinate the fix and disclosure.\nLicense\n-------\nCopyright Holger Krekel and others, 2004.\nDistributed under the terms of the `MIT`_ license, pytest is free and open source software.\n.. _`MIT`: https://github.com/pytest-dev/pytest/blob/main/LICENSE\n"
>>> 
pyyaml
>>> str(importlib.metadata.metadata("pyyaml"))  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    str(importlib.metadata.metadata("pyyaml"))
    ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\message.py", line 171, in __str__
    return self.as_string()
           ~~~~~~~~~~~~~~^^
  File "C:\Program Files\Python314\Lib\email\message.py", line 194, in as_string
    g.flatten(self, unixfrom=unixfrom)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 118, in flatten
    self._write(msg)
    ~~~~~~~~~~~^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 201, in _write
    self._write_headers(msg)
    ~~~~~~~~~~~~~~~~~~~^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 235, in _write_headers
    raise HeaderWriteError(
        f'folded header contains newline: {folded!r}')
email.errors.HeaderWriteError: folded header contains newline: 'Description: YAML is a data serialization format designed for human readability\nand interaction with scripting languages.  PyYAML is a YAML parser\nand emitter for Python.\nPyYAML features a complete YAML 1.1 parser, Unicode support, pickle\nsupport, capable extension API, and sensible error messages.  PyYAML\nsupports standard YAML tags and provides Python-specific tags that\nallow to represent an arbitrary Python object.\nPyYAML is applicable for a broad range of tasks from complex\nconfiguration files to object serialization and persistence.\n'
>>> 
pyinstaller
>>> str(importlib.metadata.metadata("pyinstaller"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    str(importlib.metadata.metadata("pyinstaller"))
    ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\message.py", line 171, in __str__
    return self.as_string()
           ~~~~~~~~~~~~~~^^
  File "C:\Program Files\Python314\Lib\email\message.py", line 194, in as_string
    g.flatten(self, unixfrom=unixfrom)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 118, in flatten
    self._write(msg)
    ~~~~~~~~~~~^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 201, in _write
    self._write_headers(msg)
    ~~~~~~~~~~~~~~~~~~~^^^^^
  File "C:\Program Files\Python314\Lib\email\generator.py", line 228, in _write_headers
    folded = self.policy.fold(h, v)
  File "C:\Program Files\Python314\Lib\email\_policybase.py", line 344, in fold
    return self._fold(name, value, sanitize=True)
           ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\_policybase.py", line 387, in _fold
    parts.append(h.encode(linesep=self.linesep, maxlinelen=maxlinelen))
                 ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python314\Lib\email\header.py", line 394, in encode
    raise HeaderParseError("header value appears to contain "
        "an embedded header: {!r}".format(value))
email.errors.HeaderParseError: header value appears to contain an embedded header: "PyInstaller Overview\n====================\n.. image:: https://img.shields.io/pypi/v/pyinstaller\n   :alt: PyPI\n   :target: https://pypi.org/project/pyinstaller\n.. image:: https://img.shields.io/pypi/pyversions/pyinstaller\n   :alt: PyPI - Python Version\n   :target: https://pypi.org/project/pyinstaller\n.. image:: https://img.shields.io/readthedocs/pyinstaller/stable\n   :alt: Read the Docs (version)\n   :target: https://pyinstaller.org\n.. image:: https://img.shields.io/pypi/dm/pyinstaller\n   :alt: PyPI - Downloads\n   :target: https://pypistats.org/packages/pyinstaller\nPyInstaller bundles a Python application and all its dependencies into a single\npackage. The user can run the packaged app without installing a Python\ninterpreter or any modules.\n:Documentation: https://pyinstaller.org/\n:Code:          https://github.com/pyinstaller/pyinstaller\nPyInstaller reads a Python script written by you. It analyzes your code\nto discover every other module and library your script needs in order to\nexecute. Then it collects copies of all those files -- including the active\nPython interpreter! -- and puts them with your script in a single folder, or\noptionally in a single executable file.\nPyInstaller is tested against Windows, macOS, and GNU/Linux.\nHowever, it is not a cross-compiler:\nto make a Windows app you run PyInstaller in Windows; to make\na GNU/Linux app you run it in GNU/Linux, etc.\nPyInstaller has been used successfully\nwith AIX, Solaris, FreeBSD and OpenBSD,\nbut is not tested against them as part of the continuous integration tests.\nMain Advantages\n---------------\n- Works out-of-the-box with any Python version 3.8-3.14.\n- Fully multi-platform, and uses the OS support to load the dynamic libraries,\n  thus ensuring full compatibility.\n- Correctly bundles the major Python packages such as numpy, PyQt5,\n  PySide2, PyQt6, PySide6, wxPython, matplotlib and others out-of-the-box.\n- Compatible with many third-party packages out-of-the-box. (All the required\n  tricks to make external packages work are already integrated.)\n- Works with code signing on macOS.\n- Bundles MS Visual C++ DLLs on Windows.\nInstallation\n------------\nPyInstaller is available on PyPI. You can install it through `pip`:\n.. code:: bash\n      pip install pyinstaller\nRequirements and Tested Platforms\n---------------------------------\n- Python:\n    - 3.8-3.14. Note that Python 3.10.0 contains a bug making it unsupportable by\n      PyInstaller. PyInstaller will also not work with beta releases of Python\n      3.15.\n- Windows (32-bit/64-bit/ARM64):\n    - PyInstaller should work on Windows 7 or newer, but we only officially support Windows 8+.\n    - Support for Python installed from the Windows Store without using virtual\n      environments requires PyInstaller 4.4 or later.\n- Linux:\n    - GNU libc based distributions on architectures ``x86_64``, ``aarch64``,\n      ``i686``, ``ppc64le``, ``s390x``.\n    - musl libc based distributions on architectures ``x86_64``, ``aarch64``.\n    - ldd: Console application to print the shared libraries required\n      by each program or shared library. This typically can be found in\n      the distribution package `glibc` or `libc-bin`.\n    - objdump: Console application to display information from\n      object files. This typically can be found in the\n      distribution package `binutils`.\n    - objcopy: Console application to copy and translate object files.\n      This typically can be found in the distribution package `binutils`,\n      too.\n    - Raspberry Pi users on ``armv5``-``armv7`` should `add piwheels as an extra\n      index URL <https://www.piwheels.org/>`_ then ``pip install pyinstaller``\n      as usual.\n- macOS (``x86_64`` or ``arm64``):\n    - macOS 10.15 (Catalina) or newer.\n    - Supports building ``universal2`` applications provided that your installation\n      of Python and all your dependencies are also compiled ``universal2``.\nUsage\n-----\nBasic usage is very simple - just run it against your main script:\n.. code:: bash\n      pyinstaller /path/to/yourscript.py\nFor more details, see the `manual`_.\nUntested Platforms\n------------------\nThe following platforms have been contributed, and any feedback or\nenhancements on these are welcome.\n- FreeBSD\n    - ldd\n- Solaris\n    - ldd\n    - objdump\n- AIX\n    - AIX 6.1 or newer. PyInstaller will not work with statically\n      linked Python libraries.\n    - ldd\n- Linux on any other libc implementation/architecture combination not listed\n  above.\nBefore using any contributed platform, you need to build the PyInstaller\nbootloader. This will happen automatically when you ``pip install pyinstaller``\nprovided that you have an appropriate C compiler (typically\neither ``gcc`` or ``clang``) and zlib's development headers already installed.\nSupport\n-------\n- Official debugging guide: https://pyinstaller.org/en/v6.20.0/when-things-go-wrong.html\n- Assorted user contributed help topics: https://github.com/pyinstaller/pyinstaller/wiki\n- Web based Q&A forums: https://github.com/pyinstaller/pyinstaller/discussions\n- Email based Q&A forums: https://groups.google.com/g/pyinstaller\nChanges in this Release\n-----------------------\nYou can find a detailed list of changes in this release\nin the `Changelog`_ section of the manual.\n.. _`manual`: https://pyinstaller.org/en/v6.20.0/\n.. _`Changelog`: https://pyinstaller.org/en/v6.20.0/CHANGES.html"
>>> 

CPython versions tested on:

3.14

Operating systems tested on:

Windows

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13bugs and security fixes3.14bugs and security fixespendingThe issue will be closed if no feedback is providedstdlibStandard Library Python modules in the Lib/ directorytopic-importlibtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions