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