Как заставить описание PyPi Markdown работать?

Я загрузил пакет в PyPi, используя:

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

Я пытаюсь изменить описание, я написал (пожалуйста, не редактируйте форматирование следующего фрагмента кода, я сделал это специально, чтобы продемонстрировать мою проблему):

**my plugin**

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

Однако текст отображается как есть, без форматирования уценки. Что я делаю не так?


person Maroun    schedule 04.11.2014    source источник


Ответы (6)


По состоянию на 16 марта 2018 года PyPI.org, также известный как Warehouse (наконец-то), поддерживает Markdown в длинных описаниях. Warehouse заменила старую устаревшую реализацию PyPI в апреле 2018 года.

Тебе следует:

  • Убедитесь, что setuptools обновлен до версии 38.6.0 или новее.

  • Убедитесь, что twine обновлен до версии 1.11.0 или новее.

  • Убедитесь, что wheel обновлен до версии 0.31.0 или новее.

  • Добавьте новое поле с именем long_description_content_type к вызову setup() и установите для него значение 'text/markdown':

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

    См. PEP 566 — Метаданные для программных пакетов Python. 2.1.

  • Используйте twine для загрузки ваших дистрибутивов в PyPI:

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

Старая устаревшая инфраструктура PyPI не будет отображать Markdown, это делает только новая инфраструктура Warehouse. Устаревшая инфраструктура исчезла (по состоянию на 30 апреля 2018 г.).

В настоящее время PyPI использует cmarkgfm в качестве средства визуализации уценки через файл readme_rendererбиблиотека (используя readme_renderer.markdown.render(long_description) для создания HTML-вывода). Это означает, что ваши документы уценки будут отображаться точно так же, как на GitHub; это по сути тот же рендерер.

Вы можете проверить пакет long_description с помощью команды twine check (twine 1.12.0 или новее).

Старый ответ ‹ 2018-03-16 следует ниже.


Примечание: это старый, ныне устаревший ответ, по состоянию на 16 марта 2018 г. Markdown поддерживается при условии, что вы используете правильные инструменты, см. выше.

PyPI не поддерживает Markdown, поэтому ваш файл README не будет преобразован в HTML.

Если вам нужен визуализированный README, придерживайтесь reStructuredText; Введение Sphinx в reStructuredText является хорошей отправной точкой.

Возможно, вы захотите установить пакет docutils, чтобы можно было протестировать документ локально; вы хотите запустить включенный скрипт rst2html.py в свой README, чтобы увидеть, какие ошибки возникают, если они есть. В вашем конкретном образце слишком много ошибок:

$ 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.

В вашем блоке кода используются расширения Github Markdown, которые совершенно не подходят для reStructuredText. Вы можете использовать блок кода reST (возможно, если версия docutils для PyPI достаточно новая):

.. code-block:: python

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

Чтобы проверить это локально, вам также необходимо установить Pygments.

Существует запрос функции с запросом на включение, чтобы добавить поддержку Markdown, если вы интересно.

person Martijn Pieters    schedule 04.11.2014

Как заявил @Martijn Pieters, PyPi не поддерживает Markdown. Не знаю, где я научился следующему трюку, но вы можете использовать Pandoc и PyPandoc для преобразования файлов Markdown в RestructuredText перед загрузкой в ​​PyPi. Для этого добавьте в файл setup.py следующее:

try:
    import pypandoc
    long_description = pypandoc.convert('README.md', 'rst')
except(IOError, ImportError):
    long_description = open('README.md').read()

setup(
    name='blah',
    version=find_version('blah.py'),
    description='Short description',
    long_description=long_description,
)

Чтобы установить Pandoc в OS X, я использовал Homebrew:

brew install pandoc

Чтобы установить PyPandoc, я использовал pip. :

pip install pypandoc
person Matthew Rankin    schedule 04.11.2014
comment
Побочный вопрос: зачем еще ловить IOError? Разве ImportError не единственное ожидаемое исключение в этом случае? - person Nick Chammas; 09.12.2015
comment
@NickChammas, я могу ошибаться, но ImportError может поймать исключение, когда pypandoc не может быть импортирован, а IOError может поймать возможный случай, когда README.md не может быть открыт или README.rst не может быть записан. - person mre; 29.01.2016
comment
Спасибо за это. Одно примечание: вам нужно включить README.md в качестве файла данных в setup.py (data_files=[('', ['README.md'])]), иначе вы получите RuntimeError из pypandoc при установке с помощью pip. В качестве альтернативы перехват исключений должен быть более общим и вместо этого передавать long_description базовую версию. - person Alastair McCormack; 18.08.2016
comment
OSError возникает, когда pandoc не установлен. Я использую except (IOError, ImportError, OSError): - person utapyngo; 22.12.2017
comment
pypandoc.convert устарел. Используйте pypandoc.convert_file - person giantas; 10.03.2018

PyPI поддерживает сначала, а не уценку, как упоминалось в других ответах. Но вам не нужен pypandoc сам по себе, достаточно pandoc. Вы можете сначала сгенерировать первый файл локально, а затем запустить setup.py для загрузки пакета.

