26 votes

Comment puis-je écrire un setup.py pour un twistd/torsadée plugin qui fonctionne avec setuptools, distribuer, etc?

Le Tordu Système de Plugin est le moyen préféré pour écrire extensible tordu applications.

Toutefois, en raison de la façon dont le système de plugin est structuré (plugins aller dans un tordu/plugins ce qui devrait pas être un paquet Python), rédaction d'un bon setup.py pour l'installation de ces plugins, semble être non négligeable.

J'ai vu quelques tentatives ajouter " tordues.plugins' de 'paquets' clé de la distutils commande du programme d'installation, mais comme il n'est pas vraiment un paquet, les mauvaises choses se produisent (par exemple, un __init__.py il est utile ajouté par certains outils).

D'autres tentatives semblent utiliser 'package_data" à la place (par exemple, http://bazaar.launchpad.net/~glyph/divmod.org/trunk/view/head:/Epsilon/epsilon/setuphelper.py), mais qui peut aussi ne pas de moyens détournés.

La question est: quelqu'un a réussi à graver un setup.py pour l'installation d'tordu de plugins qui fonctionne dans tous les cas?

17voto

Ivan Kozik Points 386

Par la prévention de pip à partir de l'écriture de la ligne "twisted" à l' .egg-info/top_level.txt, vous pouvez continuer à l'utiliser packages=[..., 'twisted.plugins'] , et disposer d'un pip uninstall qui permet de ne pas supprimer tous twisted/. Cela implique monkeypatching setuptools/distribuer près du haut de votre setup.py. Voici un exemple d' 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))

J'ai testé avec pip install, pip install --user, et easy_install. Avec n'importe quelle installation, la méthode ci-dessus monkeypatch et pip uninstall fonctionner correctement.

Vous pourriez vous demander: ai-je besoin pour effacer le monkeypatch pour éviter la pagaille jusqu'à l'installation? (par exemple, pip install --no-deps MyPackage Twisted; vous ne voulez pas affecter Tordu de l' top_level.txt.) La réponse est non; la monkeypatch n'a pas d'incidence sur une autre installation, car pip engendre un nouveau python pour chaque installation.

Connexes: gardez à l'esprit que, dans votre projet, vous devez pas avoir un fichier twisted/plugins/__init__.py. Si vous voyez cet avertissement lors de l'installation:

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

il est tout à fait normal et vous devriez pas essayer de régler le problème en ajoutant un __init__.py.

3voto

Zooko Points 742

Voici une entrée de blog qui décrit le faire avec 'package_data':

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

Dans quelle étrange façons peut qu'échouer? Elle peut échouer si l'installation du paquet n'a pas mis le paquet de données dans un répertoire qui est sur le sys.chemin d'accès. Dans ce cas, le Tordu chargeur de plugin ne serait pas à le trouver. Cependant, toutes les installations de paquets Python, que je sache, va le mettre dans le même répertoire que celui où ils sont installer les modules Python ou les paquets eux-mêmes, de sorte que ne sera pas un problème.

2voto

Éric Araujo Points 4212

Peut-être que vous pourriez adapter l'package_data idée d'utiliser data_files au lieu de cela: il ne nécessite pas de liste tordu.plugins, car il utilise des chemins absolus. Il serait encore une bidouille, si.

Mes tests avec de la pure distutils ont m'a dit que cela est possible de remplacer des fichiers à partir d'une autre distribution. Je voulais tester le pauvre homme de l'espace de noms de packages à l'aide de pkgutil.extend_path et distutils, et il s'avère que je peux installer spam/ham/__init__.py avec spam.ham/setup.py et spam/eggs/__init__.py avec spam.eggs/setup.py. Les répertoires ne sont pas un problème, mais les fichiers seront heureux écrasé. Je pense que c'est effectivement un comportement indéfini dans distutils qui ruisselle jusqu'à setuptools et pip, donc pip pourrait OMI près wontfix.

Quelle est la manière habituelle pour installer Tordu plugins? Chute-il-ici par la main?

1voto

Alex Fedorov Points 119

J'utilise cette approche:

  1. Put '.py"et".pyc"versions de votre fichier "twisted/plugins/" le dossier à l'intérieur de votre colis. Notez que '.pyc' fichier peut être vide, il devrait juste exister.
  2. En setup.py spécifiez copier les deux fichiers dans un dossier de la bibliothèque (assurez-vous que vous n'écrase pas les plugins existants!). Par exemple:

    # 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
    )
    

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X