繁体   English   中英

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

[英]How do I write a setup.py for a twistd/twisted plugin that works with setuptools, distribute, etc?

Twisted Plugin System是编写可扩展扭曲应用程序的首选方法。

但是,由于插件系统的结构方式(插件进入一个应该是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来安装扭曲的插件,它适用于所有情况?

我记录下面的setup.py,只有当用户的pip <1.2时才需要(例如在Ubuntu 12.04上)。 如果每个人都有1.2或更新的pip,你唯一需要的是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))

我用pip installpip 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)

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

这是一篇博客文章,描述了使用'package_data'进行的操作:

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

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

也许您可以调整package_data的想法来改为使用data_files:它不需要您将twisted.plugins列为包,因为它使用绝对路径。 不过,它仍然是一个kludge。

我对纯distutils的测试告诉我,它可以覆盖另一个发行版的文件。 我想使用pkgutil.extend_path和distutils测试穷人的命名空间包,结果发现我可以使用spam.eggs安装spam.ham / setup.py和spam/eggs/__init__.py spam/ham/__init__.py init__.py /setup.py。 目录不是问题,但文件将被愉快地覆盖。 我认为这实际上是在distutils中的未定义行为,这些行为涓涓细流到setuptools和pip,所以pip可以IMO关闭为wontfix。

安装Twisted插件的常用方法是什么? 手动放在这里?

我用这种方法:

  1. 将文件的' .py '和' .pyc '版本放入包中的“ twisted/plugins/ ”文件夹中。 请注意,'。 .pyc '文件可以为空,它应该存在。
  2. setup.py指定将两个文件复制到库文件夹(确保不会覆盖现有插件!)。 例如:

     # setup.py from distutils import sysconfig LIB_PATH = sysconfig.get_python_lib() # ... plugin_name = '<your_package>/twisted/plugins/<plugin_name>' # '.pyc' extension is necessary for correct plugins removing data_files = [ (os.path.join(LIB_PATH, 'twisted', 'plugins'), [''.join((plugin_name, extension)) for extension in ('.py', '.pyc')]) ] setup( # ... data_files=data_files ) 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM