test_setup.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for parts of our release automation system.
  5. """
  6. import os
  7. from setuptools.dist import Distribution
  8. import twisted
  9. from twisted.trial.unittest import TestCase
  10. from twisted.python import _setup, filepath
  11. from twisted.python.compat import _PY3
  12. from twisted.python._setup import (
  13. BuildPy3,
  14. getSetupArgs,
  15. ConditionalExtension,
  16. _EXTRAS_REQUIRE,
  17. )
  18. class SetupTests(TestCase):
  19. """
  20. Tests for L{getSetupArgs}.
  21. """
  22. def test_conditionalExtensions(self):
  23. """
  24. Will return the arguments with a custom build_ext which knows how to
  25. check whether they should be built.
  26. """
  27. good_ext = ConditionalExtension("whatever", ["whatever.c"],
  28. condition=lambda b: True)
  29. bad_ext = ConditionalExtension("whatever", ["whatever.c"],
  30. condition=lambda b: False)
  31. args = getSetupArgs(extensions=[good_ext, bad_ext])
  32. # ext_modules should be set even though it's not used. See comment
  33. # in getSetupArgs
  34. self.assertEqual(args["ext_modules"], [good_ext, bad_ext])
  35. cmdclass = args["cmdclass"]
  36. build_ext = cmdclass["build_ext"]
  37. builder = build_ext(Distribution())
  38. builder.prepare_extensions()
  39. self.assertEqual(builder.extensions, [good_ext])
  40. def test_win32Definition(self):
  41. """
  42. When building on Windows NT, the WIN32 macro will be defined as 1 on
  43. the extensions.
  44. """
  45. ext = ConditionalExtension("whatever", ["whatever.c"],
  46. define_macros=[("whatever", 2)])
  47. args = getSetupArgs(extensions=[ext])
  48. builder = args["cmdclass"]["build_ext"](Distribution())
  49. self.patch(os, "name", "nt")
  50. builder.prepare_extensions()
  51. self.assertEqual(ext.define_macros, [("whatever", 2), ("WIN32", 1)])
  52. class OptionalDependenciesTests(TestCase):
  53. """
  54. Tests for L{_EXTRAS_REQUIRE}
  55. """
  56. def test_distributeTakesExtrasRequire(self):
  57. """
  58. Setuptools' Distribution object parses and stores its C{extras_require}
  59. argument as an attribute.
  60. """
  61. extras = dict(im_an_extra_dependency="thing")
  62. attrs = dict(extras_require=extras)
  63. distribution = Distribution(attrs)
  64. self.assertEqual(
  65. extras,
  66. distribution.extras_require
  67. )
  68. def test_extrasRequireDictContainsKeys(self):
  69. """
  70. L{_EXTRAS_REQUIRE} contains options for all documented extras: C{dev},
  71. C{tls}, C{conch}, C{soap}, C{serial}, C{all_non_platform},
  72. C{osx_platform}, and C{windows_platform}.
  73. """
  74. self.assertIn('dev', _EXTRAS_REQUIRE)
  75. self.assertIn('tls', _EXTRAS_REQUIRE)
  76. self.assertIn('conch', _EXTRAS_REQUIRE)
  77. self.assertIn('soap', _EXTRAS_REQUIRE)
  78. self.assertIn('serial', _EXTRAS_REQUIRE)
  79. self.assertIn('all_non_platform', _EXTRAS_REQUIRE)
  80. self.assertIn('osx_platform', _EXTRAS_REQUIRE)
  81. self.assertIn('windows_platform', _EXTRAS_REQUIRE)
  82. self.assertIn('http2', _EXTRAS_REQUIRE)
  83. def test_extrasRequiresDevDeps(self):
  84. """
  85. L{_EXTRAS_REQUIRE}'s C{dev} extra contains setuptools requirements for
  86. the tools required for Twisted development.
  87. """
  88. deps = _EXTRAS_REQUIRE['dev']
  89. self.assertIn('pyflakes >= 1.0.0', deps)
  90. self.assertIn('twisted-dev-tools >= 0.0.2', deps)
  91. self.assertIn('python-subunit', deps)
  92. self.assertIn('sphinx >= 1.3.1', deps)
  93. if not _PY3:
  94. self.assertIn('twistedchecker >= 0.4.0', deps)
  95. self.assertIn('pydoctor >= 16.2.0', deps)
  96. def test_extrasRequiresTlsDeps(self):
  97. """
  98. L{_EXTRAS_REQUIRE}'s C{tls} extra contains setuptools requirements for
  99. the packages required to make Twisted's transport layer security fully
  100. work for both clients and servers.
  101. """
  102. deps = _EXTRAS_REQUIRE['tls']
  103. self.assertIn('pyopenssl >= 16.0.0', deps)
  104. self.assertIn('service_identity', deps)
  105. self.assertIn('idna >= 0.6, != 2.3', deps)
  106. def test_extrasRequiresConchDeps(self):
  107. """
  108. L{_EXTRAS_REQUIRE}'s C{conch} extra contains setuptools requirements
  109. for the packages required to make Twisted Conch's secure shell server
  110. work.
  111. """
  112. deps = _EXTRAS_REQUIRE['conch']
  113. self.assertIn('pyasn1', deps)
  114. self.assertIn('cryptography >= 0.9.1', deps)
  115. self.assertIn('appdirs >= 1.4.0', deps)
  116. def test_extrasRequiresSoapDeps(self):
  117. """
  118. L{_EXTRAS_REQUIRE}' C{soap} extra contains setuptools requirements for
  119. the packages required to make the C{twisted.web.soap} module function.
  120. """
  121. self.assertIn(
  122. 'soappy',
  123. _EXTRAS_REQUIRE['soap']
  124. )
  125. def test_extrasRequiresSerialDeps(self):
  126. """
  127. L{_EXTRAS_REQUIRE}'s C{serial} extra contains setuptools requirements
  128. for the packages required to make Twisted's serial support work.
  129. """
  130. self.assertIn(
  131. 'pyserial',
  132. _EXTRAS_REQUIRE['serial']
  133. )
  134. def test_extrasRequiresHttp2Deps(self):
  135. """
  136. L{_EXTRAS_REQUIRE}'s C{http2} extra contains setuptools requirements
  137. for the packages required to make Twisted HTTP/2 support work.
  138. """
  139. deps = _EXTRAS_REQUIRE['http2']
  140. self.assertIn('h2 >= 3.0, < 4.0', deps)
  141. self.assertIn('priority >= 1.1.0, < 2.0', deps)
  142. def test_extrasRequiresAllNonPlatformDeps(self):
  143. """
  144. L{_EXTRAS_REQUIRE}'s C{all_non_platform} extra contains setuptools
  145. requirements for all of Twisted's optional dependencies which work on
  146. all supported operating systems.
  147. """
  148. deps = _EXTRAS_REQUIRE['all_non_platform']
  149. self.assertIn('pyopenssl >= 16.0.0', deps)
  150. self.assertIn('service_identity', deps)
  151. self.assertIn('idna >= 0.6, != 2.3', deps)
  152. self.assertIn('pyasn1', deps)
  153. self.assertIn('cryptography >= 0.9.1', deps)
  154. self.assertIn('soappy', deps)
  155. self.assertIn('pyserial', deps)
  156. self.assertIn('appdirs >= 1.4.0', deps)
  157. self.assertIn('h2 >= 3.0, < 4.0', deps)
  158. self.assertIn('priority >= 1.1.0, < 2.0', deps)
  159. def test_extrasRequiresOsxPlatformDeps(self):
  160. """
  161. L{_EXTRAS_REQUIRE}'s C{osx_platform} extra contains setuptools
  162. requirements for all of Twisted's optional dependencies usable on the
  163. Mac OS X platform.
  164. """
  165. deps = _EXTRAS_REQUIRE['osx_platform']
  166. self.assertIn('pyopenssl >= 16.0.0', deps)
  167. self.assertIn('service_identity', deps)
  168. self.assertIn('idna >= 0.6, != 2.3', deps)
  169. self.assertIn('pyasn1', deps)
  170. self.assertIn('cryptography >= 0.9.1', deps)
  171. self.assertIn('soappy', deps)
  172. self.assertIn('pyserial', deps)
  173. self.assertIn('h2 >= 3.0, < 4.0', deps)
  174. self.assertIn('priority >= 1.1.0, < 2.0', deps)
  175. self.assertIn('pyobjc-core', deps)
  176. def test_extrasRequiresWindowsPlatformDeps(self):
  177. """
  178. L{_EXTRAS_REQUIRE}'s C{windows_platform} extra contains setuptools
  179. requirements for all of Twisted's optional dependencies usable on the
  180. Microsoft Windows platform.
  181. """
  182. deps = _EXTRAS_REQUIRE['windows_platform']
  183. self.assertIn('pyopenssl >= 16.0.0', deps)
  184. self.assertIn('service_identity', deps)
  185. self.assertIn('idna >= 0.6, != 2.3', deps)
  186. self.assertIn('pyasn1', deps)
  187. self.assertIn('cryptography >= 0.9.1', deps)
  188. self.assertIn('soappy', deps)
  189. self.assertIn('pyserial', deps)
  190. self.assertIn('h2 >= 3.0, < 4.0', deps)
  191. self.assertIn('priority >= 1.1.0, < 2.0', deps)
  192. self.assertIn('pypiwin32', deps)
  193. class FakeModule(object):
  194. """
  195. A fake module, suitable for dependency injection in testing.
  196. """
  197. def __init__(self, attrs):
  198. """
  199. Initializes a fake module.
  200. @param attrs: The attrs that will be accessible on the module.
  201. @type attrs: C{dict} of C{str} (Python names) to objects
  202. """
  203. self._attrs = attrs
  204. def __getattr__(self, name):
  205. """
  206. Gets an attribute of this fake module from its attrs.
  207. @raise AttributeError: When the requested attribute is missing.
  208. """
  209. try:
  210. return self._attrs[name]
  211. except KeyError:
  212. raise AttributeError()
  213. fakeCPythonPlatform = FakeModule({"python_implementation": lambda: "CPython"})
  214. fakeOtherPlatform = FakeModule({"python_implementation": lambda: "lvhpy"})
  215. class WithPlatformTests(TestCase):
  216. """
  217. Tests for L{_checkCPython} when used with a (fake) C{platform} module.
  218. """
  219. def test_cpython(self):
  220. """
  221. L{_checkCPython} returns C{True} when C{platform.python_implementation}
  222. says we're running on CPython.
  223. """
  224. self.assertTrue(_setup._checkCPython(platform=fakeCPythonPlatform))
  225. def test_other(self):
  226. """
  227. L{_checkCPython} returns C{False} when C{platform.python_implementation}
  228. says we're not running on CPython.
  229. """
  230. self.assertFalse(_setup._checkCPython(platform=fakeOtherPlatform))
  231. class BuildPy3Tests(TestCase):
  232. """
  233. Tests for L{BuildPy3}.
  234. """
  235. maxDiff = None
  236. if not _PY3:
  237. skip = "BuildPy3 setuptools command used with Python 3 only."
  238. def test_find_package_modules(self):
  239. """
  240. Will filter the found modules excluding the modules listed in
  241. L{twisted.python.dist3}.
  242. """
  243. distribution = Distribution()
  244. distribution.script_name = 'setup.py'
  245. distribution.script_args = 'build_py'
  246. builder = BuildPy3(distribution)
  247. # Rig the dist3 data so that we can reduce the scope of this test and
  248. # reduce the risk of getting false failures, while doing a minimum
  249. # level of patching.
  250. self.patch(
  251. _setup,
  252. 'notPortedModules',
  253. [
  254. "twisted.spread.test.test_pbfailure",
  255. ],
  256. )
  257. twistedPackageDir = filepath.FilePath(twisted.__file__).parent()
  258. packageDir = twistedPackageDir.child("spread").child("test")
  259. result = builder.find_package_modules('twisted.spread.test',
  260. packageDir.path)
  261. self.assertEqual(sorted([
  262. ('twisted.spread.test', '__init__',
  263. packageDir.child('__init__.py').path),
  264. ('twisted.spread.test', 'test_banana',
  265. packageDir.child('test_banana.py').path),
  266. ('twisted.spread.test', 'test_jelly',
  267. packageDir.child('test_jelly.py').path),
  268. ('twisted.spread.test', 'test_pb',
  269. packageDir.child('test_pb.py').path),
  270. ]),
  271. sorted(result),
  272. )