Skip to content

Commit

Permalink
Merge extras-3696-6: Support setuptools extras for optional dependenc…
Browse files Browse the repository at this point in the history
…ies.

Author: herrwolfe

Reviewer: glyph, thijs

Fixes: twisted#3696

Optional dependencies can be installed using the extra_requires facility
provided by setuptools.

git-svn-id: svn://svn.twistedmatrix.com/svn/Twisted/trunk@43808 bbbe8e31-12d6-0310-92fd-ac37d47ddeeb
  • Loading branch information
glyph committed Feb 2, 2015
1 parent f51be6c commit 4804eff
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Contents:
:maxdepth: 2
:includehidden:

installation/index
core/index
conch/index
lore/index
Expand Down
63 changes: 63 additions & 0 deletions docs/installation/howto/optional.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@

:LastChangedDate: $LastChangedDate$
:LastChangedRevision: $LastChangedRevision$
:LastChangedBy: $LastChangedBy$

Installing Optional Dependencies
================================

This document describes the optional dependencies that Twisted supports.
The dependencies are python packages that Twisted's developers have found useful either for developing Twisted itself or for developing Twisted applications.

The intended audience of this document is someone who is familiar with installing optional dependencies using `pip`_.

If you are unfamiliar with the installation of optional dependencies, the `python packaging tutorial`_ can show you how.
For a deeper explanation of what optional dependencies are and how they are declared, please see the `setuptools documentation`_.

The following optional dependencies are supported:

* **dev** - packages that aid in the development of Twisted itself.
* `TwistedChecker`_
* `pyflakes`_
* `twisted-dev-tools`_
* `python-subunit`_
* `Sphinx`_
* `pydoctor`_

* **tls** - packages that are needed to work with TLS.
* `pyOpenSSL`_
* `service_identity`_

* **conch** - packages for working with conch/SSH.
* `gmpy`_
* `pyasn1`_
* `pycrypto`_

* **soap** - the `SOAPpy`_ package to work with SOAP.

* **serial** - the `pyserial`_ package to work with serial data.

* **all_non_platform** - installs **tls**, **conch**, **soap**, and **serial** options.

* **osx_platform** - **all_non_platform** options and `pyobjc`_ to work with Objective-C apis.

* **windows_platform** - **all_non_platform** options and `pypiwin32`_ to work with Windows's apis.

.. _pip: https://pip.pypa.io/en/latest/quickstart.html
.. _TwistedChecker: https://pypi.python.org/pypi/TwistedChecker
.. _pyflakes: https://pypi.python.org/pypi/pyflakes
.. _twisted-dev-tools: https://pypi.python.org/pypi/twisted-dev-tools
.. _python-subunit: https://pypi.python.org/pypi/python-subunit
.. _Sphinx: https://pypi.python.org/pypi/Sphinx/1.3b1
.. _pydoctor: https://pypi.python.org/pypi/pydoctor
.. _pyOpenSSL: https://pypi.python.org/pypi/pyOpenSSL
.. _service_identity: https://pypi.python.org/pypi/service_identity
.. _gmpy: https://pypi.python.org/pypi/gmpy/1.17
.. _pyasn1: https://pypi.python.org/pypi/pyasn1
.. _pycrypto: https://pypi.python.org/pypi/pycrypto
.. _SOAPpy: https://pypi.python.org/pypi/SOAPpy
.. _pyserial: https://pypi.python.org/pypi/pyserial
.. _pyobjc: https://pypi.python.org/pypi/pyobjc
.. _pypiwin32: https://pypi.python.org/pypi/pypiwin32
.. _`setuptools documentation`: https://pythonhosted.org/setuptools/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies
.. _`python packaging tutorial`: https://packaging.python.org/en/latest/installing.html#examples
14 changes: 14 additions & 0 deletions docs/installation/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

:LastChangedDate: $LastChangedDate$
:LastChangedRevision: $LastChangedRevision$
:LastChangedBy: $LastChangedBy$

Installing Twisted
==================

.. toctree::
:hidden:

howto/optional

- :doc:`Installing Optional Dependencies <howto/optional>`: documentation on how to install Twisted's optional dependencies.
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@ def main(args):

from twisted.python.dist import (
STATIC_PACKAGE_METADATA, getDataFiles, getExtensions, getAllScripts,
getPackages, setup)
getPackages, setup, _EXTRAS_REQUIRE)

