26

ツイスト プラグイン システム は、拡張可能なツイスト アプリケーションを作成するための推奨される方法です。

ただし、プラグイン システムの構造 (プラグインは Python パッケージであってはならないtwisted/plugins ディレクトリに入る) のせいで、これらのプラグインをインストールするための適切な setup.py を書くことは簡単ではないようです。

distutils setup コマンドの 'packages' キーに 'twisted.plugins' を追加しようとする試みをいくつか見てきましたが、これは実際にはパッケージではないため、悪いことが起こります (たとえば、__init__.pyいくつかのツールによって an が便利に追加されます)。

他の試みでは代わりに「package_data」を使用しているように見えますが (例: http://bazaar.launchpad.net/~glyph/divmod.org/trunk/view/head:/Epsilon/epsilon/setuphelper.py )、それも失敗する可能性があります奇妙な方法で。

問題は、ねじれたプラグインをインストールするための setup.py を正常に作成して、すべての場合に機能する人はいますか?

4

4 に答える 4

17

pip < 1.2 (Ubuntu 12.04 など) のユーザーがいる場合にのみ必要な setup.py を以下に文書化します。誰もが pip 1.2 以降を持っている場合、必要なのはpackages=[..., 'twisted.plugins'].

pip が行 " twisted" を.egg-info/top_level.txtに書き込まないようにすることで、 を引き続き使用し、すべてを削除しないpackages=[..., 'twisted.plugins']作業を行うことができます。これには、ファイルの上部近くで setuptools/distribute にモンキーパッチを適用することが含まれます。ここにサンプルがあります:pip uninstalltwisted/setup.pysetup.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 --user、および でこれをテストしましたeasy_install。どのインストール方法でも、上記の monkeypatch と正常にpip uninstall動作します。

次のインストールを台無しにしないために、monkeypatch をクリアする必要があるのでしょうか? (例えばpip install --no-deps MyPackage Twisted; Twisted の に影響を与えたくないでしょうtop_level.txt。) 答えはノーです。モンキーパッチは、インストールごとpipに新しいパッチを生成するため、別のインストールには影響しません。python

関連: あなたのプロジェクトには file があってはならない twisted/plugins/__init__.pyことに注意してください。インストール中にこの警告が表示された場合:

package init file 'twisted/plugins/__init__.py' not found (or not a regular file)

これは完全に正常な動作であり__init__.py.

于 2011-09-23T06:34:42.507 に答える
3

「package_data」でそれを行うことを説明するブログエントリは次のとおりです。

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

それはどのような奇妙な方法で失敗する可能性がありますか? パッケージのインストールでパッケージ データが sys.path 上のディレクトリに配置されない場合、失敗する可能性があります。その場合、Twisted プラグイン ローダーはそれを見つけられません。ただし、私が知っている Python パッケージのすべてのインストールは、Python モジュールまたはパッケージ自体をインストールしているのと同じディレクトリに配置されるため、問題にはなりません。

于 2011-09-01T21:15:50.603 に答える
2

おそらく、代わりに data_files を使用するように package_data のアイデアを適応させることができます: 絶対パスを使用するため、twisted.plugins をパッケージとしてリストする必要はありません。しかし、それはまだクラッジでしょう。

純粋な distutils を使用したテストでは、別のディストリビューションのファイルを上書きできることがわかりました。pkgutil.extend_path と distutils を使用して貧乏人の名前空間パッケージをテストしたかったのですがspam/ham/__init__.py、spam.ham/setup.py と spam.eggs/setup.py でインストールできることがわかりspam/eggs/__init__.pyました。ディレクトリは問題ありませんが、ファイルは問題なく上書きされます。これは実際には distutils で定義されていない動作であり、setuptools と pip までトリクルアップするため、pip は IMO を wntfix として閉じることができます。

Twisted プラグインをインストールする通常の方法は何ですか? ここに手でドロップしますか?

于 2011-09-21T15:43:15.913 に答える
1

私はこのアプローチを使用します:

  1. ファイルの ' ' バージョンと ' ' バージョンをパッケージ内の " ".pyフォルダーに入れます。' ' ファイルは空でも構いませんが、存在する必要があります。.pyctwisted/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
    )
    
于 2013-11-28T13:06:10.643 に答える