test_register.py 9.6 KB

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