【问题标题】:How to make PyPi description Markdown work?如何使 PyPi 描述 Markdown 工作?
【发布时间】:2014-12-31 11:10:40
【问题描述】:

我使用以下方法将一个包上传到 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
```

但是,文本会按原样显示,没有降价格式。我做错了什么?

【问题讨论】:

    标签: python restructuredtext pypi


    【解决方案1】:

    截至 2018 年 3 月 16 日,PyPI.org aka Warehouse(终于)支持长描述的 Markdown。 Warehouse 在 2018 年 4 月替换了旧的旧 PyPI 实施。

    你需要:

    • 确保 setuptools 升级到 38.6.0 或更高版本

    • 确保 twine 升级到 1.11.0 或更高版本

    • 确保 wheel 升级到 0.31.0 或更高版本

    • 在您的setup() 调用中添加一个名为long_description_content_type 的新字段,并将其设置为'text/markdown'

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

      PEP 566 - Metadata for Python Software Packages 2.1

    • 使用twine 将您的分配上传到 PyPI:

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

    旧的旧 PyPI 基础架构不会渲染 Markdown,只有新的 Warehouse 基础架构可以。旧版基础架构现已不复存在(截至 2018 年 4 月 30 日)。

    目前,PyPI 通过readme_renderer library 使用cmarkgfm 作为降价渲染器(使用readme_renderer.markdown.render(long_description) 生成HTML 输出)。这意味着您的降价文档将呈现与 GitHub 上的完全相同;它本质上是相同的渲染器。

    您可以使用twine check commandtwine 1.12.0 或更高版本)验证您的包long_description

    下面是


    注意:这是旧的,现在已经过时的答案,从 2018 年 3 月 16 日起,只要您使用正确的工具,就支持 Markdown,见上文

    PyPI 支持 Markdown,所以你的 README 不会被渲染成 HTML。

    如果你想要一个渲染的 README,坚持使用 reStructuredText; Sphinx introduction to reStructuredText 是一个很好的起点。

    您可能想要安装docutils package,以便在本地测试您的文档;您想在 README 中运行包含的 rst2html.py 脚本,以查看产生了哪些错误(如果有)。您的具体示例有太多错误:

    $ 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

    如果你有兴趣,有一个feature request with pull request 可以添加对 Markdown 的支持。

    【讨论】:

      【解决方案2】:

      正如@Martijn Pieters 所说,PyPi 不支持 Markdown。我不确定我在哪里学到了以下技巧,但您可以使用 PandocPyPandoc 将 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,
      )
      

      为了在 OS X 上安装Pandoc,我使用了Homebrew

      brew install pandoc
      

      为了安装PyPandoc,我使用了pip

      pip install pypandoc
      

      【讨论】:

      • 附带问题:为什么还要捕获IOError?在这种情况下,ImportError 不是唯一的预期异常吗?
      • @NickChammas,我可能错了,但 ImportError 可能会在无法导入 pypandoc 时捕获异常,并且 IOError 可能会捕获 README.md 无法打开或 README.rst 的可能情况写不出来。
      • 谢谢。注意:您需要将README.md 作为数据文件包含在setup.py (data_files=[('', ['README.md'])]) 中,否则在使用pip 安装时,您会从pypandoc 获得RuntimeError。或者,异常捕获应该更通用,并使用基本版本来提供 long_description。
      • OSError 在未安装 pandoc 时引发。我用except (IOError, ImportError, OSError):
      • pypandoc.convert 已被弃用。使用pypandoc.convert_file
      【解决方案3】:

      我遇到了\r 字符的问题,导致解析问题,其中仅 README 的第一行出现在 pypi 中。下面的代码解决了这个问题,它来自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 包含您的自述文件的净化版本,您可以将其传递给setup.py 脚本中的 setup() 函数。

      【讨论】:

      • 被否决了,有一段时间没有尝试过,所以如果这不起作用,请报告
      • 为我工作,非常感谢!我花了几个小时进行故障排除。 ... 为什么io.open 而不仅仅是open
      • 投反对票可能是因为convert_text 需要format=md 参数,而convert_file 不需要。我不确定convert 使用什么机制。也许特殊情况也需要论证。参考文献github.com/bebraw/pypandoc/blob/master/README.md#usage
      • 这两个函数肯定是 pypandoc 的新增功能,因为它们以前不存在。您是说使用裸convert 的代码不起作用吗?
      • Bare convert 在一台机器上对我不起作用,但在另一台机器上起作用。我没有调查两者之间有什么不同。
      【解决方案4】:

      PyPI 支持 rst 而不是其他答案中提到的降价。但是您不需要pypandoc 本身,只需pandoc 就可以了。您可以先在本地生成 rst 文件,然后运行 ​​setup.py 来上传包。

      upload.sh:

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

      将自动识别生成的名为README 的文件。请务必将其添加到您的.gitignoresetup.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。

      【讨论】:

      • 在我的例子中,README 文件没有被自动识别为 long_description。必须将 long_description 字段添加到 setup.py 。否则 README 文件将不会在 pypi 上呈现。
      【解决方案5】:

      有一个很好的 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
      

      【讨论】:

        【解决方案6】:

        你也可以在setup.cfg文件中设置markdown:

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

        以我的项目为例:githubpypi

        【讨论】:

        • 虽然setup.py 可以在技术上巧妙地被陪审团操纵 (A) 使用上下文管理器安全地打开 README.md (B) 将该文件的内容读入一个局部变量,然后 (C)long_description 选项设置为该上下文之外的该变量的值,没有人应该确实这样做。 setup.cfg 已经代表您正确、安全、高效地实现了这一点。不要重新发明生锈的轮子。只需使用setup.cfg,因为它很好。 (这是您友好的邻居打包员发来的消息。
        • 注意: 这个答案之前混合了pbr (Python Build Reasonableness) 特有的非标准description-file 密钥和pbr 特有的标准long-description-content-type 密钥not .我已经通过更喜欢标准的long_descriptionlong_description_content_type 键来编辑错误的差异。这个答案现在对每个人来说都是预期的——不管你是否使用 pbr。包装世界现在一切正常。
        • 像魅力一样工作!感谢分享。
        【解决方案7】:

        我发现这里的其他答案有点复杂且陈旧。我对这一切都很陌生,所以我将使用我理解的工具给出一个答案,并在我的第一次尝试中工作。

        为了让我的 github 页面 readme.md 文件显示在我的 PyPi 页面上,我在我的 setup.py 文件中执行了以下两个步骤。

        1。在我的setup.py 文件顶部包含以下内容

        from pathlib import Path
        this_directory = Path(__file__).parent
        long_description = (this_directory / "readme.md").read_text()
        

        这些步骤直接将 Markdown 文件中的数据读入 long_description 变量。

        2。在setup()函数中输入以下参数

        long_description = long_description
        long_description_content_type="text/markdown"
        

        这会将 Markdown 文件中的数据插入到 long_description,然后告诉 setup() 它是什么类型的数据(markdown)。

        正如我所说,上述两个步骤在我第一次尝试时效果很好,没有任何麻烦或复杂性。非常适合我的小脑袋。 :)

        注意此代码改编自:
        https://packaging.python.org/guides/making-a-pypi-friendly-readme/

        【讨论】:

          猜你喜欢
          • 2020-08-18
          • 1970-01-01
          • 2011-10-28
          • 2023-03-09
          • 1970-01-01
          • 2020-03-10
          • 2018-04-04
          • 2018-06-08
          相关资源
          最近更新 更多