upload.sh:

#!/bin/bash
pandoc --from=markdown --to=rst --output=README README.md
python setup.py sdist upload

Сгенерированный файл с именем README будет автоматически распознан. Обязательно добавьте его в свой .gitignore! setup.py не нужно делать ничего особенного.

setup.py:

from distutils.core import setup

setup(
    name='mypackage',
    packages=['mypackage'],  # this must be the same as the name above
    version='0.2.8',
    description='short',
    author='Chiel ten Brinke',
    author_email='<email>',
    url='<github url>',  # use the URL to the github repo
    keywords=[],  # arbitrary keywords
    classifiers=[],
)

Затем просто запустите bash upload.sh, чтобы загрузить материал в PyPI.

person Chiel ten Brinke    schedule 15.06.2016
comment
В моем случае файл README не был автоматически распознан как long_description. Нужно добавить поле long_description в setup.py. В противном случае файл README не будет отображаться в pypi. - person asmaier; 20.09.2017

У меня были проблемы с символами \r, вызывающими проблемы с разбором, когда в pypi появляется только первая строка README. Приведенный ниже код устраняет проблему, он взят из репозитория модулей pypandoc:

try:
    long_description = pypandoc.convert('README.md', 'rst')
    long_description = long_description.replace("\r","") # Do not forget this line
except OSError:
    print("Pandoc not found. Long_description conversion failure.")
    import io
    # pandoc is not installed, fallback to using raw contents
    with io.open('README.md', encoding="utf-8") as f:
        long_description = f.read()

Таким образом, long_description содержит очищенную версию вашего файла Readme, и вы можете передать его функции setup() в вашем сценарии setup.py.

person Overdrivr    schedule 20.02.2016
comment
Получил отрицательный голос, давно не пробовал, поэтому, если это не сработает, сообщите об этом. - person Overdrivr; 23.04.2017
comment
Работал для меня, большое спасибо! Я потратил часы на устранение неполадок. ... Почему io.open, а не просто open? - person matt wilkie; 06.03.2018
comment
Понижение могло быть связано с тем, что convert_text требует аргумента format=md, а convert_file — нет. Я не уверен, какой механизм использует голый convert. Может быть, определенные ситуации также требуют аргумента. ср. github.com/bebraw/pypandoc/blob/master/README.md# использование - person matt wilkie; 06.03.2018
comment
Эти две функции должны быть новыми дополнениями к pypandoc, потому что их раньше не было. Вы говорите, что этот код с голым convert не работает? - person Overdrivr; 06.03.2018
comment
Голое преобразование у меня не сработало на одной машине, но сработало на другой. Я не исследовал, чтобы увидеть, чем они отличаются друг от друга. - person matt wilkie; 07.03.2018

Вы также можете установить уценку в setup.cfg файле:

[metadata]
...
long_description = file: README.md
long_description_content_type = text/markdown

В качестве примера посмотрите мой проект: на github и на pypi.

person betontalpfa    schedule 23.09.2019
comment
Хотя setup.py может технически быть искусно подстроена для (A) безопасного открытия README.md с помощью менеджера контекста, (B) прочитать содержимое этого файл в локальную переменную и (C) установить для параметра long_description значение этой переменной вне этого контекста, на самом деле никто не должен этого делать. setup.cfg уже реализует это правильно, безопасно и эффективно от вашего имени. Не изобретайте ржавое колесо. Просто используйте setup.cfg, потому что это хорошо. (Это сообщение от вашего дружелюбного упаковщика по соседству.) - person Cecil Curry; 09.04.2020
comment
Примечание: этот ответ ранее смешивал нестандартный ключ description-file, специфичный для pbr (разумность сборки Python) со стандартным ключом long-description-content-type, не специфичным для pbr. С тех пор я отредактировал это ошибочное несоответствие, отдав предпочтение стандартным клавишам long_description и long_description_content_type. Этот ответ теперь ведет себя так, как ожидалось для всех — независимо от того, используете ли вы pbr или нет. Теперь с миром упаковки все в порядке. - person Cecil Curry; 09.04.2020
comment
Работает как шарм! Спасибо, что поделились этим. - person Ricardo Mendes; 09.04.2020

Есть хороший пакет pip, который сработал для меня

https://pypi.python.org/pypi/restructuredtext_lint/

Я использую его в своей настройке сейчас:

https://github.com/pablodav/burp_server_reports/blob/master/setup.py

def check_readme(file='README.rst'):
"""
Checks readme rst file, to ensure it will upload to pypi and be formatted correctly.
:param file:
:return:
"""
errors = rst_lint.lint_file(file)
if errors:
    msg = 'There are errors in {}, errors \n {}'.format(file, errors[0].message)
    raise SystemExit(msg)
else:
    msg = 'No errors in {}'.format(file)
print(msg)

Также я создал библиотеку, которую можно будет использовать в py.test позже.

https://github.com/pablodav/burp_server_reports/blob/master/burp_reports/lib/check_readme.py
person Pablo Daniel Estigarribia Davy    schedule 03.08.2016