Как написать setup.py для twistd / twisted plugin, который работает с setuptools, распространяет и т. Д.?

Система Twisted Plugin является предпочтительным способом записи расширяемых скрученных приложений.

Однако из-за того, как структурирована система плагинов (плагины входят в каталог с скрученными / плагинами, который не должен быть пакетом Python), запись правильного файла setup.py для установки этих плагинов представляется нетривиальным.

Я видел некоторые попытки добавить «twisted.plugins» в «пакетный» ключ команды настройки distutils, но поскольку это не действительно пакет, происходят плохие вещи (например, __init__.py удобно добавляется некоторыми инструменты).

Другие попытки, похоже, используют вместо этого «package_data» (например, http://bazaar.launchpad.net/~glyph/divmod.org/trunk/view/head:/Epsilon/epsilon/setuphelper.py ), но это также может быть неудачно странными способами.

Вопрос в том, кто-нибудь успешно написал setup.py для установки витых плагинов, которые работают во всех случаях?

4 Solutions collect form web for “Как написать setup.py для twistd / twisted plugin, который работает с setuptools, распространяет и т. Д.?”

Я документирую setup.py ниже, что необходимо, только если у вас есть пользователи с pip <1.2 (например, на Ubuntu 12.04). Если у каждого есть pip 1.2 или новее, вам нужно только packages=[..., 'twisted.plugins'] .

Не позволяя pip писать строку « twisted » в .egg-info/top_level.txt , вы можете продолжать использовать packages=[..., 'twisted.plugins'] и иметь 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 , вы не хотели бы влиять на top_level.txt 's 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/ham/__init__.py со спамом.ham / setup.py и spam/eggs/__init__.py со спамом.eggs /setup.py. Каталоги не являются проблемой, но файлы будут перезаписаны. Я думаю, что на самом деле это неопределенное поведение в distutils, которое стекает до setuptools и pip, поэтому pip может закрыть IMO как wontfix.

Каков обычный способ установки Twisted plugins? Брось-сюда-сюда вручную?

Я использую такой подход:

  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 ) 
  • Переопределить класс Autobahn / Twisted WebsocketClientProtocol
  • ImportError с cx_Freeze и pyinstaller
  • Как получить IP-адрес клиента после того, как соединение потеряно в скрученном
  • Twisted Python + spawnProcess. Получение вывода из команды
  • Клиентская библиотека Python Jabber / XMPP для Twisted
  • Базовая сеть с Pygame
  • Trial unittests с использованием Autobahn WebSocket
  • pauseProducing () в Twisted гарантирует, что больше вызовов для dataReceived ()?
  • Python - лучший язык программирования в мире.