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