如何编写一个setup.py用于与setuptools,分发等一起使用的扭曲/扭曲插件?

Sid*_*nei 26 python distutils twisted setuptools distribute

所述扭曲扩展系统 是写扩展的扭曲应用的首选方式.

但是,由于插件系统的结构方式(插件进入一个应该是Python包的twisted/plugins目录),编写适当的setup.py来安装这些插件似乎并非易事.

我已经看到一些尝试将'twisted.plugins'添加到distutils setup命令的'packages'键,但由于它不是真正的包,所以会发生不好的事情(例如,__init__.py某些工具有助于添加).

其他尝试似乎使用'package_data'(例如,http://bazaar.launchpad.net/~glyph/divmod.org/trunk/view/head: /Epsilon/epsilon/setuphelper.py),但这也可能失败以奇怪的方式.

问题是:有没有人成功编写过setup.py来安装扭曲的插件,它适用于所有情况?

Iva*_*zik 17

我记录下面的setup.py,只有当用户的pip <1.2时才需要(例如在Ubuntu 12.04上).如果每个人都有1.2或更新,你唯一需要的是packages=[..., 'twisted.plugins'].

通过阻止pip将行" twisted"写入.egg-info/top_level.txt,你可以继续使用packages=[..., 'twisted.plugins']并拥有一个pip uninstall不会删除全部的工作twisted/.这涉及monkeypatching setuptools /分布在你的顶部附近setup.py.这是一个示例setup.py:

from distutils.core import setup

# When pip installs anything from packages, py_modules, or ext_modules that
# includes a twistd plugin (which are installed to twisted/plugins/),
# setuptools/distribute writes a Package.egg-info/top_level.txt that includes
# "twisted".  If you later uninstall Package with `pip uninstall Package`,
# pip <1.2 removes all of twisted/ instead of just Package's twistd plugins.
# See https://github.com/pypa/pip/issues/355 (now fixed)
#
# To work around this problem, we monkeypatch
# setuptools.command.egg_info.write_toplevel_names to not write the line
# "twisted".  This fixes the behavior of `pip uninstall Package`.  Note that
# even with this workaround, `pip uninstall Package` still correctly uninstalls
# Package's twistd plugins from twisted/plugins/, since pip also uses
# Package.egg-info/installed-files.txt to determine what to uninstall,
# and the paths to the plugin files are indeed listed in installed-files.txt.
try:
    from setuptools.command import egg_info
    egg_info.write_toplevel_names
except (ImportError, AttributeError):
    pass
else:
    def _top_level_package(name):
        return name.split('.', 1)[0]

    def _hacked_write_toplevel_names(cmd, basename, filename):
        pkgs = dict.fromkeys(
            [_top_level_package(k)
                for k in cmd.distribution.iter_distribution_names()
                if _top_level_package(k) != "twisted"
            ]
        )
        cmd.write_file("top-level names", filename, '\n'.join(pkgs) + '\n')

    egg_info.write_toplevel_names = _hacked_write_toplevel_names

setup(
    name='MyPackage',
    version='1.0',
    description="You can do anything with MyPackage, anything at all.",
    url="http://example.com/",
    author="John Doe",
    author_email="jdoe@example.com",
    packages=['mypackage', 'twisted.plugins'],
    # You may want more options here, including install_requires=,
    # package_data=, and classifiers=
)

# Make Twisted regenerate the dropin.cache, if possible.  This is necessary
# because in a site-wide install, dropin.cache cannot be rewritten by
# normal users.
try:
    from twisted.plugin import IPlugin, getPlugins
except ImportError:
    pass
else:
    list(getPlugins(IPlugin))
Run Code Online (Sandbox Code Playgroud)

我已经测试了这个pip install,pip install --usereasy_install.使用任何安装方法,上面的monkeypatch和pip uninstall工作正常.

您可能想知道:我是否需要清除monkeypatch以避免搞乱下一次安装?(例如pip install --no-deps MyPackage Twisted;你不想影响Twisted的top_level.txt.)答案是否定的; monkeypatch不影响另一个安装,因为每次安装都会pip生成一个新python的安装.

相关:请记住,在项目中,您不能拥有文件 twisted/plugins/__init__.py.如果在安装过程中看到此警告:

package init file 'twisted/plugins/__init__.py' not found (or not a regular file)
Run Code Online (Sandbox Code Playgroud)

这是完全正常的,你应该不会尝试通过添加修复它__init__.py.

  • 更新了dropin.cache再生 (2认同)

Zoo*_*oko 3

这是一篇博客文章,描述了如何使用“package_data”进行此操作:

http://chrismiles.livejournal.com/23399.html

会以什么奇怪的方式失败?如果包的安装未将包数据放入 sys.path 上的目录中,则可能会失败。在这种情况下,Twisted 插件加载器将找不到它。但是,据我所知,所有 Python 包的安装都会将其放入安装 Python 模块或包本身的同一目录中,因此这不会成为问题。

  • 像这样使用 package_data 的问题之一是你仍然需要在包列表中列出 `'twisted.plugins'` ;这会导致“pip uninstall”破坏您的整个 Twisted 安装。 (3认同)