blob: ca7d79bbb2294673a19d0ce90207a1706eb158d3 [file] [log] [blame]
Tarek Ziadéf14c7fc2010-01-24 00:33:32 +00001# -*- encoding: utf8 -*-
Éric Araujo017e5352011-10-09 07:11:19 +02002"""Tests for distutils.command.register."""
Tarek Ziadée4c75bb2008-12-24 19:10:05 +00003import os
4import unittest
Tarek Ziadé1a240fb2009-01-08 23:56:31 +00005import getpass
Tarek Ziadéca2b8d22009-03-31 20:53:13 +00006import urllib2
Tarek Ziadécb768042009-05-16 16:37:06 +00007import warnings
8
Éric Araujo54274ad2011-02-03 00:12:18 +00009from test.test_support import check_warnings, run_unittest
Tarek Ziadée4c75bb2008-12-24 19:10:05 +000010
Tarek Ziadéca2b8d22009-03-31 20:53:13 +000011from distutils.command import register as register_module
Tarek Ziadée4c75bb2008-12-24 19:10:05 +000012from distutils.command.register import register
Tarek Ziadécb768042009-05-16 16:37:06 +000013from distutils.errors import DistutilsSetupError
Tarek Ziadée4c75bb2008-12-24 19:10:05 +000014
Éric Araujo2320fa02012-12-08 22:26:57 -050015from distutils.tests.test_config import PyPIRCCommandTestCase
16
17try:
18 import docutils
19except ImportError:
20 docutils = None
Tarek Ziadée4c75bb2008-12-24 19:10:05 +000021
Tarek Ziadé1a240fb2009-01-08 23:56:31 +000022PYPIRC_NOPASSWORD = """\
23[distutils]
24
25index-servers =
26 server1
27
28[server1]
29username:me
30"""
31
32WANTED_PYPIRC = """\
33[distutils]
34index-servers =
35 pypi
36
37[pypi]
38username:tarek
39password:password
40"""
41
Tarek Ziadée4c75bb2008-12-24 19:10:05 +000042class RawInputs(object):
43 """Fakes user inputs."""
44 def __init__(self, *answers):
45 self.answers = answers
46 self.index = 0
47
48 def __call__(self, prompt=''):
49 try:
50 return self.answers[self.index]
51 finally:
52 self.index += 1
53
Tarek Ziadéca2b8d22009-03-31 20:53:13 +000054class FakeOpener(object):
Tarek Ziadé1a240fb2009-01-08 23:56:31 +000055 """Fakes a PyPI server"""
56 def __init__(self):
Tarek Ziadéca2b8d22009-03-31 20:53:13 +000057 self.reqs = []
Tarek Ziadée4c75bb2008-12-24 19:10:05 +000058
Tarek Ziadé1a240fb2009-01-08 23:56:31 +000059 def __call__(self, *args):
Tarek Ziadéca2b8d22009-03-31 20:53:13 +000060 return self
61
62 def open(self, req):
63 self.reqs.append(req)
64 return self
65
66 def read(self):
67 return 'xxx'
Tarek Ziadée4c75bb2008-12-24 19:10:05 +000068
Tarek Ziadécb768042009-05-16 16:37:06 +000069class RegisterTestCase(PyPIRCCommandTestCase):
Tarek Ziadée4c75bb2008-12-24 19:10:05 +000070
Tarek Ziadé1a240fb2009-01-08 23:56:31 +000071 def setUp(self):
Tarek Ziadé3e3eace2009-05-29 08:08:07 +000072 super(RegisterTestCase, self).setUp()
Tarek Ziadé1a240fb2009-01-08 23:56:31 +000073 # patching the password prompt
74 self._old_getpass = getpass.getpass
75 def _getpass(prompt):
76 return 'password'
77 getpass.getpass = _getpass
Tarek Ziadéca2b8d22009-03-31 20:53:13 +000078 self.old_opener = urllib2.build_opener
79 self.conn = urllib2.build_opener = FakeOpener()
Tarek Ziadé1a240fb2009-01-08 23:56:31 +000080
81 def tearDown(self):
82 getpass.getpass = self._old_getpass
Tarek Ziadéca2b8d22009-03-31 20:53:13 +000083 urllib2.build_opener = self.old_opener
Tarek Ziadé3e3eace2009-05-29 08:08:07 +000084 super(RegisterTestCase, self).tearDown()
Tarek Ziadé1a240fb2009-01-08 23:56:31 +000085
Tarek Ziadécb768042009-05-16 16:37:06 +000086 def _get_cmd(self, metadata=None):
87 if metadata is None:
88 metadata = {'url': 'xxx', 'author': 'xxx',
89 'author_email': 'xxx',
90 'name': 'xxx', 'version': 'xxx'}
Tarek Ziadéca2b8d22009-03-31 20:53:13 +000091 pkg_info, dist = self.create_dist(**metadata)
92 return register(dist)
93
Tarek Ziadée4c75bb2008-12-24 19:10:05 +000094 def test_create_pypirc(self):
95 # this test makes sure a .pypirc file
96 # is created when requested.
97
Tarek Ziadéca2b8d22009-03-31 20:53:13 +000098 # let's create a register instance
99 cmd = self._get_cmd()
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000100
101 # we shouldn't have a .pypirc file yet
Serhiy Storchaka25a23ef2013-11-17 00:29:27 +0200102 self.assertFalse(os.path.exists(self.rc))
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000103
104 # patching raw_input and getpass.getpass
105 # so register gets happy
106 #
107 # Here's what we are faking :
108 # use your existing login (choice 1.)
109 # Username : 'tarek'
Tarek Ziadé1a240fb2009-01-08 23:56:31 +0000110 # Password : 'password'
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000111 # Save your login (y/N)? : 'y'
112 inputs = RawInputs('1', 'tarek', 'y')
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000113 register_module.raw_input = inputs.__call__
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000114 # let's run the command
Tarek Ziadéca2b8d22009-03-31 20:53:13 +0000115 try:
116 cmd.run()
117 finally:
118 del register_module.raw_input
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000119
120 # we should have a brand new .pypirc file
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000121 self.assertTrue(os.path.exists(self.rc))
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000122
123 # with the content similar to WANTED_PYPIRC
Éric Araujod1feff72010-11-06 04:06:18 +0000124 f = open(self.rc)
125 try:
126 content = f.read()
Ezio Melotti2623a372010-11-21 13:34:58 +0000127 self.assertEqual(content, WANTED_PYPIRC)
Éric Araujod1feff72010-11-06 04:06:18 +0000128 finally:
129 f.close()
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000130
131 # now let's make sure the .pypirc file generated
132 # really works : we shouldn't be asked anything
133 # if we run the command again
134 def _no_way(prompt=''):
135 raise AssertionError(prompt)
136 register_module.raw_input = _no_way
137
Tarek Ziadéca2b8d22009-03-31 20:53:13 +0000138 cmd.show_response = 1
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000139 cmd.run()
140
141 # let's see what the server received : we should
142 # have 2 similar requests
Éric Araujoe4f8d832011-04-14 03:49:19 +0200143 self.assertEqual(len(self.conn.reqs), 2)
Tarek Ziadéca2b8d22009-03-31 20:53:13 +0000144 req1 = dict(self.conn.reqs[0].headers)
145 req2 = dict(self.conn.reqs[1].headers)
Ezio Melotti2623a372010-11-21 13:34:58 +0000146 self.assertEqual(req2['Content-length'], req1['Content-length'])
Serhiy Storchaka25a23ef2013-11-17 00:29:27 +0200147 self.assertIn('xxx', self.conn.reqs[1].data)
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000148
Tarek Ziadé1a240fb2009-01-08 23:56:31 +0000149 def test_password_not_in_file(self):
150
Tarek Ziadéca2b8d22009-03-31 20:53:13 +0000151 self.write_file(self.rc, PYPIRC_NOPASSWORD)
152 cmd = self._get_cmd()
Tarek Ziadé1a240fb2009-01-08 23:56:31 +0000153 cmd._set_config()
154 cmd.finalize_options()
155 cmd.send_metadata()
156
157 # dist.password should be set
158 # therefore used afterwards by other commands
Ezio Melotti2623a372010-11-21 13:34:58 +0000159 self.assertEqual(cmd.distribution.password, 'password')
Tarek Ziadéca2b8d22009-03-31 20:53:13 +0000160
161 def test_registering(self):
162 # this test runs choice 2
163 cmd = self._get_cmd()
164 inputs = RawInputs('2', 'tarek', 'tarek@ziade.org')
165 register_module.raw_input = inputs.__call__
166 try:
167 # let's run the command
168 cmd.run()
169 finally:
170 del register_module.raw_input
171
172 # we should have send a request
Éric Araujoe4f8d832011-04-14 03:49:19 +0200173 self.assertEqual(len(self.conn.reqs), 1)
Tarek Ziadéca2b8d22009-03-31 20:53:13 +0000174 req = self.conn.reqs[0]
175 headers = dict(req.headers)
Ezio Melotti2623a372010-11-21 13:34:58 +0000176 self.assertEqual(headers['Content-length'], '608')
Serhiy Storchaka25a23ef2013-11-17 00:29:27 +0200177 self.assertIn('tarek', req.data)
Tarek Ziadéca2b8d22009-03-31 20:53:13 +0000178
179 def test_password_reset(self):
180 # this test runs choice 3
181 cmd = self._get_cmd()
182 inputs = RawInputs('3', 'tarek@ziade.org')
183 register_module.raw_input = inputs.__call__
184 try:
185 # let's run the command
186 cmd.run()
187 finally:
188 del register_module.raw_input
189
190 # we should have send a request
Éric Araujoe4f8d832011-04-14 03:49:19 +0200191 self.assertEqual(len(self.conn.reqs), 1)
Tarek Ziadéca2b8d22009-03-31 20:53:13 +0000192 req = self.conn.reqs[0]
193 headers = dict(req.headers)
Ezio Melotti2623a372010-11-21 13:34:58 +0000194 self.assertEqual(headers['Content-length'], '290')
Serhiy Storchaka25a23ef2013-11-17 00:29:27 +0200195 self.assertIn('tarek', req.data)
Tarek Ziadé1a240fb2009-01-08 23:56:31 +0000196
Éric Araujo9e06e8d2012-12-08 22:30:47 -0500197 @unittest.skipUnless(docutils is not None, 'needs docutils')
Tarek Ziadécb768042009-05-16 16:37:06 +0000198 def test_strict(self):
199 # testing the script option
200 # when on, the register command stops if
201 # the metadata is incomplete or if
202 # long_description is not reSt compliant
203
204 # empty metadata
205 cmd = self._get_cmd({})
206 cmd.ensure_finalized()
207 cmd.strict = 1
208 self.assertRaises(DistutilsSetupError, cmd.run)
209
Tarek Ziadécb768042009-05-16 16:37:06 +0000210 # metadata are OK but long_description is broken
211 metadata = {'url': 'xxx', 'author': 'xxx',
Tarek Ziadéf14c7fc2010-01-24 00:33:32 +0000212 'author_email': u'éxéxé',
Tarek Ziadécb768042009-05-16 16:37:06 +0000213 'name': 'xxx', 'version': 'xxx',
214 'long_description': 'title\n==\n\ntext'}
215
216 cmd = self._get_cmd(metadata)
217 cmd.ensure_finalized()
218 cmd.strict = 1
219 self.assertRaises(DistutilsSetupError, cmd.run)
220
221 # now something that works
222 metadata['long_description'] = 'title\n=====\n\ntext'
223 cmd = self._get_cmd(metadata)
224 cmd.ensure_finalized()
225 cmd.strict = 1
226 inputs = RawInputs('1', 'tarek', 'y')
227 register_module.raw_input = inputs.__call__
228 # let's run the command
229 try:
230 cmd.run()
231 finally:
232 del register_module.raw_input
233
234 # strict is not by default
235 cmd = self._get_cmd()
236 cmd.ensure_finalized()
237 inputs = RawInputs('1', 'tarek', 'y')
238 register_module.raw_input = inputs.__call__
239 # let's run the command
240 try:
241 cmd.run()
242 finally:
243 del register_module.raw_input
244
Éric Araujo017e5352011-10-09 07:11:19 +0200245 # and finally a Unicode test (bug #12114)
246 metadata = {'url': u'xxx', 'author': u'\u00c9ric',
247 'author_email': u'xxx', u'name': 'xxx',
248 'version': u'xxx',
249 'description': u'Something about esszet \u00df',
250 'long_description': u'More things about esszet \u00df'}
251
252 cmd = self._get_cmd(metadata)
253 cmd.ensure_finalized()
254 cmd.strict = 1
255 inputs = RawInputs('1', 'tarek', 'y')
256 register_module.raw_input = inputs.__call__
257 # let's run the command
258 try:
259 cmd.run()
260 finally:
261 del register_module.raw_input
262
Éric Araujo2320fa02012-12-08 22:26:57 -0500263 @unittest.skipUnless(docutils is not None, 'needs docutils')
264 def test_register_invalid_long_description(self):
265 description = ':funkie:`str`' # mimic Sphinx-specific markup
266 metadata = {'url': 'xxx', 'author': 'xxx',
267 'author_email': 'xxx',
268 'name': 'xxx', 'version': 'xxx',
269 'long_description': description}
270 cmd = self._get_cmd(metadata)
271 cmd.ensure_finalized()
272 cmd.strict = True
273 inputs = RawInputs('2', 'tarek', 'tarek@ziade.org')
274 register_module.raw_input = inputs
275 self.addCleanup(delattr, register_module, 'raw_input')
276 self.assertRaises(DistutilsSetupError, cmd.run)
277
Tarek Ziadécb768042009-05-16 16:37:06 +0000278 def test_check_metadata_deprecated(self):
279 # makes sure make_metadata is deprecated
280 cmd = self._get_cmd()
281 with check_warnings() as w:
282 warnings.simplefilter("always")
283 cmd.check_metadata()
Ezio Melotti2623a372010-11-21 13:34:58 +0000284 self.assertEqual(len(w.warnings), 1)
Tarek Ziadécb768042009-05-16 16:37:06 +0000285
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000286def test_suite():
Tarek Ziadécb768042009-05-16 16:37:06 +0000287 return unittest.makeSuite(RegisterTestCase)
Tarek Ziadée4c75bb2008-12-24 19:10:05 +0000288
289if __name__ == "__main__":
Éric Araujo54274ad2011-02-03 00:12:18 +0000290 run_unittest(test_suite())