簡體   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