test_resources.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # NOTE: the shebang and encoding lines are for ScriptHeaderTests do not remove
  4. import os
  5. import sys
  6. import tempfile
  7. import shutil
  8. from unittest import TestCase
  9. import pkg_resources
  10. from pkg_resources import (parse_requirements, VersionConflict, parse_version,
  11. Distribution, EntryPoint, Requirement, safe_version, safe_name,
  12. WorkingSet)
  13. from setuptools.command.easy_install import (get_script_header, is_sh,
  14. nt_quote_arg)
  15. from setuptools.compat import StringIO, iteritems
  16. try:
  17. frozenset
  18. except NameError:
  19. from sets import ImmutableSet as frozenset
  20. def safe_repr(obj, short=False):
  21. """ copied from Python2.7"""
  22. try:
  23. result = repr(obj)
  24. except Exception:
  25. result = object.__repr__(obj)
  26. if not short or len(result) < pkg_resources._MAX_LENGTH:
  27. return result
  28. return result[:pkg_resources._MAX_LENGTH] + ' [truncated]...'
  29. class Metadata(pkg_resources.EmptyProvider):
  30. """Mock object to return metadata as if from an on-disk distribution"""
  31. def __init__(self,*pairs):
  32. self.metadata = dict(pairs)
  33. def has_metadata(self,name):
  34. return name in self.metadata
  35. def get_metadata(self,name):
  36. return self.metadata[name]
  37. def get_metadata_lines(self,name):
  38. return pkg_resources.yield_lines(self.get_metadata(name))
  39. dist_from_fn = pkg_resources.Distribution.from_filename
  40. class DistroTests(TestCase):
  41. def testCollection(self):
  42. # empty path should produce no distributions
  43. ad = pkg_resources.Environment([], platform=None, python=None)
  44. self.assertEqual(list(ad), [])
  45. self.assertEqual(ad['FooPkg'],[])
  46. ad.add(dist_from_fn("FooPkg-1.3_1.egg"))
  47. ad.add(dist_from_fn("FooPkg-1.4-py2.4-win32.egg"))
  48. ad.add(dist_from_fn("FooPkg-1.2-py2.4.egg"))
  49. # Name is in there now
  50. self.assertTrue(ad['FooPkg'])
  51. # But only 1 package
  52. self.assertEqual(list(ad), ['foopkg'])
  53. # Distributions sort by version
  54. self.assertEqual(
  55. [dist.version for dist in ad['FooPkg']], ['1.4','1.3-1','1.2']
  56. )
  57. # Removing a distribution leaves sequence alone
  58. ad.remove(ad['FooPkg'][1])
  59. self.assertEqual(
  60. [dist.version for dist in ad['FooPkg']], ['1.4','1.2']
  61. )
  62. # And inserting adds them in order
  63. ad.add(dist_from_fn("FooPkg-1.9.egg"))
  64. self.assertEqual(
  65. [dist.version for dist in ad['FooPkg']], ['1.9','1.4','1.2']
  66. )
  67. ws = WorkingSet([])
  68. foo12 = dist_from_fn("FooPkg-1.2-py2.4.egg")
  69. foo14 = dist_from_fn("FooPkg-1.4-py2.4-win32.egg")
  70. req, = parse_requirements("FooPkg>=1.3")
  71. # Nominal case: no distros on path, should yield all applicable
  72. self.assertEqual(ad.best_match(req,ws).version, '1.9')
  73. # If a matching distro is already installed, should return only that
  74. ws.add(foo14)
  75. self.assertEqual(ad.best_match(req,ws).version, '1.4')
  76. # If the first matching distro is unsuitable, it's a version conflict
  77. ws = WorkingSet([])
  78. ws.add(foo12)
  79. ws.add(foo14)
  80. self.assertRaises(VersionConflict, ad.best_match, req, ws)
  81. # If more than one match on the path, the first one takes precedence
  82. ws = WorkingSet([])
  83. ws.add(foo14)
  84. ws.add(foo12)
  85. ws.add(foo14)
  86. self.assertEqual(ad.best_match(req,ws).version, '1.4')
  87. def checkFooPkg(self,d):
  88. self.assertEqual(d.project_name, "FooPkg")
  89. self.assertEqual(d.key, "foopkg")
  90. self.assertEqual(d.version, "1.3-1")
  91. self.assertEqual(d.py_version, "2.4")
  92. self.assertEqual(d.platform, "win32")
  93. self.assertEqual(d.parsed_version, parse_version("1.3-1"))
  94. def testDistroBasics(self):
  95. d = Distribution(
  96. "/some/path",
  97. project_name="FooPkg",version="1.3-1",py_version="2.4",platform="win32"
  98. )
  99. self.checkFooPkg(d)
  100. d = Distribution("/some/path")
  101. self.assertEqual(d.py_version, sys.version[:3])
  102. self.assertEqual(d.platform, None)
  103. def testDistroParse(self):
  104. d = dist_from_fn("FooPkg-1.3_1-py2.4-win32.egg")
  105. self.checkFooPkg(d)
  106. d = dist_from_fn("FooPkg-1.3_1-py2.4-win32.egg-info")
  107. self.checkFooPkg(d)
  108. def testDistroMetadata(self):
  109. d = Distribution(
  110. "/some/path", project_name="FooPkg", py_version="2.4", platform="win32",
  111. metadata = Metadata(
  112. ('PKG-INFO',"Metadata-Version: 1.0\nVersion: 1.3-1\n")
  113. )
  114. )
  115. self.checkFooPkg(d)
  116. def distRequires(self, txt):
  117. return Distribution("/foo", metadata=Metadata(('depends.txt', txt)))
  118. def checkRequires(self, dist, txt, extras=()):
  119. self.assertEqual(
  120. list(dist.requires(extras)),
  121. list(parse_requirements(txt))
  122. )
  123. def testDistroDependsSimple(self):
  124. for v in "Twisted>=1.5", "Twisted>=1.5\nZConfig>=2.0":
  125. self.checkRequires(self.distRequires(v), v)
  126. def testResolve(self):
  127. ad = pkg_resources.Environment([])
  128. ws = WorkingSet([])
  129. # Resolving no requirements -> nothing to install
  130. self.assertEqual(list(ws.resolve([],ad)), [])
  131. # Request something not in the collection -> DistributionNotFound
  132. self.assertRaises(
  133. pkg_resources.DistributionNotFound, ws.resolve, parse_requirements("Foo"), ad
  134. )
  135. Foo = Distribution.from_filename(
  136. "/foo_dir/Foo-1.2.egg",
  137. metadata=Metadata(('depends.txt', "[bar]\nBaz>=2.0"))
  138. )
  139. ad.add(Foo)
  140. ad.add(Distribution.from_filename("Foo-0.9.egg"))
  141. # Request thing(s) that are available -> list to activate
  142. for i in range(3):
  143. targets = list(ws.resolve(parse_requirements("Foo"), ad))
  144. self.assertEqual(targets, [Foo])
  145. list(map(ws.add,targets))
  146. self.assertRaises(VersionConflict, ws.resolve,
  147. parse_requirements("Foo==0.9"), ad)
  148. ws = WorkingSet([]) # reset
  149. # Request an extra that causes an unresolved dependency for "Baz"
  150. self.assertRaises(
  151. pkg_resources.DistributionNotFound, ws.resolve,parse_requirements("Foo[bar]"), ad
  152. )
  153. Baz = Distribution.from_filename(
  154. "/foo_dir/Baz-2.1.egg", metadata=Metadata(('depends.txt', "Foo"))
  155. )
  156. ad.add(Baz)
  157. # Activation list now includes resolved dependency
  158. self.assertEqual(
  159. list(ws.resolve(parse_requirements("Foo[bar]"), ad)), [Foo,Baz]
  160. )
  161. # Requests for conflicting versions produce VersionConflict
  162. self.assertRaises(VersionConflict,
  163. ws.resolve, parse_requirements("Foo==1.2\nFoo!=1.2"), ad)
  164. def testDistroDependsOptions(self):
  165. d = self.distRequires("""
  166. Twisted>=1.5
  167. [docgen]
  168. ZConfig>=2.0
  169. docutils>=0.3
  170. [fastcgi]
  171. fcgiapp>=0.1""")
  172. self.checkRequires(d,"Twisted>=1.5")
  173. self.checkRequires(
  174. d,"Twisted>=1.5 ZConfig>=2.0 docutils>=0.3".split(), ["docgen"]
  175. )
  176. self.checkRequires(
  177. d,"Twisted>=1.5 fcgiapp>=0.1".split(), ["fastcgi"]
  178. )
  179. self.checkRequires(
  180. d,"Twisted>=1.5 ZConfig>=2.0 docutils>=0.3 fcgiapp>=0.1".split(),
  181. ["docgen","fastcgi"]
  182. )
  183. self.checkRequires(
  184. d,"Twisted>=1.5 fcgiapp>=0.1 ZConfig>=2.0 docutils>=0.3".split(),
  185. ["fastcgi", "docgen"]
  186. )
  187. self.assertRaises(pkg_resources.UnknownExtra, d.requires, ["foo"])
  188. class EntryPointTests(TestCase):
  189. def assertfields(self, ep):
  190. self.assertEqual(ep.name,"foo")
  191. self.assertEqual(ep.module_name,"setuptools.tests.test_resources")
  192. self.assertEqual(ep.attrs, ("EntryPointTests",))
  193. self.assertEqual(ep.extras, ("x",))
  194. self.assertTrue(ep.load() is EntryPointTests)
  195. self.assertEqual(
  196. str(ep),
  197. "foo = setuptools.tests.test_resources:EntryPointTests [x]"
  198. )
  199. def setUp(self):
  200. self.dist = Distribution.from_filename(
  201. "FooPkg-1.2-py2.4.egg", metadata=Metadata(('requires.txt','[x]')))
  202. def testBasics(self):
  203. ep = EntryPoint(
  204. "foo", "setuptools.tests.test_resources", ["EntryPointTests"],
  205. ["x"], self.dist
  206. )
  207. self.assertfields(ep)
  208. def testParse(self):
  209. s = "foo = setuptools.tests.test_resources:EntryPointTests [x]"
  210. ep = EntryPoint.parse(s, self.dist)
  211. self.assertfields(ep)
  212. ep = EntryPoint.parse("bar baz= spammity[PING]")
  213. self.assertEqual(ep.name,"bar baz")
  214. self.assertEqual(ep.module_name,"spammity")
  215. self.assertEqual(ep.attrs, ())
  216. self.assertEqual(ep.extras, ("ping",))
  217. ep = EntryPoint.parse(" fizzly = wocka:foo")
  218. self.assertEqual(ep.name,"fizzly")
  219. self.assertEqual(ep.module_name,"wocka")
  220. self.assertEqual(ep.attrs, ("foo",))
  221. self.assertEqual(ep.extras, ())
  222. def testRejects(self):
  223. for ep in [
  224. "foo", "x=1=2", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2",
  225. ]:
  226. try: EntryPoint.parse(ep)
  227. except ValueError: pass
  228. else: raise AssertionError("Should've been bad", ep)
  229. def checkSubMap(self, m):
  230. self.assertEqual(len(m), len(self.submap_expect))
  231. for key, ep in iteritems(self.submap_expect):
  232. self.assertEqual(repr(m.get(key)), repr(ep))
  233. submap_expect = dict(
  234. feature1=EntryPoint('feature1', 'somemodule', ['somefunction']),
  235. feature2=EntryPoint('feature2', 'another.module', ['SomeClass'], ['extra1','extra2']),
  236. feature3=EntryPoint('feature3', 'this.module', extras=['something'])
  237. )
  238. submap_str = """
  239. # define features for blah blah
  240. feature1 = somemodule:somefunction
  241. feature2 = another.module:SomeClass [extra1,extra2]
  242. feature3 = this.module [something]
  243. """
  244. def testParseList(self):
  245. self.checkSubMap(EntryPoint.parse_group("xyz", self.submap_str))
  246. self.assertRaises(ValueError, EntryPoint.parse_group, "x a", "foo=bar")
  247. self.assertRaises(ValueError, EntryPoint.parse_group, "x",
  248. ["foo=baz", "foo=bar"])
  249. def testParseMap(self):
  250. m = EntryPoint.parse_map({'xyz':self.submap_str})
  251. self.checkSubMap(m['xyz'])
  252. self.assertEqual(list(m.keys()),['xyz'])
  253. m = EntryPoint.parse_map("[xyz]\n"+self.submap_str)
  254. self.checkSubMap(m['xyz'])
  255. self.assertEqual(list(m.keys()),['xyz'])
  256. self.assertRaises(ValueError, EntryPoint.parse_map, ["[xyz]", "[xyz]"])
  257. self.assertRaises(ValueError, EntryPoint.parse_map, self.submap_str)
  258. class RequirementsTests(TestCase):
  259. def testBasics(self):
  260. r = Requirement.parse("Twisted>=1.2")
  261. self.assertEqual(str(r),"Twisted>=1.2")
  262. self.assertEqual(repr(r),"Requirement.parse('Twisted>=1.2')")
  263. self.assertEqual(r, Requirement("Twisted", [('>=','1.2')], ()))
  264. self.assertEqual(r, Requirement("twisTed", [('>=','1.2')], ()))
  265. self.assertNotEqual(r, Requirement("Twisted", [('>=','2.0')], ()))
  266. self.assertNotEqual(r, Requirement("Zope", [('>=','1.2')], ()))
  267. self.assertNotEqual(r, Requirement("Zope", [('>=','3.0')], ()))
  268. self.assertNotEqual(r, Requirement.parse("Twisted[extras]>=1.2"))
  269. def testOrdering(self):
  270. r1 = Requirement("Twisted", [('==','1.2c1'),('>=','1.2')], ())
  271. r2 = Requirement("Twisted", [('>=','1.2'),('==','1.2c1')], ())
  272. self.assertEqual(r1,r2)
  273. self.assertEqual(str(r1),str(r2))
  274. self.assertEqual(str(r2),"Twisted==1.2c1,>=1.2")
  275. def testBasicContains(self):
  276. r = Requirement("Twisted", [('>=','1.2')], ())
  277. foo_dist = Distribution.from_filename("FooPkg-1.3_1.egg")
  278. twist11 = Distribution.from_filename("Twisted-1.1.egg")
  279. twist12 = Distribution.from_filename("Twisted-1.2.egg")
  280. self.assertTrue(parse_version('1.2') in r)
  281. self.assertTrue(parse_version('1.1') not in r)
  282. self.assertTrue('1.2' in r)
  283. self.assertTrue('1.1' not in r)
  284. self.assertTrue(foo_dist not in r)
  285. self.assertTrue(twist11 not in r)
  286. self.assertTrue(twist12 in r)
  287. def testAdvancedContains(self):
  288. r, = parse_requirements("Foo>=1.2,<=1.3,==1.9,>2.0,!=2.5,<3.0,==4.5")
  289. for v in ('1.2','1.2.2','1.3','1.9','2.0.1','2.3','2.6','3.0c1','4.5'):
  290. self.assertTrue(v in r, (v,r))
  291. for v in ('1.2c1','1.3.1','1.5','1.9.1','2.0','2.5','3.0','4.0'):
  292. self.assertTrue(v not in r, (v,r))
  293. def testOptionsAndHashing(self):
  294. r1 = Requirement.parse("Twisted[foo,bar]>=1.2")
  295. r2 = Requirement.parse("Twisted[bar,FOO]>=1.2")
  296. r3 = Requirement.parse("Twisted[BAR,FOO]>=1.2.0")
  297. self.assertEqual(r1,r2)
  298. self.assertEqual(r1,r3)
  299. self.assertEqual(r1.extras, ("foo","bar"))
  300. self.assertEqual(r2.extras, ("bar","foo")) # extras are normalized
  301. self.assertEqual(hash(r1), hash(r2))
  302. self.assertEqual(
  303. hash(r1), hash(("twisted", ((">=",parse_version("1.2")),),
  304. frozenset(["foo","bar"])))
  305. )
  306. def testVersionEquality(self):
  307. r1 = Requirement.parse("foo==0.3a2")
  308. r2 = Requirement.parse("foo!=0.3a4")
  309. d = Distribution.from_filename
  310. self.assertTrue(d("foo-0.3a4.egg") not in r1)
  311. self.assertTrue(d("foo-0.3a1.egg") not in r1)
  312. self.assertTrue(d("foo-0.3a4.egg") not in r2)
  313. self.assertTrue(d("foo-0.3a2.egg") in r1)
  314. self.assertTrue(d("foo-0.3a2.egg") in r2)
  315. self.assertTrue(d("foo-0.3a3.egg") in r2)
  316. self.assertTrue(d("foo-0.3a5.egg") in r2)
  317. def testSetuptoolsProjectName(self):
  318. """
  319. The setuptools project should implement the setuptools package.
  320. """
  321. self.assertEqual(
  322. Requirement.parse('setuptools').project_name, 'setuptools')
  323. # setuptools 0.7 and higher means setuptools.
  324. self.assertEqual(
  325. Requirement.parse('setuptools == 0.7').project_name, 'setuptools')
  326. self.assertEqual(
  327. Requirement.parse('setuptools == 0.7a1').project_name, 'setuptools')
  328. self.assertEqual(
  329. Requirement.parse('setuptools >= 0.7').project_name, 'setuptools')
  330. class ParseTests(TestCase):
  331. def testEmptyParse(self):
  332. self.assertEqual(list(parse_requirements('')), [])
  333. def testYielding(self):
  334. for inp,out in [
  335. ([], []), ('x',['x']), ([[]],[]), (' x\n y', ['x','y']),
  336. (['x\n\n','y'], ['x','y']),
  337. ]:
  338. self.assertEqual(list(pkg_resources.yield_lines(inp)),out)
  339. def testSplitting(self):
  340. sample = """
  341. x
  342. [Y]
  343. z
  344. a
  345. [b ]
  346. # foo
  347. c
  348. [ d]
  349. [q]
  350. v
  351. """
  352. self.assertEqual(list(pkg_resources.split_sections(sample)),
  353. [(None,["x"]), ("Y",["z","a"]), ("b",["c"]), ("d",[]), ("q",["v"])]
  354. )
  355. self.assertRaises(ValueError,list,pkg_resources.split_sections("[foo"))
  356. def testSafeName(self):
  357. self.assertEqual(safe_name("adns-python"), "adns-python")
  358. self.assertEqual(safe_name("WSGI Utils"), "WSGI-Utils")
  359. self.assertEqual(safe_name("WSGI Utils"), "WSGI-Utils")
  360. self.assertEqual(safe_name("Money$$$Maker"), "Money-Maker")
  361. self.assertNotEqual(safe_name("peak.web"), "peak-web")
  362. def testSafeVersion(self):
  363. self.assertEqual(safe_version("1.2-1"), "1.2-1")
  364. self.assertEqual(safe_version("1.2 alpha"), "1.2.alpha")
  365. self.assertEqual(safe_version("2.3.4 20050521"), "2.3.4.20050521")
  366. self.assertEqual(safe_version("Money$$$Maker"), "Money-Maker")
  367. self.assertEqual(safe_version("peak.web"), "peak.web")
  368. def testSimpleRequirements(self):
  369. self.assertEqual(
  370. list(parse_requirements('Twis-Ted>=1.2-1')),
  371. [Requirement('Twis-Ted',[('>=','1.2-1')], ())]
  372. )
  373. self.assertEqual(
  374. list(parse_requirements('Twisted >=1.2, \ # more\n<2.0')),
  375. [Requirement('Twisted',[('>=','1.2'),('<','2.0')], ())]
  376. )
  377. self.assertEqual(
  378. Requirement.parse("FooBar==1.99a3"),
  379. Requirement("FooBar", [('==','1.99a3')], ())
  380. )
  381. self.assertRaises(ValueError,Requirement.parse,">=2.3")
  382. self.assertRaises(ValueError,Requirement.parse,"x\\")
  383. self.assertRaises(ValueError,Requirement.parse,"x==2 q")
  384. self.assertRaises(ValueError,Requirement.parse,"X==1\nY==2")
  385. self.assertRaises(ValueError,Requirement.parse,"#")
  386. def testVersionEquality(self):
  387. def c(s1,s2):
  388. p1, p2 = parse_version(s1),parse_version(s2)
  389. self.assertEqual(p1,p2, (s1,s2,p1,p2))
  390. c('1.2-rc1', '1.2rc1')
  391. c('0.4', '0.4.0')
  392. c('0.4.0.0', '0.4.0')
  393. c('0.4.0-0', '0.4-0')
  394. c('0pl1', '0.0pl1')
  395. c('0pre1', '0.0c1')
  396. c('0.0.0preview1', '0c1')
  397. c('0.0c1', '0-rc1')
  398. c('1.2a1', '1.2.a.1')
  399. c('1.2...a', '1.2a')
  400. def testVersionOrdering(self):
  401. def c(s1,s2):
  402. p1, p2 = parse_version(s1),parse_version(s2)
  403. self.assertTrue(p1<p2, (s1,s2,p1,p2))
  404. c('2.1','2.1.1')
  405. c('2a1','2b0')
  406. c('2a1','2.1')
  407. c('2.3a1', '2.3')
  408. c('2.1-1', '2.1-2')
  409. c('2.1-1', '2.1.1')
  410. c('2.1', '2.1pl4')
  411. c('2.1a0-20040501', '2.1')
  412. c('1.1', '02.1')
  413. c('A56','B27')
  414. c('3.2', '3.2.pl0')
  415. c('3.2-1', '3.2pl1')
  416. c('3.2pl1', '3.2pl1-1')
  417. c('0.4', '4.0')
  418. c('0.0.4', '0.4.0')
  419. c('0pl1', '0.4pl1')
  420. c('2.1.0-rc1','2.1.0')
  421. c('2.1dev','2.1a0')
  422. torture ="""
  423. 0.80.1-3 0.80.1-2 0.80.1-1 0.79.9999+0.80.0pre4-1
  424. 0.79.9999+0.80.0pre2-3 0.79.9999+0.80.0pre2-2
  425. 0.77.2-1 0.77.1-1 0.77.0-1
  426. """.split()
  427. for p,v1 in enumerate(torture):
  428. for v2 in torture[p+1:]:
  429. c(v2,v1)
  430. class ScriptHeaderTests(TestCase):
  431. non_ascii_exe = '/Users/José/bin/python'
  432. exe_with_spaces = r'C:\Program Files\Python33\python.exe'
  433. def test_get_script_header(self):
  434. if not sys.platform.startswith('java') or not is_sh(sys.executable):
  435. # This test is for non-Jython platforms
  436. expected = '#!%s\n' % nt_quote_arg(os.path.normpath(sys.executable))
  437. self.assertEqual(get_script_header('#!/usr/local/bin/python'),
  438. expected)
  439. expected = '#!%s -x\n' % nt_quote_arg(os.path.normpath(sys.executable))
  440. self.assertEqual(get_script_header('#!/usr/bin/python -x'),
  441. expected)
  442. self.assertEqual(get_script_header('#!/usr/bin/python',
  443. executable=self.non_ascii_exe),
  444. '#!%s -x\n' % self.non_ascii_exe)
  445. candidate = get_script_header('#!/usr/bin/python',
  446. executable=self.exe_with_spaces)
  447. self.assertEqual(candidate, '#!"%s"\n' % self.exe_with_spaces)
  448. def test_get_script_header_jython_workaround(self):
  449. # This test doesn't work with Python 3 in some locales
  450. if (sys.version_info >= (3,) and os.environ.get("LC_CTYPE")
  451. in (None, "C", "POSIX")):
  452. return
  453. class java:
  454. class lang:
  455. class System:
  456. @staticmethod
  457. def getProperty(property):
  458. return ""
  459. sys.modules["java"] = java
  460. platform = sys.platform
  461. sys.platform = 'java1.5.0_13'
  462. stdout, stderr = sys.stdout, sys.stderr
  463. try:
  464. # A mock sys.executable that uses a shebang line (this file)
  465. exe = os.path.normpath(os.path.splitext(__file__)[0] + '.py')
  466. self.assertEqual(
  467. get_script_header('#!/usr/local/bin/python', executable=exe),
  468. '#!/usr/bin/env %s\n' % exe)
  469. # Ensure we generate what is basically a broken shebang line
  470. # when there's options, with a warning emitted
  471. sys.stdout = sys.stderr = StringIO()
  472. self.assertEqual(get_script_header('#!/usr/bin/python -x',
  473. executable=exe),
  474. '#!%s -x\n' % exe)
  475. self.assertTrue('Unable to adapt shebang line' in sys.stdout.getvalue())
  476. sys.stdout = sys.stderr = StringIO()
  477. self.assertEqual(get_script_header('#!/usr/bin/python',
  478. executable=self.non_ascii_exe),
  479. '#!%s -x\n' % self.non_ascii_exe)
  480. self.assertTrue('Unable to adapt shebang line' in sys.stdout.getvalue())
  481. finally:
  482. del sys.modules["java"]
  483. sys.platform = platform
  484. sys.stdout, sys.stderr = stdout, stderr
  485. class NamespaceTests(TestCase):
  486. def setUp(self):
  487. self._ns_pkgs = pkg_resources._namespace_packages.copy()
  488. self._tmpdir = tempfile.mkdtemp(prefix="tests-setuptools-")
  489. os.makedirs(os.path.join(self._tmpdir, "site-pkgs"))
  490. self._prev_sys_path = sys.path[:]
  491. sys.path.append(os.path.join(self._tmpdir, "site-pkgs"))
  492. def tearDown(self):
  493. shutil.rmtree(self._tmpdir)
  494. pkg_resources._namespace_packages = self._ns_pkgs.copy()
  495. sys.path = self._prev_sys_path[:]
  496. def _assertIn(self, member, container):
  497. """ assertIn and assertTrue does not exist in Python2.3"""
  498. if member not in container:
  499. standardMsg = '%s not found in %s' % (safe_repr(member),
  500. safe_repr(container))
  501. self.fail(self._formatMessage(msg, standardMsg))
  502. def test_two_levels_deep(self):
  503. """
  504. Test nested namespace packages
  505. Create namespace packages in the following tree :
  506. site-packages-1/pkg1/pkg2
  507. site-packages-2/pkg1/pkg2
  508. Check both are in the _namespace_packages dict and that their __path__
  509. is correct
  510. """
  511. sys.path.append(os.path.join(self._tmpdir, "site-pkgs2"))
  512. os.makedirs(os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2"))
  513. os.makedirs(os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2"))
  514. ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n"
  515. for site in ["site-pkgs", "site-pkgs2"]:
  516. pkg1_init = open(os.path.join(self._tmpdir, site,
  517. "pkg1", "__init__.py"), "w")
  518. pkg1_init.write(ns_str)
  519. pkg1_init.close()
  520. pkg2_init = open(os.path.join(self._tmpdir, site,
  521. "pkg1", "pkg2", "__init__.py"), "w")
  522. pkg2_init.write(ns_str)
  523. pkg2_init.close()
  524. import pkg1
  525. self._assertIn("pkg1", pkg_resources._namespace_packages.keys())
  526. try:
  527. import pkg1.pkg2
  528. except ImportError:
  529. self.fail("Setuptools tried to import the parent namespace package")
  530. # check the _namespace_packages dict
  531. self._assertIn("pkg1.pkg2", pkg_resources._namespace_packages.keys())
  532. self.assertEqual(pkg_resources._namespace_packages["pkg1"], ["pkg1.pkg2"])
  533. # check the __path__ attribute contains both paths
  534. self.assertEqual(pkg1.pkg2.__path__, [
  535. os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2"),
  536. os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2")])