[英]How do I make an ubuntu/debian package for a twistd/twisted plugin?
[英]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 install
, pip install --user
和easy_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插件的常用方法是什么? 手动放在这里?
我用这种方法:
.py
'和' .pyc
'版本放入包中的“ twisted/plugins/
”文件夹中。 请注意,'。 .pyc
'文件可以为空,它应该存在。 在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.