scripts = getAllScripts()

setup_args.update(dict(
packages=getPackages('twisted'),
conditionalExtensions=getExtensions(),
scripts=scripts,
extras_require=_EXTRAS_REQUIRE,
data_files=getDataFiles('twisted'),
**STATIC_PACKAGE_METADATA))

Expand Down
55 changes: 55 additions & 0 deletions twisted/python/dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@
Don't use this outside of Twisted.
Maintainer: Christopher Armstrong
@var _EXTRA_OPTIONS: These are the actual package names and versions that will
be used by C{extras_require}. This is not passed to setup directly so that
combinations of the packages can be created without the need to copy
package names multiple times.
@var _EXTRAS_REQUIRE: C{extras_require} is a dictionary of items that can be
passed to setup.py to install optional dependencies. For example, to
install the optional dev dependencies one would type::
pip install -e ".[dev]"
This has been supported by setuptools since 0.5a4.
@var _PLATFORM_INDEPENDENT: A list of all optional cross-platform dependencies,
as setuptools version specifiers, used to populate L{_EXTRAS_REQUIRE}.
"""

from distutils.command import build_scripts, install_data, build_ext
Expand Down Expand Up @@ -49,6 +65,45 @@
"news", "pair", "runner", "web",
"words"]

_EXTRA_OPTIONS = dict(
dev=['twistedchecker >= 0.2.0',
'pyflakes >= 0.8.1',
'twisted-dev-tools >= 0.0.2',
'python-subunit',
'sphinx >= 1.2.2',
'pydoctor >= 0.5'],
tls=['pyopenssl >= 0.11',
'service_identity'],
conch=['gmpy',
'pyasn1',
'pycrypto'],
soap=['soappy'],
serial=['pyserial'],
osx=['pyobjc'],
windows=['pypiwin32']
)

_PLATFORM_INDEPENDENT = (
_EXTRA_OPTIONS['tls'] +
_EXTRA_OPTIONS['conch'] +
_EXTRA_OPTIONS['soap'] +
_EXTRA_OPTIONS['serial']
)

_EXTRAS_REQUIRE = {
'dev': _EXTRA_OPTIONS['dev'],
'tls': _EXTRA_OPTIONS['tls'],
'conch': _EXTRA_OPTIONS['conch'],
'soap': _EXTRA_OPTIONS['soap'],
'serial': _EXTRA_OPTIONS['serial'],
'all_non_platform': _PLATFORM_INDEPENDENT,
'osx_platform': (
_EXTRA_OPTIONS['osx'] + _PLATFORM_INDEPENDENT
),
'windows_platform': (
_EXTRA_OPTIONS['windows'] + _PLATFORM_INDEPENDENT
),
}


class ConditionalExtension(Extension):
Expand Down
150 changes: 148 additions & 2 deletions twisted/python/test/test_dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
import os
import sys

from distutils.core import Distribution

from setuptools.dist import Distribution

from twisted.trial.unittest import TestCase

from twisted.python import dist
from twisted.python.dist import (get_setup_args, ConditionalExtension,
build_scripts_twisted)
build_scripts_twisted, _EXTRAS_REQUIRE)
from twisted.python.filepath import FilePath


Expand Down Expand Up @@ -59,6 +60,151 @@ def test_win32Definition(self):



class OptionalDependenciesTests(TestCase):
"""
Tests for L{_EXTRAS_REQUIRE}
"""

def test_distributeTakesExtrasRequire(self):
"""
Setuptools' Distribution object parses and stores its C{extras_require}
argument as an attribute.
"""
extras = dict(im_an_extra_dependency="thing")
attrs = dict(extras_require=extras)
distribution = Distribution(attrs)
self.assertEqual(
extras,
distribution.extras_require
)


def test_extrasRequireDictContainsKeys(self):
"""
L{_EXTRAS_REQUIRE} contains options for all documented extras: C{dev},
C{tls}, C{conch}, C{soap}, C{serial}, C{all_non_platform},
C{osx_platform}, and C{windows_platform}.
"""
self.assertIn('dev', _EXTRAS_REQUIRE)
self.assertIn('tls', _EXTRAS_REQUIRE)
self.assertIn('conch', _EXTRAS_REQUIRE)
self.assertIn('soap', _EXTRAS_REQUIRE)
self.assertIn('serial', _EXTRAS_REQUIRE)
self.assertIn('all_non_platform', _EXTRAS_REQUIRE)
self.assertIn('osx_platform', _EXTRAS_REQUIRE)
self.assertIn('windows_platform', _EXTRAS_REQUIRE)


def test_extrasRequiresDevDeps(self):
"""
L{_EXTRAS_REQUIRE}'s C{dev} extra contains setuptools requirements for
the tools required for Twisted development.
"""
deps = _EXTRAS_REQUIRE['dev']
self.assertIn('twistedchecker >= 0.2.0', deps)
self.assertIn('pyflakes >= 0.8.1', deps)
self.assertIn('twisted-dev-tools >= 0.0.2', deps)
self.assertIn('python-subunit', deps)
self.assertIn('sphinx >= 1.2.2', deps)
self.assertIn('pydoctor >= 0.5', deps)


def test_extrasRequiresTlsDeps(self):
"""
L{_EXTRAS_REQUIRE}'s C{tls} extra contains setuptools requirements for
the packages required to make Twisted's transport layer security fully
work for both clients and servers.
"""
deps = _EXTRAS_REQUIRE['tls']
self.assertIn('pyopenssl >= 0.11', deps)
self.assertIn('service_identity', deps)


def test_extrasRequiresConchDeps(self):
"""
L{_EXTRAS_REQUIRE}'s C{conch} extra contains setuptools requirements
for the packages required to make Twisted Conch's secure shell server
work.
"""
deps = _EXTRAS_REQUIRE['conch']
self.assertIn('gmpy', deps)
self.assertIn('pyasn1', deps)
self.assertIn('pycrypto', deps)


def test_extrasRequiresSoapDeps(self):
"""
L{_EXTRAS_REQUIRE}' C{soap} extra contains setuptools requirements for
the packages required to make the C{twisted.web.soap} module function.
"""
self.assertIn(
'soappy',
_EXTRAS_REQUIRE['soap']
)


def test_extrasRequiresSerialDeps(self):
"""
L{_EXTRAS_REQUIRE}'s C{serial} extra contains setuptools requirements
for the packages required to make Twisted's serial support work.
"""
self.assertIn(
'pyserial',
_EXTRAS_REQUIRE['serial']
)


def test_extrasRequiresAllNonPlatformDeps(self):
"""
L{_EXTRAS_REQUIRE}'s C{all_non_platform} extra contains setuptools
requirements for all of Twisted's optional dependencies which work on
all supported operating systems.
"""
deps = _EXTRAS_REQUIRE['all_non_platform']
self.assertIn('pyopenssl >= 0.11', deps)
self.assertIn('service_identity', deps)
self.assertIn('gmpy', deps)
self.assertIn('pyasn1', deps)
self.assertIn('pycrypto', deps)
self.assertIn('soappy', deps)
self.assertIn('pyserial', deps)


def test_extrasRequiresOsxPlatformDeps(self):
"""
L{_EXTRAS_REQUIRE}'s C{osx_platform} extra contains setuptools
requirements for all of Twisted's optional dependencies usable on the
Mac OS X platform.
"""
deps = _EXTRAS_REQUIRE['osx_platform']
self.assertIn('pyopenssl >= 0.11', deps)
self.assertIn('service_identity', deps)
self.assertIn('gmpy', deps)
self.assertIn('pyasn1', deps)
self.assertIn('pycrypto', deps)
self.assertIn('soappy', deps)
self.assertIn('pyserial', deps)
self.assertIn('pyobjc', deps)


def test_extrasRequiresWindowsPlatformDeps(self):
"""
L{_EXTRAS_REQUIRE}'s C{windows_platform} extra contains setuptools
requirements for all of Twisted's optional dependencies usable on the
Microsoft Windows platform.
"""
deps = _EXTRAS_REQUIRE['windows_platform']
self.assertIn('pyopenssl >= 0.11', deps)
self.assertIn('service_identity', deps)
self.assertIn('gmpy', deps)
self.assertIn('pyasn1', deps)
self.assertIn('pycrypto', deps)
self.assertIn('soappy', deps)
self.assertIn('pyserial', deps)
self.assertIn('pypiwin32', deps)



class GetExtensionsTests(TestCase):
"""
Tests for L{dist.getExtensions}.
Expand Down
1 change: 1 addition & 0 deletions twisted/topfiles/3696.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Optional dependencies can be installed using the extra_requires facility provided by setuptools.

0 comments on commit 4804eff

Please sign in to comment.