Home | History | Annotate | Download | only in tests
      1 # -*- encoding: utf8 -*-
      2 """Tests for distutils.command.register."""
      3 import os
      4 import unittest
      5 import getpass
      6 import urllib2
      7 import warnings
      8 
      9 from test.test_support import check_warnings, run_unittest
     10 
     11 from distutils.command import register as register_module
     12 from distutils.command.register import register
     13 from distutils.errors import DistutilsSetupError
     14 
     15 from distutils.tests.test_config import PyPIRCCommandTestCase
     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 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 
     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):
     63         self.reqs.append(req)
     64         return self
     65 
     66     def read(self):
     67         return 'xxx'
     68 
     69 class RegisterTestCase(PyPIRCCommandTestCase):
     70 
     71     def setUp(self):
     72         super(RegisterTestCase, self).setUp()
     73         # patching the password prompt
     74         self._old_getpass = getpass.getpass
     75         def _getpass(prompt):
     76             return 'password'
     77         getpass.getpass = _getpass
     78         self.old_opener = urllib2.build_opener
     79         self.conn = urllib2.build_opener = FakeOpener()
     80 
     81     def tearDown(self):
     82         getpass.getpass = self._old_getpass
     83         urllib2.build_opener = self.old_opener
     84         super(RegisterTestCase, self).tearDown()
     85 
     86     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'}
     91         pkg_info, dist = self.create_dist(**metadata)
     92         return register(dist)
     93 
     94     def test_create_pypirc(self):
     95         # this test makes sure a .pypirc file
     96         # is created when requested.
     97 
     98         # let's create a register instance
     99         cmd = self._get_cmd()
    100 
    101         # we shouldn't have a .pypirc file yet
    102         self.assertTrue(not os.path.exists(self.rc))
    103 
    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'
    110         # Password : 'password'
    111         # Save your login (y/N)? : 'y'
    112         inputs = RawInputs('1', 'tarek', 'y')
    113         register_module.raw_input = inputs.__call__
    114         # let's run the command
    115         try:
    116             cmd.run()
    117         finally:
    118             del register_module.raw_input
    119 
    120         # we should have a brand new .pypirc file
    121         self.assertTrue(os.path.exists(self.rc))
    122 
    123         # with the content similar to WANTED_PYPIRC
    124         f = open(self.rc)
    125         try:
    126             content = f.read()
    127             self.assertEqual(content, WANTED_PYPIRC)
    128         finally:
    129             f.close()
    130 
    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 
    138         cmd.show_response = 1
    139         cmd.run()
    140 
    141         # let's see what the server received : we should
    142         # have 2 similar requests
    143         self.assertEqual(len(self.conn.reqs), 2)
    144         req1 = dict(self.conn.reqs[0].headers)
    145         req2 = dict(self.conn.reqs[1].headers)
    146         self.assertEqual(req2['Content-length'], req1['Content-length'])
    147         self.assertTrue('xxx' in self.conn.reqs[1].data)
    148 
    149     def test_password_not_in_file(self):
    150 
    151         self.write_file(self.rc, PYPIRC_NOPASSWORD)
    152         cmd = self._get_cmd()
    153         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
    159         self.assertEqual(cmd.distribution.password, 'password')
    160 
    161     def test_registering(self):
    162         # this test runs choice 2
    163         cmd = self._get_cmd()
    164         inputs = RawInputs('2', 'tarek', 'tarek (at] 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
    173         self.assertEqual(len(self.conn.reqs), 1)
    174         req = self.conn.reqs[0]
    175         headers = dict(req.headers)
    176         self.assertEqual(headers['Content-length'], '608')
    177         self.assertTrue('tarek' in req.data)
    178 
    179     def test_password_reset(self):
    180         # this test runs choice 3
    181         cmd = self._get_cmd()
    182         inputs = RawInputs('3', 'tarek (at] 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
    191         self.assertEqual(len(self.conn.reqs), 1)
    192         req = self.conn.reqs[0]
    193         headers = dict(req.headers)
    194         self.assertEqual(headers['Content-length'], '290')
    195         self.assertTrue('tarek' in req.data)
    196 
    197     @unittest.skipUnless(docutils is not None, 'needs docutils')
    198     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 
    210         # metadata are OK but long_description is broken
    211         metadata = {'url': 'xxx', 'author': 'xxx',
    212                     'author_email': u'xx',
    213                     '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 
    245         # 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 
    263     @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 (at] ziade.org')
    274         register_module.raw_input = inputs
    275         self.addCleanup(delattr, register_module, 'raw_input')
    276         self.assertRaises(DistutilsSetupError, cmd.run)
    277 
    278     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()
    284             self.assertEqual(len(w.warnings), 1)
    285 
    286 def test_suite():
    287     return unittest.makeSuite(RegisterTestCase)
    288 
    289 if __name__ == "__main__":
    290     run_unittest(test_suite())
    291