test_register.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. """Tests for distutils.command.register."""
  2. import os
  3. import unittest
  4. import getpass
  5. import urllib
  6. import warnings
  7. from test.support import check_warnings, run_unittest
  8. from distutils.command import register as register_module
  9. from distutils.command.register import register
  10. from distutils.errors import DistutilsSetupError
  11. from distutils.log import INFO
  12. from distutils.tests.test_config import BasePyPIRCCommandTestCase
  13. try:
  14. import docutils
  15. except ImportError:
  16. docutils = None
  17. PYPIRC_NOPASSWORD = """\
  18. [distutils]
  19. index-servers =
  20. server1
  21. [server1]
  22. username:me
  23. """
  24. WANTED_PYPIRC = """\
  25. [distutils]
  26. index-servers =
  27. pypi
  28. [pypi]
  29. username:tarek
  30. password:password
  31. """
  32. class Inputs(object):
  33. """Fakes user inputs."""
  34. def __init__(self, *answers):
  35. self.answers = answers
  36. self.index = 0
  37. def __call__(self, prompt=''):
  38. try:
  39. return self.answers[self.index]
  40. finally:
  41. self.index += 1
  42. class FakeOpener(object):
  43. """Fakes a PyPI server"""
  44. def __init__(self):
  45. self.reqs = []
  46. def __call__(self, *args):
  47. return self
  48. def open(self, req, data=None, timeout=None):
  49. self.reqs.append(req)
  50. return self
  51. def read(self):
  52. return b'xxx'
  53. def getheader(self, name, default=None):
  54. return {
  55. 'content-type': 'text/plain; charset=utf-8',
  56. }.get(name.lower(), default)
  57. class RegisterTestCase(BasePyPIRCCommandTestCase):
  58. def setUp(self):
  59. super(RegisterTestCase, self).setUp()
  60. # patching the password prompt
  61. self._old_getpass = getpass.getpass
  62. def _getpass(prompt):
  63. return 'password'
  64. getpass.getpass = _getpass
  65. urllib.request._opener = None
  66. self.old_opener = urllib.request.build_opener
  67. self.conn = urllib.request.build_opener = FakeOpener()
  68. def tearDown(self):
  69. getpass.getpass = self._old_getpass
  70. urllib.request._opener = None
  71. urllib.request.build_opener = self.old_opener
  72. super(RegisterTestCase, self).tearDown()
  73. def _get_cmd(self, metadata=None):
  74. if metadata is None:
  75. metadata = {'url': 'xxx', 'author': 'xxx',
  76. 'author_email': 'xxx',
  77. 'name': 'xxx', 'version': 'xxx'}
  78. pkg_info, dist = self.create_dist(**metadata)
  79. return register(dist)
  80. def test_create_pypirc(self):
  81. # this test makes sure a .pypirc file
  82. # is created when requested.
  83. # let's create a register instance
  84. cmd = self._get_cmd()
  85. # we shouldn't have a .pypirc file yet
  86. self.assertFalse(os.path.exists(self.rc))
  87. # patching input and getpass.getpass
  88. # so register gets happy
  89. #
  90. # Here's what we are faking :
  91. # use your existing login (choice 1.)
  92. # Username : 'tarek'
  93. # Password : 'password'
  94. # Save your login (y/N)? : 'y'
  95. inputs = Inputs('1', 'tarek', 'y')
  96. register_module.input = inputs.__call__
  97. # let's run the command
  98. try:
  99. cmd.run()
  100. finally:
  101. del register_module.input
  102. # we should have a brand new .pypirc file
  103. self.assertTrue(os.path.exists(self.rc))
  104. # with the content similar to WANTED_PYPIRC
  105. f = open(self.rc)
  106. try:
  107. content = f.read()
  108. self.assertEqual(content, WANTED_PYPIRC)
  109. finally:
  110. f.close()
  111. # now let's make sure the .pypirc file generated
  112. # really works : we shouldn't be asked anything
  113. # if we run the command again
  114. def _no_way(prompt=''):
  115. raise AssertionError(prompt)
  116. register_module.input = _no_way
  117. cmd.show_response = 1
  118. cmd.run()
  119. # let's see what the server received : we should
  120. # have 2 similar requests
  121. self.assertEqual(len(self.conn.reqs), 2)
  122. req1 = dict(self.conn.reqs[0].headers)
  123. req2 = dict(self.conn.reqs[1].headers)
  124. self.assertEqual(req1['Content-length'], '1374')
  125. self.assertEqual(req2['Content-length'], '1374')
  126. self.assertIn(b'xxx', self.conn.reqs[1].data)
  127. def test_password_not_in_file(self):
  128. self.write_file(self.rc, PYPIRC_NOPASSWORD)
  129. cmd = self._get_cmd()
  130. cmd._set_config()
  131. cmd.finalize_options()
  132. cmd.send_metadata()
  133. # dist.password should be set
  134. # therefore used afterwards by other commands
  135. self.assertEqual(cmd.distribution.password, 'password')
  136. def test_registering(self):
  137. # this test runs choice 2
  138. cmd = self._get_cmd()
  139. inputs = Inputs('2', 'tarek', 'tarek@ziade.org')
  140. register_module.input = inputs.__call__
  141. try:
  142. # let's run the command
  143. cmd.run()
  144. finally:
  145. del register_module.input
  146. # we should have send a request
  147. self.assertEqual(len(self.conn.reqs), 1)
  148. req = self.conn.reqs[0]
  149. headers = dict(req.headers)
  150. self.assertEqual(headers['Content-length'], '608')
  151. self.assertIn(b'tarek', req.data)
  152. def test_password_reset(self):
  153. # this test runs choice 3
  154. cmd = self._get_cmd()
  155. inputs = Inputs('3', 'tarek@ziade.org')
  156. register_module.input = inputs.__call__
  157. try:
  158. # let's run the command
  159. cmd.run()
  160. finally:
  161. del register_module.input
  162. # we should have send a request
  163. self.assertEqual(len(self.conn.reqs), 1)
  164. req = self.conn.reqs[0]
  165. headers = dict(req.headers)
  166. self.assertEqual(headers['Content-length'], '290')
  167. self.assertIn(b'tarek', req.data)
  168. @unittest.skipUnless(docutils is not None, 'needs docutils')
  169. def test_strict(self):
  170. # testing the script option
  171. # when on, the register command stops if
  172. # the metadata is incomplete or if
  173. # long_description is not reSt compliant
  174. # empty metadata
  175. cmd = self._get_cmd({})
  176. cmd.ensure_finalized()
  177. cmd.strict = 1
  178. self.assertRaises(DistutilsSetupError, cmd.run)
  179. # metadata are OK but long_description is broken
  180. metadata = {'url': 'xxx', 'author': 'xxx',
  181. 'author_email': 'éxéxé',
  182. 'name': 'xxx', 'version': 'xxx',
  183. 'long_description': 'title\n==\n\ntext'}
  184. cmd = self._get_cmd(metadata)
  185. cmd.ensure_finalized()
  186. cmd.strict = 1
  187. self.assertRaises(DistutilsSetupError, cmd.run)
  188. # now something that works
  189. metadata['long_description'] = 'title\n=====\n\ntext'
  190. cmd = self._get_cmd(metadata)
  191. cmd.ensure_finalized()
  192. cmd.strict = 1
  193. inputs = Inputs('1', 'tarek', 'y')
  194. register_module.input = inputs.__call__
  195. # let's run the command
  196. try:
  197. cmd.run()
  198. finally:
  199. del register_module.input
  200. # strict is not by default
  201. cmd = self._get_cmd()
  202. cmd.ensure_finalized()
  203. inputs = Inputs('1', 'tarek', 'y')
  204. register_module.input = inputs.__call__
  205. # let's run the command
  206. try:
  207. cmd.run()
  208. finally:
  209. del register_module.input
  210. # and finally a Unicode test (bug #12114)
  211. metadata = {'url': 'xxx', 'author': '\u00c9ric',
  212. 'author_email': 'xxx', 'name': 'xxx',
  213. 'version': 'xxx',
  214. 'description': 'Something about esszet \u00df',
  215. 'long_description': 'More things about esszet \u00df'}
  216. cmd = self._get_cmd(metadata)
  217. cmd.ensure_finalized()
  218. cmd.strict = 1
  219. inputs = Inputs('1', 'tarek', 'y')
  220. register_module.input = inputs.__call__
  221. # let's run the command
  222. try:
  223. cmd.run()
  224. finally:
  225. del register_module.input
  226. @unittest.skipUnless(docutils is not None, 'needs docutils')
  227. def test_register_invalid_long_description(self):
  228. description = ':funkie:`str`' # mimic Sphinx-specific markup
  229. metadata = {'url': 'xxx', 'author': 'xxx',
  230. 'author_email': 'xxx',
  231. 'name': 'xxx', 'version': 'xxx',
  232. 'long_description': description}
  233. cmd = self._get_cmd(metadata)
  234. cmd.ensure_finalized()
  235. cmd.strict = True
  236. inputs = Inputs('2', 'tarek', 'tarek@ziade.org')
  237. register_module.input = inputs
  238. self.addCleanup(delattr, register_module, 'input')
  239. self.assertRaises(DistutilsSetupError, cmd.run)
  240. def test_check_metadata_deprecated(self):
  241. # makes sure make_metadata is deprecated
  242. cmd = self._get_cmd()
  243. with check_warnings() as w:
  244. warnings.simplefilter("always")
  245. cmd.check_metadata()
  246. self.assertEqual(len(w.warnings), 1)
  247. def test_list_classifiers(self):
  248. cmd = self._get_cmd()
  249. cmd.list_classifiers = 1
  250. cmd.run()
  251. results = self.get_logs(INFO)
  252. self.assertEqual(results, ['running check', 'xxx'])
  253. def test_show_response(self):
  254. # test that the --show-response option return a well formatted response
  255. cmd = self._get_cmd()
  256. inputs = Inputs('1', 'tarek', 'y')
  257. register_module.input = inputs.__call__
  258. cmd.show_response = 1
  259. try:
  260. cmd.run()
  261. finally:
  262. del register_module.input
  263. results = self.get_logs(INFO)
  264. self.assertEqual(results[3], 75 * '-' + '\nxxx\n' + 75 * '-')
  265. def test_suite():
  266. return unittest.makeSuite(RegisterTestCase)
  267. if __name__ == "__main__":
  268. run_unittest(test_suite())