blob: 5c95cdaa03be8e3dcf39718678fdd7bcaa26e2b4 [file] [log] [blame]
Tarek Ziade1231a4e2011-05-19 13:07:25 +02001import os
2import io
3import csv
Tarek Ziade1231a4e2011-05-19 13:07:25 +02004import sys
5import shutil
Tarek Ziade1231a4e2011-05-19 13:07:25 +02006import tempfile
Tarek Ziade1231a4e2011-05-19 13:07:25 +02007from hashlib import md5
Tarek Ziadea17d8882011-05-30 10:57:44 +02008from textwrap import dedent
Tarek Ziade1231a4e2011-05-19 13:07:25 +02009
Tarek Ziadea17d8882011-05-30 10:57:44 +020010from packaging.tests.test_util import GlobTestCaseBase
11from packaging.tests.support import requires_zlib
12
13from packaging.config import get_resources_dests
Tarek Ziade1231a4e2011-05-19 13:07:25 +020014from packaging.errors import PackagingError
15from packaging.metadata import Metadata
Tarek Ziade43f289a2011-05-30 11:07:54 +020016from packaging.tests import unittest, support
Tarek Ziade1231a4e2011-05-19 13:07:25 +020017from packaging.database import (
18 Distribution, EggInfoDistribution, get_distribution, get_distributions,
19 provides_distribution, obsoletes_distribution, get_file_users,
Tarek Ziadea17d8882011-05-30 10:57:44 +020020 enable_cache, disable_cache, distinfo_dirname, _yield_distributions,
21 get_file, get_file_path)
Tarek Ziade1231a4e2011-05-19 13:07:25 +020022
23# TODO Add a test for getting a distribution provided by another distribution
24# TODO Add a test for absolute pathed RECORD items (e.g. /etc/myapp/config.ini)
25# TODO Add tests from the former pep376 project (zipped site-packages, etc.)
26
27
28def get_hexdigest(filename):
29 with open(filename, 'rb') as file:
30 checksum = md5(file.read())
31 return checksum.hexdigest()
32
33
Éric Araujo37ccd6f2011-09-15 18:18:51 +020034def record_pieces(path):
35 path = os.path.join(*path)
36 digest = get_hexdigest(path)
37 size = os.path.getsize(path)
38 return path, digest, size
Tarek Ziade1231a4e2011-05-19 13:07:25 +020039
40
Éric Araujob85b9662011-07-31 20:47:47 +020041class FakeDistsMixin:
42
43 def setUp(self):
44 super(FakeDistsMixin, self).setUp()
45 self.addCleanup(enable_cache)
46 disable_cache()
47
48 # make a copy that we can write into for our fake installed
49 # distributions
50 tmpdir = tempfile.mkdtemp()
51 self.addCleanup(shutil.rmtree, tmpdir)
52 self.fake_dists_path = os.path.join(tmpdir, 'fake_dists')
53 fake_dists_src = os.path.abspath(
54 os.path.join(os.path.dirname(__file__), 'fake_dists'))
55 shutil.copytree(fake_dists_src, self.fake_dists_path)
56 # XXX ugly workaround: revert copystat calls done by shutil behind our
57 # back (to avoid getting a read-only copy of a read-only file). we
58 # could pass a custom copy_function to change the mode of files, but
59 # shutil gives no control over the mode of directories :(
60 for root, dirs, files in os.walk(self.fake_dists_path):
61 os.chmod(root, 0o755)
62 for f in files:
63 os.chmod(os.path.join(root, f), 0o644)
64 for d in dirs:
65 os.chmod(os.path.join(root, d), 0o755)
66
67
68class CommonDistributionTests(FakeDistsMixin):
Tarek Ziade1231a4e2011-05-19 13:07:25 +020069 """Mixin used to test the interface common to both Distribution classes.
70
71 Derived classes define cls, sample_dist, dirs and records. These
72 attributes are used in test methods. See source code for details.
73 """
74
Tarek Ziade1231a4e2011-05-19 13:07:25 +020075 def test_instantiation(self):
76 # check that useful attributes are here
77 name, version, distdir = self.sample_dist
78 here = os.path.abspath(os.path.dirname(__file__))
79 dist_path = os.path.join(here, 'fake_dists', distdir)
80
81 dist = self.dist = self.cls(dist_path)
82 self.assertEqual(dist.path, dist_path)
83 self.assertEqual(dist.name, name)
84 self.assertEqual(dist.metadata['Name'], name)
85 self.assertIsInstance(dist.metadata, Metadata)
86 self.assertEqual(dist.version, version)
87 self.assertEqual(dist.metadata['Version'], version)
88
Ezio Melotticad648c2011-05-19 21:25:10 +030089 @requires_zlib
Tarek Ziade1231a4e2011-05-19 13:07:25 +020090 def test_repr(self):
91 dist = self.cls(self.dirs[0])
92 # just check that the class name is in the repr
93 self.assertIn(self.cls.__name__, repr(dist))
94
Ezio Melotticad648c2011-05-19 21:25:10 +030095 @requires_zlib
Tarek Ziade1231a4e2011-05-19 13:07:25 +020096 def test_comparison(self):
97 # tests for __eq__ and __hash__
98 dist = self.cls(self.dirs[0])
99 dist2 = self.cls(self.dirs[0])
100 dist3 = self.cls(self.dirs[1])
101 self.assertIn(dist, {dist: True})
102 self.assertEqual(dist, dist)
103
104 self.assertIsNot(dist, dist2)
105 self.assertEqual(dist, dist2)
106 self.assertNotEqual(dist, dist3)
107 self.assertNotEqual(dist, ())
108
109 def test_list_installed_files(self):
110 for dir_ in self.dirs:
111 dist = self.cls(dir_)
112 for path, md5_, size in dist.list_installed_files():
113 record_data = self.records[dist.path]
114 self.assertIn(path, record_data)
115 self.assertEqual(md5_, record_data[path][0])
116 self.assertEqual(size, record_data[path][1])
117
118
119class TestDistribution(CommonDistributionTests, unittest.TestCase):
120
121 cls = Distribution
122 sample_dist = 'choxie', '2.0.0.9', 'choxie-2.0.0.9.dist-info'
123
124 def setUp(self):
125 super(TestDistribution, self).setUp()
126 self.dirs = [os.path.join(self.fake_dists_path, f)
127 for f in os.listdir(self.fake_dists_path)
128 if f.endswith('.dist-info')]
129
130 self.records = {}
131 for distinfo_dir in self.dirs:
Éric Araujob85b9662011-07-31 20:47:47 +0200132
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200133 record_file = os.path.join(distinfo_dir, 'RECORD')
134 with open(record_file, 'w') as file:
135 record_writer = csv.writer(
Tarek Ziadebe20be12011-05-21 19:45:48 +0200136 file, delimiter=',', quoting=csv.QUOTE_NONE,
137 lineterminator='\n')
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200138
139 dist_location = distinfo_dir.replace('.dist-info', '')
140
141 for path, dirs, files in os.walk(dist_location):
142 for f in files:
Éric Araujo37ccd6f2011-09-15 18:18:51 +0200143 record_writer.writerow(record_pieces((path, f)))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200144 for file in ('INSTALLER', 'METADATA', 'REQUESTED'):
Éric Araujo37ccd6f2011-09-15 18:18:51 +0200145 record_writer.writerow(record_pieces((distinfo_dir, file)))
146 record_writer.writerow([record_file])
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200147
148 with open(record_file) as file:
Tarek Ziadebe20be12011-05-21 19:45:48 +0200149 record_reader = csv.reader(file, lineterminator='\n')
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200150 record_data = {}
151 for row in record_reader:
Tarek Ziadebe20be12011-05-21 19:45:48 +0200152 if row == []:
153 continue
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200154 path, md5_, size = (row[:] +
155 [None for i in range(len(row), 3)])
156 record_data[path] = md5_, size
157 self.records[distinfo_dir] = record_data
158
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200159 def test_instantiation(self):
160 super(TestDistribution, self).test_instantiation()
161 self.assertIsInstance(self.dist.requested, bool)
162
163 def test_uses(self):
164 # Test to determine if a distribution uses a specified file.
165 # Criteria to test against
166 distinfo_name = 'grammar-1.0a4'
167 distinfo_dir = os.path.join(self.fake_dists_path,
168 distinfo_name + '.dist-info')
169 true_path = [self.fake_dists_path, distinfo_name,
170 'grammar', 'utils.py']
Éric Araujo37ccd6f2011-09-15 18:18:51 +0200171 true_path = os.path.join(*true_path)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200172 false_path = [self.fake_dists_path, 'towel_stuff-0.1', 'towel_stuff',
173 '__init__.py']
Éric Araujo37ccd6f2011-09-15 18:18:51 +0200174 false_path = os.path.join(*false_path)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200175
176 # Test if the distribution uses the file in question
177 dist = Distribution(distinfo_dir)
Éric Araujo37ccd6f2011-09-15 18:18:51 +0200178 self.assertTrue(dist.uses(true_path), 'dist %r is supposed to use %r' %
179 (dist, true_path))
180 self.assertFalse(dist.uses(false_path), 'dist %r is not supposed to '
181 'use %r' % (dist, true_path))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200182
183 def test_get_distinfo_file(self):
184 # Test the retrieval of dist-info file objects.
185 distinfo_name = 'choxie-2.0.0.9'
186 other_distinfo_name = 'grammar-1.0a4'
187 distinfo_dir = os.path.join(self.fake_dists_path,
188 distinfo_name + '.dist-info')
189 dist = Distribution(distinfo_dir)
190 # Test for known good file matches
191 distinfo_files = [
192 # Relative paths
193 'INSTALLER', 'METADATA',
194 # Absolute paths
195 os.path.join(distinfo_dir, 'RECORD'),
196 os.path.join(distinfo_dir, 'REQUESTED'),
197 ]
198
199 for distfile in distinfo_files:
200 with dist.get_distinfo_file(distfile) as value:
201 self.assertIsInstance(value, io.TextIOWrapper)
202 # Is it the correct file?
203 self.assertEqual(value.name,
204 os.path.join(distinfo_dir, distfile))
205
206 # Test an absolute path that is part of another distributions dist-info
207 other_distinfo_file = os.path.join(
208 self.fake_dists_path, other_distinfo_name + '.dist-info',
209 'REQUESTED')
210 self.assertRaises(PackagingError, dist.get_distinfo_file,
211 other_distinfo_file)
212 # Test for a file that should not exist
213 self.assertRaises(PackagingError, dist.get_distinfo_file,
214 'MAGICFILE')
215
216 def test_list_distinfo_files(self):
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200217 distinfo_name = 'towel_stuff-0.1'
218 distinfo_dir = os.path.join(self.fake_dists_path,
219 distinfo_name + '.dist-info')
220 dist = Distribution(distinfo_dir)
221 # Test for the iteration of the raw path
Éric Araujo37ccd6f2011-09-15 18:18:51 +0200222 distinfo_files = [os.path.join(distinfo_dir, filename) for filename in
223 os.listdir(distinfo_dir)]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200224 found = dist.list_distinfo_files()
Éric Araujo37ccd6f2011-09-15 18:18:51 +0200225 self.assertEqual(sorted(found), sorted(distinfo_files))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200226 # Test for the iteration of local absolute paths
Éric Araujo37ccd6f2011-09-15 18:18:51 +0200227 distinfo_files = [os.path.join(sys.prefix, distinfo_dir, path) for
228 path in distinfo_files]
229 found = sorted(dist.list_distinfo_files(local=True))
230 if os.sep != '/':
231 self.assertNotIn('/', found[0])
232 self.assertIn(os.sep, found[0])
233 self.assertEqual(found, sorted(distinfo_files))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200234
235 def test_get_resources_path(self):
236 distinfo_name = 'babar-0.1'
237 distinfo_dir = os.path.join(self.fake_dists_path,
238 distinfo_name + '.dist-info')
239 dist = Distribution(distinfo_dir)
240 resource_path = dist.get_resource_path('babar.png')
241 self.assertEqual(resource_path, 'babar.png')
242 self.assertRaises(KeyError, dist.get_resource_path, 'notexist')
243
244
245class TestEggInfoDistribution(CommonDistributionTests,
246 support.LoggingCatcher,
247 unittest.TestCase):
248
249 cls = EggInfoDistribution
250 sample_dist = 'bacon', '0.1', 'bacon-0.1.egg-info'
251
252 def setUp(self):
253 super(TestEggInfoDistribution, self).setUp()
254
255 self.dirs = [os.path.join(self.fake_dists_path, f)
256 for f in os.listdir(self.fake_dists_path)
257 if f.endswith('.egg') or f.endswith('.egg-info')]
258
259 self.records = {}
260
261 @unittest.skip('not implemented yet')
262 def test_list_installed_files(self):
263 # EggInfoDistribution defines list_installed_files but there is no
264 # test for it yet; someone with setuptools expertise needs to add a
265 # file with the list of installed files for one of the egg fake dists
266 # and write the support code to populate self.records (and then delete
267 # this method)
268 pass
269
270
271class TestDatabase(support.LoggingCatcher,
Éric Araujob85b9662011-07-31 20:47:47 +0200272 FakeDistsMixin,
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200273 unittest.TestCase):
274
275 def setUp(self):
276 super(TestDatabase, self).setUp()
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200277 sys.path.insert(0, self.fake_dists_path)
Éric Araujob85b9662011-07-31 20:47:47 +0200278 self.addCleanup(sys.path.remove, self.fake_dists_path)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200279
280 def test_distinfo_dirname(self):
281 # Given a name and a version, we expect the distinfo_dirname function
282 # to return a standard distribution information directory name.
283
284 items = [
285 # (name, version, standard_dirname)
286 # Test for a very simple single word name and decimal version
287 # number
288 ('docutils', '0.5', 'docutils-0.5.dist-info'),
289 # Test for another except this time with a '-' in the name, which
290 # needs to be transformed during the name lookup
291 ('python-ldap', '2.5', 'python_ldap-2.5.dist-info'),
292 # Test for both '-' in the name and a funky version number
293 ('python-ldap', '2.5 a---5', 'python_ldap-2.5 a---5.dist-info'),
294 ]
295
296 # Loop through the items to validate the results
297 for name, version, standard_dirname in items:
298 dirname = distinfo_dirname(name, version)
299 self.assertEqual(dirname, standard_dirname)
300
Ezio Melotticad648c2011-05-19 21:25:10 +0300301 @requires_zlib
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200302 def test_get_distributions(self):
303 # Lookup all distributions found in the ``sys.path``.
304 # This test could potentially pick up other installed distributions
305 fake_dists = [('grammar', '1.0a4'), ('choxie', '2.0.0.9'),
306 ('towel-stuff', '0.1'), ('babar', '0.1')]
307 found_dists = []
308
309 # Verify the fake dists have been found.
310 dists = [dist for dist in get_distributions()]
311 for dist in dists:
312 self.assertIsInstance(dist, Distribution)
313 if (dist.name in dict(fake_dists) and
314 dist.path.startswith(self.fake_dists_path)):
Éric Araujobab50cb2011-07-29 02:37:21 +0200315 found_dists.append((dist.name, dist.version))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200316 else:
317 # check that it doesn't find anything more than this
318 self.assertFalse(dist.path.startswith(self.fake_dists_path))
319 # otherwise we don't care what other distributions are found
320
321 # Finally, test that we found all that we were looking for
322 self.assertEqual(sorted(found_dists), sorted(fake_dists))
323
324 # Now, test if the egg-info distributions are found correctly as well
325 fake_dists += [('bacon', '0.1'), ('cheese', '2.0.2'),
326 ('coconuts-aster', '10.3'),
327 ('banana', '0.4'), ('strawberry', '0.6'),
328 ('truffles', '5.0'), ('nut', 'funkyversion')]
329 found_dists = []
330
331 dists = [dist for dist in get_distributions(use_egg_info=True)]
332 for dist in dists:
333 self.assertIsInstance(dist, (Distribution, EggInfoDistribution))
334 if (dist.name in dict(fake_dists) and
335 dist.path.startswith(self.fake_dists_path)):
Éric Araujobab50cb2011-07-29 02:37:21 +0200336 found_dists.append((dist.name, dist.version))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200337 else:
338 self.assertFalse(dist.path.startswith(self.fake_dists_path))
339
340 self.assertEqual(sorted(fake_dists), sorted(found_dists))
341
Ezio Melotticad648c2011-05-19 21:25:10 +0300342 @requires_zlib
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200343 def test_get_distribution(self):
344 # Test for looking up a distribution by name.
345 # Test the lookup of the towel-stuff distribution
346 name = 'towel-stuff' # Note: This is different from the directory name
347
348 # Lookup the distribution
349 dist = get_distribution(name)
350 self.assertIsInstance(dist, Distribution)
351 self.assertEqual(dist.name, name)
352
353 # Verify that an unknown distribution returns None
354 self.assertIsNone(get_distribution('bogus'))
355
356 # Verify partial name matching doesn't work
357 self.assertIsNone(get_distribution('towel'))
358
359 # Verify that it does not find egg-info distributions, when not
360 # instructed to
361 self.assertIsNone(get_distribution('bacon'))
362 self.assertIsNone(get_distribution('cheese'))
363 self.assertIsNone(get_distribution('strawberry'))
364 self.assertIsNone(get_distribution('banana'))
365
366 # Now check that it works well in both situations, when egg-info
367 # is a file and directory respectively.
368 dist = get_distribution('cheese', use_egg_info=True)
369 self.assertIsInstance(dist, EggInfoDistribution)
370 self.assertEqual(dist.name, 'cheese')
371
372 dist = get_distribution('bacon', use_egg_info=True)
373 self.assertIsInstance(dist, EggInfoDistribution)
374 self.assertEqual(dist.name, 'bacon')
375
376 dist = get_distribution('banana', use_egg_info=True)
377 self.assertIsInstance(dist, EggInfoDistribution)
378 self.assertEqual(dist.name, 'banana')
379
380 dist = get_distribution('strawberry', use_egg_info=True)
381 self.assertIsInstance(dist, EggInfoDistribution)
382 self.assertEqual(dist.name, 'strawberry')
383
384 def test_get_file_users(self):
385 # Test the iteration of distributions that use a file.
386 name = 'towel_stuff-0.1'
387 path = os.path.join(self.fake_dists_path, name,
388 'towel_stuff', '__init__.py')
389 for dist in get_file_users(path):
390 self.assertIsInstance(dist, Distribution)
391 self.assertEqual(dist.name, name)
392
Ezio Melotticad648c2011-05-19 21:25:10 +0300393 @requires_zlib
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200394 def test_provides(self):
395 # Test for looking up distributions by what they provide
396 checkLists = lambda x, y: self.assertEqual(sorted(x), sorted(y))
397
398 l = [dist.name for dist in provides_distribution('truffles')]
399 checkLists(l, ['choxie', 'towel-stuff'])
400
401 l = [dist.name for dist in provides_distribution('truffles', '1.0')]
402 checkLists(l, ['choxie'])
403
404 l = [dist.name for dist in provides_distribution('truffles', '1.0',
405 use_egg_info=True)]
406 checkLists(l, ['choxie', 'cheese'])
407
408 l = [dist.name for dist in provides_distribution('truffles', '1.1.2')]
409 checkLists(l, ['towel-stuff'])
410
411 l = [dist.name for dist in provides_distribution('truffles', '1.1')]
412 checkLists(l, ['towel-stuff'])
413
414 l = [dist.name for dist in provides_distribution('truffles',
415 '!=1.1,<=2.0')]
416 checkLists(l, ['choxie'])
417
418 l = [dist.name for dist in provides_distribution('truffles',
419 '!=1.1,<=2.0',
420 use_egg_info=True)]
421 checkLists(l, ['choxie', 'bacon', 'cheese'])
422
423 l = [dist.name for dist in provides_distribution('truffles', '>1.0')]
424 checkLists(l, ['towel-stuff'])
425
426 l = [dist.name for dist in provides_distribution('truffles', '>1.5')]
427 checkLists(l, [])
428
429 l = [dist.name for dist in provides_distribution('truffles', '>1.5',
430 use_egg_info=True)]
431 checkLists(l, ['bacon'])
432
433 l = [dist.name for dist in provides_distribution('truffles', '>=1.0')]
434 checkLists(l, ['choxie', 'towel-stuff'])
435
436 l = [dist.name for dist in provides_distribution('strawberry', '0.6',
437 use_egg_info=True)]
438 checkLists(l, ['coconuts-aster'])
439
440 l = [dist.name for dist in provides_distribution('strawberry', '>=0.5',
441 use_egg_info=True)]
442 checkLists(l, ['coconuts-aster'])
443
444 l = [dist.name for dist in provides_distribution('strawberry', '>0.6',
445 use_egg_info=True)]
446 checkLists(l, [])
447
448 l = [dist.name for dist in provides_distribution('banana', '0.4',
449 use_egg_info=True)]
450 checkLists(l, ['coconuts-aster'])
451
452 l = [dist.name for dist in provides_distribution('banana', '>=0.3',
453 use_egg_info=True)]
454 checkLists(l, ['coconuts-aster'])
455
456 l = [dist.name for dist in provides_distribution('banana', '!=0.4',
457 use_egg_info=True)]
458 checkLists(l, [])
459
Ezio Melotticad648c2011-05-19 21:25:10 +0300460 @requires_zlib
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200461 def test_obsoletes(self):
462 # Test looking for distributions based on what they obsolete
463 checkLists = lambda x, y: self.assertEqual(sorted(x), sorted(y))
464
465 l = [dist.name for dist in obsoletes_distribution('truffles', '1.0')]
466 checkLists(l, [])
467
468 l = [dist.name for dist in obsoletes_distribution('truffles', '1.0',
469 use_egg_info=True)]
470 checkLists(l, ['cheese', 'bacon'])
471
472 l = [dist.name for dist in obsoletes_distribution('truffles', '0.8')]
473 checkLists(l, ['choxie'])
474
475 l = [dist.name for dist in obsoletes_distribution('truffles', '0.8',
476 use_egg_info=True)]
477 checkLists(l, ['choxie', 'cheese'])
478
479 l = [dist.name for dist in obsoletes_distribution('truffles', '0.9.6')]
480 checkLists(l, ['choxie', 'towel-stuff'])
481
482 l = [dist.name for dist in obsoletes_distribution('truffles',
483 '0.5.2.3')]
484 checkLists(l, ['choxie', 'towel-stuff'])
485
486 l = [dist.name for dist in obsoletes_distribution('truffles', '0.2')]
487 checkLists(l, ['towel-stuff'])
488
Ezio Melotticad648c2011-05-19 21:25:10 +0300489 @requires_zlib
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200490 def test_yield_distribution(self):
491 # tests the internal function _yield_distributions
492 checkLists = lambda x, y: self.assertEqual(sorted(x), sorted(y))
493
494 eggs = [('bacon', '0.1'), ('banana', '0.4'), ('strawberry', '0.6'),
495 ('truffles', '5.0'), ('cheese', '2.0.2'),
496 ('coconuts-aster', '10.3'), ('nut', 'funkyversion')]
497 dists = [('choxie', '2.0.0.9'), ('grammar', '1.0a4'),
498 ('towel-stuff', '0.1'), ('babar', '0.1')]
499
Éric Araujo6f677652011-06-16 23:43:15 +0200500 checkLists([], _yield_distributions(False, False, sys.path))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200501
Éric Araujobab50cb2011-07-29 02:37:21 +0200502 found = [(dist.name, dist.version)
Éric Araujo6f677652011-06-16 23:43:15 +0200503 for dist in _yield_distributions(False, True, sys.path)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200504 if dist.path.startswith(self.fake_dists_path)]
505 checkLists(eggs, found)
506
Éric Araujobab50cb2011-07-29 02:37:21 +0200507 found = [(dist.name, dist.version)
Éric Araujo6f677652011-06-16 23:43:15 +0200508 for dist in _yield_distributions(True, False, sys.path)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200509 if dist.path.startswith(self.fake_dists_path)]
510 checkLists(dists, found)
511
Éric Araujobab50cb2011-07-29 02:37:21 +0200512 found = [(dist.name, dist.version)
Éric Araujo6f677652011-06-16 23:43:15 +0200513 for dist in _yield_distributions(True, True, sys.path)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200514 if dist.path.startswith(self.fake_dists_path)]
515 checkLists(dists + eggs, found)
516
517
Tarek Ziadea17d8882011-05-30 10:57:44 +0200518class DataFilesTestCase(GlobTestCaseBase):
519
520 def assertRulesMatch(self, rules, spec):
521 tempdir = self.build_files_tree(spec)
522 expected = self.clean_tree(spec)
523 result = get_resources_dests(tempdir, rules)
524 self.assertEqual(expected, result)
525
526 def clean_tree(self, spec):
527 files = {}
528 for path, value in spec.items():
529 if value is not None:
530 files[path] = value
531 return files
532
533 def test_simple_glob(self):
534 rules = [('', '*.tpl', '{data}')]
535 spec = {'coucou.tpl': '{data}/coucou.tpl',
536 'Donotwant': None}
537 self.assertRulesMatch(rules, spec)
538
539 def test_multiple_match(self):
540 rules = [('scripts', '*.bin', '{appdata}'),
541 ('scripts', '*', '{appscript}')]
542 spec = {'scripts/script.bin': '{appscript}/script.bin',
543 'Babarlikestrawberry': None}
544 self.assertRulesMatch(rules, spec)
545
546 def test_set_match(self):
547 rules = [('scripts', '*.{bin,sh}', '{appscript}')]
548 spec = {'scripts/script.bin': '{appscript}/script.bin',
549 'scripts/babar.sh': '{appscript}/babar.sh',
550 'Babarlikestrawberry': None}
551 self.assertRulesMatch(rules, spec)
552
553 def test_set_match_multiple(self):
554 rules = [('scripts', 'script{s,}.{bin,sh}', '{appscript}')]
555 spec = {'scripts/scripts.bin': '{appscript}/scripts.bin',
556 'scripts/script.sh': '{appscript}/script.sh',
557 'Babarlikestrawberry': None}
558 self.assertRulesMatch(rules, spec)
559
560 def test_set_match_exclude(self):
561 rules = [('scripts', '*', '{appscript}'),
562 ('', os.path.join('**', '*.sh'), None)]
563 spec = {'scripts/scripts.bin': '{appscript}/scripts.bin',
564 'scripts/script.sh': None,
565 'Babarlikestrawberry': None}
566 self.assertRulesMatch(rules, spec)
567
568 def test_glob_in_base(self):
569 rules = [('scrip*', '*.bin', '{appscript}')]
570 spec = {'scripts/scripts.bin': '{appscript}/scripts.bin',
571 'scripouille/babar.bin': '{appscript}/babar.bin',
572 'scriptortu/lotus.bin': '{appscript}/lotus.bin',
573 'Babarlikestrawberry': None}
574 self.assertRulesMatch(rules, spec)
575
576 def test_recursive_glob(self):
577 rules = [('', os.path.join('**', '*.bin'), '{binary}')]
578 spec = {'binary0.bin': '{binary}/binary0.bin',
579 'scripts/binary1.bin': '{binary}/scripts/binary1.bin',
580 'scripts/bin/binary2.bin': '{binary}/scripts/bin/binary2.bin',
581 'you/kill/pandabear.guy': None}
582 self.assertRulesMatch(rules, spec)
583
584 def test_final_exemple_glob(self):
585 rules = [
586 ('mailman/database/schemas/', '*', '{appdata}/schemas'),
587 ('', os.path.join('**', '*.tpl'), '{appdata}/templates'),
588 ('', os.path.join('developer-docs', '**', '*.txt'), '{doc}'),
589 ('', 'README', '{doc}'),
590 ('mailman/etc/', '*', '{config}'),
Tarek Ziade43f289a2011-05-30 11:07:54 +0200591 ('mailman/foo/', os.path.join('**', 'bar', '*.cfg'),
592 '{config}/baz'),
Tarek Ziadea17d8882011-05-30 10:57:44 +0200593 ('mailman/foo/', os.path.join('**', '*.cfg'), '{config}/hmm'),
594 ('', 'some-new-semantic.sns', '{funky-crazy-category}'),
595 ]
596 spec = {
597 'README': '{doc}/README',
598 'some.tpl': '{appdata}/templates/some.tpl',
599 'some-new-semantic.sns':
600 '{funky-crazy-category}/some-new-semantic.sns',
601 'mailman/database/mailman.db': None,
602 'mailman/database/schemas/blah.schema':
603 '{appdata}/schemas/blah.schema',
604 'mailman/etc/my.cnf': '{config}/my.cnf',
605 'mailman/foo/some/path/bar/my.cfg':
606 '{config}/hmm/some/path/bar/my.cfg',
607 'mailman/foo/some/path/other.cfg':
608 '{config}/hmm/some/path/other.cfg',
609 'developer-docs/index.txt': '{doc}/developer-docs/index.txt',
610 'developer-docs/api/toc.txt': '{doc}/developer-docs/api/toc.txt',
611 }
612 self.maxDiff = None
613 self.assertRulesMatch(rules, spec)
614
615 def test_get_file(self):
616 # Create a fake dist
617 temp_site_packages = tempfile.mkdtemp()
618 self.addCleanup(shutil.rmtree, temp_site_packages)
619
620 dist_name = 'test'
621 dist_info = os.path.join(temp_site_packages, 'test-0.1.dist-info')
622 os.mkdir(dist_info)
623
624 metadata_path = os.path.join(dist_info, 'METADATA')
625 resources_path = os.path.join(dist_info, 'RESOURCES')
626
627 with open(metadata_path, 'w') as fp:
628 fp.write(dedent("""\
629 Metadata-Version: 1.2
630 Name: test
631 Version: 0.1
632 Summary: test
633 Author: me
634 """))
635
636 test_path = 'test.cfg'
637
638 fd, test_resource_path = tempfile.mkstemp()
639 os.close(fd)
640 self.addCleanup(os.remove, test_resource_path)
641
642 with open(test_resource_path, 'w') as fp:
643 fp.write('Config')
644
645 with open(resources_path, 'w') as fp:
646 fp.write('%s,%s' % (test_path, test_resource_path))
647
648 # Add fake site-packages to sys.path to retrieve fake dist
649 self.addCleanup(sys.path.remove, temp_site_packages)
650 sys.path.insert(0, temp_site_packages)
651
652 # Force packaging.database to rescan the sys.path
653 self.addCleanup(enable_cache)
654 disable_cache()
655
656 # Try to retrieve resources paths and files
657 self.assertEqual(get_file_path(dist_name, test_path),
658 test_resource_path)
659 self.assertRaises(KeyError, get_file_path, dist_name, 'i-dont-exist')
660
661 with get_file(dist_name, test_path) as fp:
662 self.assertEqual(fp.read(), 'Config')
663 self.assertRaises(KeyError, get_file, dist_name, 'i-dont-exist')
664
665
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200666def test_suite():
667 suite = unittest.TestSuite()
668 load = unittest.defaultTestLoader.loadTestsFromTestCase
669 suite.addTest(load(TestDistribution))
670 suite.addTest(load(TestEggInfoDistribution))
671 suite.addTest(load(TestDatabase))
Tarek Ziadea17d8882011-05-30 10:57:44 +0200672 suite.addTest(load(DataFilesTestCase))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200673 return suite
674
675
676if __name__ == "__main__":
677 unittest.main(defaultTest='test_suite')