test_packageindex.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. """Package Index Tests
  2. """
  3. import sys
  4. import os
  5. import unittest
  6. import pkg_resources
  7. from setuptools.compat import urllib2, httplib, HTTPError, unicode, pathname2url
  8. import distutils.errors
  9. import setuptools.package_index
  10. from setuptools.tests.server import IndexServer
  11. class TestPackageIndex(unittest.TestCase):
  12. def test_bad_url_bad_port(self):
  13. index = setuptools.package_index.PackageIndex()
  14. url = 'http://127.0.0.1:0/nonesuch/test_package_index'
  15. try:
  16. v = index.open_url(url)
  17. except Exception:
  18. v = sys.exc_info()[1]
  19. self.assertTrue(url in str(v))
  20. else:
  21. self.assertTrue(isinstance(v, HTTPError))
  22. def test_bad_url_typo(self):
  23. # issue 16
  24. # easy_install inquant.contentmirror.plone breaks because of a typo
  25. # in its home URL
  26. index = setuptools.package_index.PackageIndex(
  27. hosts=('www.example.com',)
  28. )
  29. url = 'url:%20https://svn.plone.org/svn/collective/inquant.contentmirror.plone/trunk'
  30. try:
  31. v = index.open_url(url)
  32. except Exception:
  33. v = sys.exc_info()[1]
  34. self.assertTrue(url in str(v))
  35. else:
  36. self.assertTrue(isinstance(v, HTTPError))
  37. def test_bad_url_bad_status_line(self):
  38. index = setuptools.package_index.PackageIndex(
  39. hosts=('www.example.com',)
  40. )
  41. def _urlopen(*args):
  42. raise httplib.BadStatusLine('line')
  43. index.opener = _urlopen
  44. url = 'http://example.com'
  45. try:
  46. v = index.open_url(url)
  47. except Exception:
  48. v = sys.exc_info()[1]
  49. self.assertTrue('line' in str(v))
  50. else:
  51. raise AssertionError('Should have raise here!')
  52. def test_bad_url_double_scheme(self):
  53. """
  54. A bad URL with a double scheme should raise a DistutilsError.
  55. """
  56. index = setuptools.package_index.PackageIndex(
  57. hosts=('www.example.com',)
  58. )
  59. # issue 20
  60. url = 'http://http://svn.pythonpaste.org/Paste/wphp/trunk'
  61. try:
  62. index.open_url(url)
  63. except distutils.errors.DistutilsError:
  64. error = sys.exc_info()[1]
  65. msg = unicode(error)
  66. assert 'nonnumeric port' in msg or 'getaddrinfo failed' in msg or 'Name or service not known' in msg
  67. return
  68. raise RuntimeError("Did not raise")
  69. def test_bad_url_screwy_href(self):
  70. index = setuptools.package_index.PackageIndex(
  71. hosts=('www.example.com',)
  72. )
  73. # issue #160
  74. if sys.version_info[0] == 2 and sys.version_info[1] == 7:
  75. # this should not fail
  76. url = 'http://example.com'
  77. page = ('<a href="http://www.famfamfam.com]('
  78. 'http://www.famfamfam.com/">')
  79. index.process_index(url, page)
  80. def test_url_ok(self):
  81. index = setuptools.package_index.PackageIndex(
  82. hosts=('www.example.com',)
  83. )
  84. url = 'file:///tmp/test_package_index'
  85. self.assertTrue(index.url_ok(url, True))
  86. def test_links_priority(self):
  87. """
  88. Download links from the pypi simple index should be used before
  89. external download links.
  90. https://bitbucket.org/tarek/distribute/issue/163
  91. Usecase :
  92. - someone uploads a package on pypi, a md5 is generated
  93. - someone manually copies this link (with the md5 in the url) onto an
  94. external page accessible from the package page.
  95. - someone reuploads the package (with a different md5)
  96. - while easy_installing, an MD5 error occurs because the external link
  97. is used
  98. -> Setuptools should use the link from pypi, not the external one.
  99. """
  100. if sys.platform.startswith('java'):
  101. # Skip this test on jython because binding to :0 fails
  102. return
  103. # start an index server
  104. server = IndexServer()
  105. server.start()
  106. index_url = server.base_url() + 'test_links_priority/simple/'
  107. # scan a test index
  108. pi = setuptools.package_index.PackageIndex(index_url)
  109. requirement = pkg_resources.Requirement.parse('foobar')
  110. pi.find_packages(requirement)
  111. server.stop()
  112. # the distribution has been found
  113. self.assertTrue('foobar' in pi)
  114. # we have only one link, because links are compared without md5
  115. self.assertTrue(len(pi['foobar'])==1)
  116. # the link should be from the index
  117. self.assertTrue('correct_md5' in pi['foobar'][0].location)
  118. def test_parse_bdist_wininst(self):
  119. self.assertEqual(setuptools.package_index.parse_bdist_wininst(
  120. 'reportlab-2.5.win32-py2.4.exe'), ('reportlab-2.5', '2.4', 'win32'))
  121. self.assertEqual(setuptools.package_index.parse_bdist_wininst(
  122. 'reportlab-2.5.win32.exe'), ('reportlab-2.5', None, 'win32'))
  123. self.assertEqual(setuptools.package_index.parse_bdist_wininst(
  124. 'reportlab-2.5.win-amd64-py2.7.exe'), ('reportlab-2.5', '2.7', 'win-amd64'))
  125. self.assertEqual(setuptools.package_index.parse_bdist_wininst(
  126. 'reportlab-2.5.win-amd64.exe'), ('reportlab-2.5', None, 'win-amd64'))
  127. def test__vcs_split_rev_from_url(self):
  128. """
  129. Test the basic usage of _vcs_split_rev_from_url
  130. """
  131. vsrfu = setuptools.package_index.PackageIndex._vcs_split_rev_from_url
  132. url, rev = vsrfu('https://example.com/bar@2995')
  133. self.assertEqual(url, 'https://example.com/bar')
  134. self.assertEqual(rev, '2995')
  135. def test_local_index(self):
  136. """
  137. local_open should be able to read an index from the file system.
  138. """
  139. f = open('index.html', 'w')
  140. f.write('<div>content</div>')
  141. f.close()
  142. try:
  143. url = 'file:' + pathname2url(os.getcwd()) + '/'
  144. res = setuptools.package_index.local_open(url)
  145. finally:
  146. os.remove('index.html')
  147. assert 'content' in res.read()
  148. class TestContentCheckers(unittest.TestCase):
  149. def test_md5(self):
  150. checker = setuptools.package_index.HashChecker.from_url(
  151. 'http://foo/bar#md5=f12895fdffbd45007040d2e44df98478')
  152. checker.feed('You should probably not be using MD5'.encode('ascii'))
  153. self.assertEqual(checker.hash.hexdigest(),
  154. 'f12895fdffbd45007040d2e44df98478')
  155. self.assertTrue(checker.is_valid())
  156. def test_other_fragment(self):
  157. "Content checks should succeed silently if no hash is present"
  158. checker = setuptools.package_index.HashChecker.from_url(
  159. 'http://foo/bar#something%20completely%20different')
  160. checker.feed('anything'.encode('ascii'))
  161. self.assertTrue(checker.is_valid())
  162. def test_blank_md5(self):
  163. "Content checks should succeed if a hash is empty"
  164. checker = setuptools.package_index.HashChecker.from_url(
  165. 'http://foo/bar#md5=')
  166. checker.feed('anything'.encode('ascii'))
  167. self.assertTrue(checker.is_valid())
  168. def test_get_hash_name_md5(self):
  169. checker = setuptools.package_index.HashChecker.from_url(
  170. 'http://foo/bar#md5=f12895fdffbd45007040d2e44df98478')
  171. self.assertEqual(checker.hash_name, 'md5')
  172. def test_report(self):
  173. checker = setuptools.package_index.HashChecker.from_url(
  174. 'http://foo/bar#md5=f12895fdffbd45007040d2e44df98478')
  175. rep = checker.report(lambda x: x, 'My message about %s')
  176. self.assertEqual(rep, 'My message about md5')