How to make PyPi description Markdown work?

Maroun picture Maroun · Nov 4, 2014 · Viewed 13.3k times · Source

I uploaded a package to PyPi using:

python setup.py register -r pypi
python setup.py sdist upload -r pypi

I'm trying to modify the description, I wrote (please don't edit the formatting of the following piece of code, I made it on purpose to demonstrate my problem):

**my plugin**

This plugin enables you to ... For example:
```python
@attr(section='MySection', id=1)
def test_function(self):
    """
    Bla bla bla
    """
    pass
```

However, the text appears as it is, without the markdown formatting. What am I doing wrong?

Answer

Martijn Pieters picture Martijn Pieters · Nov 4, 2014

As of March 16, 2018, PyPI.org aka Warehouse (finally) supports Markdown in long descriptions. Warehouse replaced the old legacy PyPI implementation in April 2018.

You need to:

  • Make sure setuptools is upgraded to version 38.6.0 or newer

  • Make sure twine is upgraded to version 1.11.0 or newer

  • Make sure wheel is upgraded to version 0.31.0 or newer

  • Add a new field named long_description_content_type to your setup() call, and set it to 'text/markdown':

    setup(
        long_description="""# Markdown supported!\n\n* Cheer\n* Celebrate\n""",
        long_description_content_type='text/markdown',
        # ....
    )
    

    See PEP 566 - Metadata for Python Software Packages 2.1.

  • Use twine to upload your distributions to PyPI:

    $ python setup.py sdist bdist_wheel   # adjust as needed
    $ twine upload dist/*
    

The old legacy PyPI infrastructure would not render Markdown, only the new Warehouse infrastructure does. The legacy infrastructure is now gone (as of 2018-04-30).

Currently, PyPI uses cmarkgfm as the markdown renderer, via the readme_renderer library (using readme_renderer.markdown.render(long_description) to produce HTML output). This means that your markdown documents will render exactly the same as on GitHub; it is essentially the same renderer.

You can validate your package long_description with the twine check command (twine 1.12.0 or newer).

The old < 2018-03-16 answer follows below.


Note: this is the old, now outdated answer, as of 2018-03-16 Markdown is supported provided you use the right tools, see above.

PyPI does not support Markdown, so your README will not be rendered into HTML.

If you want a rendered README, stick with reStructuredText; the Sphinx introduction to reStructuredText is a good starting point.

You probably want to install the docutils package so you can test your document locally; you want to run the included rst2html.py script on your README to see what errors are produced, if any. Your specific sample has too many errors:

$ bin/rst2html.py test.rst  > /tmp/test.html
test.rst:7: (ERROR/3) Unexpected indentation.
test.rst:3: (WARNING/2) Inline literal start-string without end-string.
test.rst:3: (WARNING/2) Inline interpreted text or phrase reference start-string without end-string.
test.rst:11: (WARNING/2) Block quote ends without a blank line; unexpected unindent.
test.rst:11: (WARNING/2) Inline literal start-string without end-string.
test.rst:11: (WARNING/2) Inline interpreted text or phrase reference start-string without end-string.

Your code block is using Github's Markdown extensions, which are entirely wrong for reStructuredText. You could use a reST code block (probably, if the PyPI version of docutils is new enough):

.. code-block:: python

    @attr(section='MySection', type='functional+', module='MyModule', id=1)
    def test_function(self):
        """
        This is the original docstring
        """
        pass

To test this locally you'll need to install Pygments as well.

There is a feature request with pull request to add support for Markdown, if you are interested.