我的第一个 README 没有在 pypi.python.org 上格式化

Posted

技术标签:

【中文标题】我的第一个 README 没有在 pypi.python.org 上格式化【英文标题】:My rst README is not formatted on pypi.python.org 【发布时间】:2013-04-28 09:07:15 【问题描述】:

当我将我的包提交到 Python 包索引 (https://pypi.python.org/pypi) 时,我的 README 文件(使用有效的 reStructuredText 编写并保存为 README.rst)显示为没有任何格式的纯文本。

我已经通过验证器(rstctl 和collective.checkdocs)运行它,没有返回任何错误。

我的包裹在: https://pypi.python.org/pypi/lcinvestor

它在 github 中: https://github.com/jgillick/LendingClubAutoInvestor

【问题讨论】:

【参考方案1】:

编辑:您可以使用以下内容来查找 RST 中将显示在 PyPI 上的错误:

twine check

您需要twine 1.12.0 或更高版本。如果您没有它,您可以使用以下方式安装或更新它:

pip install --upgrade twine

Source


不推荐使用的答案:

python setup.py check --restructuredtext

Source

【讨论】:

对我来说,这仅在 pip install readme 之后有效。但是,它显示了其他检查器没有发现的问题。 这似乎已被弃用:warning: Check: This command has been deprecated. Use `twine check` instead: https://packaging.python.org/guides/making-a-pypi-friendly-readme#validating-restructuredtext-markup 并将我们推荐给packaging.python.org/guides/making-a-pypi-friendly-readme/… twine check 需要一个或多个构建分发文件形式的参数。如果生成的分发文件可以正确显示,那么预先检查当然不是很有用。 (为我的一个 C 扩展构建这些分发文件需要一个多小时,如果你运行 twine check dist/* 并发现你可以重新开始,那就浪费了)【参考方案2】:

我在将我的 python 模块上传到 pypi 时遇到了同样的问题。

后来我使用 rst-lint 检查了 README.rst 是否有错误,这表明我的自述文件是正确的。

我发现问题不在于 README 文件,而在于 setup.py 本身。

在编写 Readme 和 setup.py 时遵循以下几点

请勿编写多行 Python 字符串用于描述或摘要或任何进入 setup() 参数的内容。 不要在 README 文件中使用相对链接。(如 ./path1/path2)。 使用 rst-lint 等检查工具确保 rst 语法正确。 如果您有 Markdown 文件,您可以使用 pandoc 轻松将其转换为重组文本

【讨论】:

在我的情况下,它确实是一个用于描述的多行字符串(甚至不是 long_description!)。疯狂...您的回答节省了我的时间,谢谢!【参考方案3】:

您可以使用collective.checkdocs 包来检测无效结构:

pip install collective.checkdocs python setup.py checkdocs

然后您可以使用以下 python 函数来过滤 sphinx-only 结构(可能需要添加更多正则表达式以匹配您的内容):

#!/usr/bin/python3
"""
Cleans-up Sphinx-only constructs (ie from README.rst),
so that *PyPi* can format it properly.

To check for remaining errors, install ``sphinx`` and run::

        python setup.py --long-description | sed -file 'this_file.sed' | rst2html.py  --halt=warning

"""

import re
import sys, io


def yield_sphinx_only_markup(lines):
    """
    :param file_inp:     a `filename` or ``sys.stdin``?
    :param file_out:     a `filename` or ``sys.stdout`?`

    """
    substs = [
        ## Selected Sphinx-only Roles.
        #
        (r':abbr:`([^`]+)`',        r'\1'),
        (r':ref:`([^`]+)`',         r'`\1`_'),
        (r':term:`([^`]+)`',        r'**\1**'),
        (r':dfn:`([^`]+)`',         r'**\1**'),
        (r':(samp|guilabel|menuselection):`([^`]+)`',        r'``\2``'),


        ## Sphinx-only roles:
        #        :foo:`bar`   --> foo(``bar``)
        #        :a:foo:`bar` XXX afoo(``bar``)
        #
        #(r'(:(\w+))?:(\w+):`([^`]*)`', r'\2\3(``\4``)'),
        (r':(\w+):`([^`]*)`', r'\1(``\2``)'),


        ## Sphinx-only Directives.
        #
        (r'\.\. doctest',           r'code-block'),
        (r'\.\. plot::',            r'.. '),
        (r'\.\. seealso',           r'info'),
        (r'\.\. glossary',          r'rubric'),
        (r'\.\. figure::',          r'.. '),


        ## Other
        #
        (r'\|version\|',              r'x.x.x'),
    ]

    regex_subs = [ (re.compile(regex, re.IGNORECASE), sub) for (regex, sub) in substs ]

    def clean_line(line):
        try:
            for (regex, sub) in regex_subs:
                line = regex.sub(sub, line)
        except Exception as ex:
            print("ERROR: %s, (line(%s)"%(regex, sub))
            raise ex

        return line

    for line in lines:
        yield clean_line(line)

和/或在您的setup.py 文件中,使用类似这样的内容::

def read_text_lines(fname):
    with io.open(os.path.join(mydir, fname)) as fd:
        return fd.readlines()

readme_lines = read_text_lines('README.rst')
long_desc = ''.join(yield_sphinx_only_markup(readme_lines)),

或者,您可以将sed unix-utility 与此文件一起使用:

## Sed-file to clean-up README.rst from Sphinx-only constructs,
##   so that *PyPi* can format it properly.
##   To check for remaining errors, install ``sphinx`` and run:
##
##          sed -f "this_file.txt" README.rst | rst2html.py  --halt=warning
##

## Selected Sphinx-only Roles.
#
s/:abbr:`\([^`]*\)`/\1/gi
s/:ref:`\([^`]*\)`/`\1`_/gi
s/:term:`\([^`]*\)`/**\1**/gi
s/:dfn:`\([^`]*\)`/**\1**/gi
s/:\(samp\|guilabel\|menuselection\):`\([^`]*\)`/``\1``/gi


## Sphinx-only roles:
#        :foo:`bar` --> foo(``bar``)
#
s/:\([a-z]*\):`\([^`]*\)`/\1(``\2``)/gi


## Sphinx-only Directives.
#
s/\.\. +doctest/code-block/i
s/\.\. +plot/raw/i
s/\.\. +seealso/info/i
s/\.\. +glossary/rubric/i
s/\.\. +figure::/../i


## Other
#
s/|version|/x.x.x/gi

【讨论】:

checkdocs 的好提示,当python setup.py check --restructuredtext 没有发现任何错误时,发现了破坏我的自述文件的错误 如果没有 setup.py 就很难使用:from setuptools import Distribution; from collective.checkdocs import checkdocs; checkdocs(Distribution(dict(long_description=open("README.rst").read()))).run()【参考方案4】:

事实证明,@sigmavirus 关于链接的答案很接近。我在 distutils 邮件列表上创建了一个discussion,发现 pypi reStructuredText 解析器不允许页内链接(即#minimum-cash),这将使整个文档无效。

似乎 pypi 使用白名单来过滤链接协议(http vs ftp vs gopher),并将“#”视为无效协议。看起来这很容易解决他们的问题,但在那之前,我将删除我的页内锚链接。

【讨论】:

PyPI 的 reStructuredText 渲染器也会阻塞相关链接,即使它们不是锚点。我不得不用完整路径(以https:// 开始)切换我的相对链接,但它现在可以工作了。 github.com/chbrown/filesequence/commit/… 您可以使用我上面的过滤代码来消除我所知道的 PyPi 的所有无效结构。【参考方案5】:

首先出现在我面前的是(快速浏览后),在您的“高级过滤器”部分中,您在链接后使用了两个下划线,例如,

`Link text <http://example.com>`__

应该在哪里

`Link text <http://example.com>`_

奇怪的是,reStructuredText 检查器没有发现这一点。如果你也安装了 docutils,你可以运行rst2html.py README.rst,它应该会打印出 HTML。如果有错误,它将失败并告诉您错误在哪里。

另外,公平的警告,列表不应该有前导空格,也就是说,你有

 - foo
 - bar

代替

- foo
- bar

(为了让视觉更清晰)

- foo # correct
 - one too many for a regular list, it will show up as a quoted list

另外,相对链接不像Text to link &lt;#link&gt;_那样工作。如果您想链接到单独的部分,您必须执行以下操作:

Here's my `link <section_name>`_ to the other section.

.. Other stuff here ...

.. _section_name:

Min/Max Investment Opportunities and Other Foo Biz Baz
------------------------------------------------------

【讨论】:

以上是关于我的第一个 README 没有在 pypi.python.org 上格式化的主要内容,如果未能解决你的问题,请参考以下文章

Selenium开发环境搭建

python的第二天

怎么写一个超棒的 README 文档

怎么写一个超棒的 README 文档

从 Vuepress 中排除 readme.md

Python-模块