ยปCore Development>Code coverage>Lib/packaging/tests/test_util.py

Python code coverage for Lib/packaging/tests/test_util.py

#countcontent
1n/a"""Tests for packaging.util."""
2n/aimport os
3n/aimport sys
4n/aimport time
5n/aimport logging
6n/aimport tempfile
7n/aimport textwrap
8n/aimport warnings
9n/aimport subprocess
10n/afrom io import StringIO
11n/a
12n/afrom packaging.errors import (
13n/a PackagingPlatformError, PackagingFileError,
14n/a PackagingExecError, InstallationException)
15n/afrom packaging import util
16n/afrom packaging.dist import Distribution
17n/afrom packaging.util import (
18n/a convert_path, change_root, split_quoted, strtobool, run_2to3,
19n/a get_compiler_versions, _MAC_OS_X_LD_VERSION, byte_compile, find_packages,
20n/a spawn, get_pypirc_path, generate_pypirc, read_pypirc, resolve_name, iglob,
21n/a RICH_GLOB, egginfo_to_distinfo, is_setuptools, is_distutils, is_packaging,
22n/a get_install_method, cfg_to_args, generate_setup_py, encode_multipart)
23n/a
24n/afrom packaging.tests import support, unittest
25n/afrom packaging.tests.test_config import SETUP_CFG
26n/afrom test.script_helper import assert_python_ok, assert_python_failure
27n/a
28n/a
29n/aPYPIRC = """\
30n/a[distutils]
31n/aindex-servers =
32n/a pypi
33n/a server1
34n/a
35n/a[pypi]
36n/ausername:me
37n/apassword:xxxx
38n/a
39n/a[server1]
40n/arepository:http://example.com
41n/ausername:tarek
42n/apassword:secret
43n/a"""
44n/a
45n/aPYPIRC_OLD = """\
46n/a[server-login]
47n/ausername:tarek
48n/apassword:secret
49n/a"""
50n/a
51n/aWANTED = """\
52n/a[distutils]
53n/aindex-servers =
54n/a pypi
55n/a
56n/a[pypi]
57n/ausername:tarek
58n/apassword:xxx
59n/a"""
60n/a
61n/aEXPECTED_MULTIPART_OUTPUT = [
62n/a b'---x',
63n/a b'Content-Disposition: form-data; name="username"',
64n/a b'',
65n/a b'wok',
66n/a b'---x',
67n/a b'Content-Disposition: form-data; name="password"',
68n/a b'',
69n/a b'secret',
70n/a b'---x',
71n/a b'Content-Disposition: form-data; name="picture"; filename="wok.png"',
72n/a b'',
73n/a b'PNG89',
74n/a b'---x--',
75n/a b'',
76n/a]
77n/a
78n/a
79n/aclass FakePopen:
80n/a test_class = None
81n/a
82n/a def __init__(self, args, bufsize=0, executable=None,
83n/a stdin=None, stdout=None, stderr=None,
84n/a preexec_fn=None, close_fds=False,
85n/a shell=False, cwd=None, env=None, universal_newlines=False,
86n/a startupinfo=None, creationflags=0,
87n/a restore_signals=True, start_new_session=False,
88n/a pass_fds=()):
89n/a if isinstance(args, str):
90n/a args = args.split()
91n/a self.cmd = args[0]
92n/a exes = self.test_class._exes
93n/a if self.cmd not in exes:
94n/a # we don't want to call the system, returning an empty
95n/a # output so it doesn't match
96n/a self.stdout = StringIO()
97n/a self.stderr = StringIO()
98n/a else:
99n/a self.stdout = StringIO(exes[self.cmd])
100n/a self.stderr = StringIO()
101n/a
102n/a def communicate(self, input=None, timeout=None):
103n/a return self.stdout.read(), self.stderr.read()
104n/a
105n/a def wait(self, timeout=None):
106n/a return 0
107n/a
108n/a
109n/aclass UtilTestCase(support.EnvironRestorer,
110n/a support.TempdirManager,
111n/a support.LoggingCatcher,
112n/a unittest.TestCase):
113n/a
114n/a restore_environ = ['HOME', 'PLAT']
115n/a
116n/a def setUp(self):
117n/a super(UtilTestCase, self).setUp()
118n/a self.addCleanup(os.chdir, os.getcwd())
119n/a tempdir = self.mkdtemp()
120n/a self.rc = os.path.join(tempdir, '.pypirc')
121n/a os.environ['HOME'] = tempdir
122n/a os.chdir(tempdir)
123n/a # saving the environment
124n/a self.name = os.name
125n/a self.platform = sys.platform
126n/a self.version = sys.version
127n/a self.sep = os.sep
128n/a self.join = os.path.join
129n/a self.isabs = os.path.isabs
130n/a self.splitdrive = os.path.splitdrive
131n/a
132n/a # patching os.uname
133n/a if hasattr(os, 'uname'):
134n/a self.uname = os.uname
135n/a self._uname = os.uname()
136n/a else:
137n/a self.uname = None
138n/a self._uname = None
139n/a os.uname = self._get_uname
140n/a
141n/a def _get_uname(self):
142n/a return self._uname
143n/a
144n/a def tearDown(self):
145n/a # getting back the environment
146n/a os.name = self.name
147n/a sys.platform = self.platform
148n/a sys.version = self.version
149n/a os.sep = self.sep
150n/a os.path.join = self.join
151n/a os.path.isabs = self.isabs
152n/a os.path.splitdrive = self.splitdrive
153n/a if self.uname is not None:
154n/a os.uname = self.uname
155n/a else:
156n/a del os.uname
157n/a super(UtilTestCase, self).tearDown()
158n/a
159n/a def mock_popen(self):
160n/a self.old_find_executable = util.find_executable
161n/a util.find_executable = self._find_executable
162n/a self._exes = {}
163n/a self.old_popen = subprocess.Popen
164n/a self.old_stdout = sys.stdout
165n/a self.old_stderr = sys.stderr
166n/a FakePopen.test_class = self
167n/a subprocess.Popen = FakePopen
168n/a self.addCleanup(self.unmock_popen)
169n/a
170n/a def unmock_popen(self):
171n/a util.find_executable = self.old_find_executable
172n/a subprocess.Popen = self.old_popen
173n/a sys.stdout = self.old_stdout
174n/a sys.stderr = self.old_stderr
175n/a
176n/a def test_set_platform(self):
177n/a self.addCleanup(util.set_platform, util.get_platform())
178n/a util.set_platform("fake")
179n/a self.assertEqual("fake", util.get_platform())
180n/a
181n/a def test_convert_path(self):
182n/a # linux/mac
183n/a os.sep = '/'
184n/a
185n/a def _join(path):
186n/a return '/'.join(path)
187n/a os.path.join = _join
188n/a
189n/a self.assertEqual(convert_path('/home/to/my/stuff'),
190n/a '/home/to/my/stuff')
191n/a
192n/a # win
193n/a os.sep = '\\'
194n/a
195n/a def _join(*path):
196n/a return '\\'.join(path)
197n/a os.path.join = _join
198n/a
199n/a self.assertRaises(ValueError, convert_path, '/home/to/my/stuff')
200n/a self.assertRaises(ValueError, convert_path, 'home/to/my/stuff/')
201n/a
202n/a self.assertEqual(convert_path('home/to/my/stuff'),
203n/a 'home\\to\\my\\stuff')
204n/a self.assertEqual(convert_path('.'),
205n/a os.curdir)
206n/a
207n/a def test_change_root(self):
208n/a # linux/mac
209n/a os.name = 'posix'
210n/a
211n/a def _isabs(path):
212n/a return path[0] == '/'
213n/a os.path.isabs = _isabs
214n/a
215n/a def _join(*path):
216n/a return '/'.join(path)
217n/a os.path.join = _join
218n/a
219n/a self.assertEqual(change_root('/root', '/old/its/here'),
220n/a '/root/old/its/here')
221n/a self.assertEqual(change_root('/root', 'its/here'),
222n/a '/root/its/here')
223n/a
224n/a # windows
225n/a os.name = 'nt'
226n/a
227n/a def _isabs(path):
228n/a return path.startswith('c:\\')
229n/a os.path.isabs = _isabs
230n/a
231n/a def _splitdrive(path):
232n/a if path.startswith('c:'):
233n/a return '', path.replace('c:', '')
234n/a return '', path
235n/a os.path.splitdrive = _splitdrive
236n/a
237n/a def _join(*path):
238n/a return '\\'.join(path)
239n/a os.path.join = _join
240n/a
241n/a self.assertEqual(change_root('c:\\root', 'c:\\old\\its\\here'),
242n/a 'c:\\root\\old\\its\\here')
243n/a self.assertEqual(change_root('c:\\root', 'its\\here'),
244n/a 'c:\\root\\its\\here')
245n/a
246n/a # BugsBunny os (it's a great os)
247n/a os.name = 'BugsBunny'
248n/a self.assertRaises(PackagingPlatformError,
249n/a change_root, 'c:\\root', 'its\\here')
250n/a
251n/a # XXX platforms to be covered: os2, mac
252n/a
253n/a def test_split_quoted(self):
254n/a self.assertEqual(split_quoted('""one"" "two" \'three\' \\four'),
255n/a ['one', 'two', 'three', 'four'])
256n/a
257n/a def test_strtobool(self):
258n/a yes = ('y', 'Y', 'yes', 'True', 't', 'true', 'True', 'On', 'on', '1')
259n/a no = ('n', 'no', 'f', 'false', 'off', '0', 'Off', 'No', 'N')
260n/a
261n/a for y in yes:
262n/a self.assertTrue(strtobool(y))
263n/a
264n/a for n in no:
265n/a self.assertFalse(strtobool(n))
266n/a
267n/a def test_find_exe_version(self):
268n/a # the ld version scheme under MAC OS is:
269n/a # ^@(#)PROGRAM:ld PROJECT:ld64-VERSION
270n/a #
271n/a # where VERSION is a 2-digit number for major
272n/a # revisions. For instance under Leopard, it's
273n/a # currently 77
274n/a #
275n/a # Dots are used when branching is done.
276n/a #
277n/a # The SnowLeopard ld64 is currently 95.2.12
278n/a
279n/a for output, version in (('@(#)PROGRAM:ld PROJECT:ld64-77', '77'),
280n/a ('@(#)PROGRAM:ld PROJECT:ld64-95.2.12',
281n/a '95.2.12')):
282n/a result = _MAC_OS_X_LD_VERSION.search(output)
283n/a self.assertEqual(result.group(1), version)
284n/a
285n/a def _find_executable(self, name):
286n/a if name in self._exes:
287n/a return name
288n/a return None
289n/a
290n/a def test_get_compiler_versions(self):
291n/a self.mock_popen()
292n/a # get_versions calls distutils.spawn.find_executable on
293n/a # 'gcc', 'ld' and 'dllwrap'
294n/a self.assertEqual(get_compiler_versions(), (None, None, None))
295n/a
296n/a # Let's fake we have 'gcc' and it returns '3.4.5'
297n/a self._exes['gcc'] = 'gcc (GCC) 3.4.5 (mingw special)\nFSF'
298n/a res = get_compiler_versions()
299n/a self.assertEqual(str(res[0]), '3.4.5')
300n/a
301n/a # and let's see what happens when the version
302n/a # doesn't match the regular expression
303n/a # (\d+\.\d+(\.\d+)*)
304n/a self._exes['gcc'] = 'very strange output'
305n/a res = get_compiler_versions()
306n/a self.assertEqual(res[0], None)
307n/a
308n/a # same thing for ld
309n/a if sys.platform != 'darwin':
310n/a self._exes['ld'] = 'GNU ld version 2.17.50 20060824'
311n/a res = get_compiler_versions()
312n/a self.assertEqual(str(res[1]), '2.17.50')
313n/a self._exes['ld'] = '@(#)PROGRAM:ld PROJECT:ld64-77'
314n/a res = get_compiler_versions()
315n/a self.assertEqual(res[1], None)
316n/a else:
317n/a self._exes['ld'] = 'GNU ld version 2.17.50 20060824'
318n/a res = get_compiler_versions()
319n/a self.assertEqual(res[1], None)
320n/a self._exes['ld'] = '@(#)PROGRAM:ld PROJECT:ld64-77'
321n/a res = get_compiler_versions()
322n/a self.assertEqual(str(res[1]), '77')
323n/a
324n/a # and dllwrap
325n/a self._exes['dllwrap'] = 'GNU dllwrap 2.17.50 20060824\nFSF'
326n/a res = get_compiler_versions()
327n/a self.assertEqual(str(res[2]), '2.17.50')
328n/a self._exes['dllwrap'] = 'Cheese Wrap'
329n/a res = get_compiler_versions()
330n/a self.assertEqual(res[2], None)
331n/a
332n/a def test_byte_compile_under_B(self):
333n/a # make sure byte compilation works under -B (dont_write_bytecode)
334n/a self.addCleanup(setattr, sys, 'dont_write_bytecode',
335n/a sys.dont_write_bytecode)
336n/a sys.dont_write_bytecode = True
337n/a byte_compile([])
338n/a
339n/a def test_newer(self):
340n/a self.assertRaises(PackagingFileError, util.newer, 'xxx', 'xxx')
341n/a self.newer_f1 = self.mktempfile()
342n/a time.sleep(1)
343n/a self.newer_f2 = self.mktempfile()
344n/a self.assertTrue(util.newer(self.newer_f2.name, self.newer_f1.name))
345n/a
346n/a def test_find_packages(self):
347n/a # let's create a structure we want to scan:
348n/a #
349n/a # pkg1
350n/a # __init__
351n/a # pkg2
352n/a # __init__
353n/a # pkg3
354n/a # __init__
355n/a # pkg6
356n/a # __init__
357n/a # pkg4 <--- not a pkg
358n/a # pkg8
359n/a # __init__
360n/a # pkg5
361n/a # __init__
362n/a #
363n/a root = self.mkdtemp()
364n/a pkg1 = os.path.join(root, 'pkg1')
365n/a os.makedirs(os.path.join(pkg1, 'pkg2'))
366n/a os.makedirs(os.path.join(pkg1, 'pkg3', 'pkg6'))
367n/a os.makedirs(os.path.join(pkg1, 'pkg4', 'pkg8'))
368n/a os.makedirs(os.path.join(root, 'pkg5'))
369n/a self.write_file((pkg1, '__init__.py'))
370n/a self.write_file((pkg1, 'pkg2', '__init__.py'))
371n/a self.write_file((pkg1, 'pkg3', '__init__.py'))
372n/a self.write_file((pkg1, 'pkg3', 'pkg6', '__init__.py'))
373n/a self.write_file((pkg1, 'pkg4', 'pkg8', '__init__.py'))
374n/a self.write_file((root, 'pkg5', '__init__.py'))
375n/a
376n/a res = find_packages([root], ['pkg1.pkg2'])
377n/a self.assertEqual(sorted(res),
378n/a ['pkg1', 'pkg1.pkg3', 'pkg1.pkg3.pkg6', 'pkg5'])
379n/a
380n/a def test_resolve_name(self):
381n/a # test raw module name
382n/a tmpdir = self.mkdtemp()
383n/a sys.path.append(tmpdir)
384n/a self.addCleanup(sys.path.remove, tmpdir)
385n/a self.write_file((tmpdir, 'hello.py'), '')
386n/a
387n/a os.makedirs(os.path.join(tmpdir, 'a', 'b'))
388n/a self.write_file((tmpdir, 'a', '__init__.py'), '')
389n/a self.write_file((tmpdir, 'a', 'b', '__init__.py'), '')
390n/a self.write_file((tmpdir, 'a', 'b', 'c.py'), 'class Foo: pass')
391n/a self.write_file((tmpdir, 'a', 'b', 'd.py'), textwrap.dedent("""\
392n/a class FooBar:
393n/a class Bar:
394n/a def baz(self):
395n/a pass
396n/a """))
397n/a
398n/a # check Python, C and built-in module
399n/a self.assertEqual(resolve_name('hello').__name__, 'hello')
400n/a self.assertEqual(resolve_name('_csv').__name__, '_csv')
401n/a self.assertEqual(resolve_name('sys').__name__, 'sys')
402n/a
403n/a # test module.attr
404n/a self.assertIs(resolve_name('builtins.str'), str)
405n/a self.assertIsNone(resolve_name('hello.__doc__'))
406n/a self.assertEqual(resolve_name('a.b.c.Foo').__name__, 'Foo')
407n/a self.assertEqual(resolve_name('a.b.d.FooBar.Bar.baz').__name__, 'baz')
408n/a
409n/a # error if module not found
410n/a self.assertRaises(ImportError, resolve_name, 'nonexistent')
411n/a self.assertRaises(ImportError, resolve_name, 'non.existent')
412n/a self.assertRaises(ImportError, resolve_name, 'a.no')
413n/a self.assertRaises(ImportError, resolve_name, 'a.b.no')
414n/a self.assertRaises(ImportError, resolve_name, 'a.b.no.no')
415n/a self.assertRaises(ImportError, resolve_name, 'inva-lid')
416n/a
417n/a # looking up built-in names is not supported
418n/a self.assertRaises(ImportError, resolve_name, 'str')
419n/a
420n/a # error if module found but not attr
421n/a self.assertRaises(ImportError, resolve_name, 'a.b.Spam')
422n/a self.assertRaises(ImportError, resolve_name, 'a.b.c.Spam')
423n/a
424n/a @support.skip_2to3_optimize
425n/a def test_run_2to3_on_code(self):
426n/a content = "print 'test'"
427n/a converted_content = "print('test')"
428n/a file_handle = self.mktempfile()
429n/a file_name = file_handle.name
430n/a file_handle.write(content)
431n/a file_handle.flush()
432n/a file_handle.seek(0)
433n/a run_2to3([file_name])
434n/a new_content = "".join(file_handle.read())
435n/a file_handle.close()
436n/a self.assertEqual(new_content, converted_content)
437n/a
438n/a @support.skip_2to3_optimize
439n/a def test_run_2to3_on_doctests(self):
440n/a # to check if text files containing doctests only get converted.
441n/a content = ">>> print 'test'\ntest\n"
442n/a converted_content = ">>> print('test')\ntest\n\n"
443n/a file_handle = self.mktempfile()
444n/a file_name = file_handle.name
445n/a file_handle.write(content)
446n/a file_handle.flush()
447n/a file_handle.seek(0)
448n/a run_2to3([file_name], doctests_only=True)
449n/a new_content = "".join(file_handle.readlines())
450n/a file_handle.close()
451n/a self.assertEqual(new_content, converted_content)
452n/a
453n/a @unittest.skipUnless(os.name in ('nt', 'posix'),
454n/a 'runs only under posix or nt')
455n/a def test_spawn(self):
456n/a tmpdir = self.mkdtemp()
457n/a
458n/a # creating something executable
459n/a # through the shell that returns 1
460n/a if os.name == 'posix':
461n/a exe = os.path.join(tmpdir, 'foo.sh')
462n/a self.write_file(exe, '#!/bin/sh\nexit 1')
463n/a os.chmod(exe, 0o777)
464n/a else:
465n/a exe = os.path.join(tmpdir, 'foo.bat')
466n/a self.write_file(exe, 'exit 1')
467n/a
468n/a os.chmod(exe, 0o777)
469n/a self.assertRaises(PackagingExecError, spawn, [exe])
470n/a
471n/a # now something that works
472n/a if os.name == 'posix':
473n/a exe = os.path.join(tmpdir, 'foo.sh')
474n/a self.write_file(exe, '#!/bin/sh\nexit 0')
475n/a os.chmod(exe, 0o777)
476n/a else:
477n/a exe = os.path.join(tmpdir, 'foo.bat')
478n/a self.write_file(exe, 'exit 0')
479n/a
480n/a os.chmod(exe, 0o777)
481n/a spawn([exe]) # should work without any error
482n/a
483n/a def test_server_registration(self):
484n/a # This test makes sure we know how to:
485n/a # 1. handle several sections in .pypirc
486n/a # 2. handle the old format
487n/a
488n/a # new format
489n/a self.write_file(self.rc, PYPIRC)
490n/a config = read_pypirc()
491n/a
492n/a config = sorted(config.items())
493n/a expected = [('password', 'xxxx'), ('realm', 'pypi'),
494n/a ('repository', 'http://pypi.python.org/pypi'),
495n/a ('server', 'pypi'), ('username', 'me')]
496n/a self.assertEqual(config, expected)
497n/a
498n/a # old format
499n/a self.write_file(self.rc, PYPIRC_OLD)
500n/a config = read_pypirc()
501n/a config = sorted(config.items())
502n/a expected = [('password', 'secret'), ('realm', 'pypi'),
503n/a ('repository', 'http://pypi.python.org/pypi'),
504n/a ('server', 'server-login'), ('username', 'tarek')]
505n/a self.assertEqual(config, expected)
506n/a
507n/a def test_server_empty_registration(self):
508n/a rc = get_pypirc_path()
509n/a self.assertFalse(os.path.exists(rc))
510n/a generate_pypirc('tarek', 'xxx')
511n/a self.assertTrue(os.path.exists(rc))
512n/a with open(rc) as f:
513n/a content = f.read()
514n/a self.assertEqual(content, WANTED)
515n/a
516n/a def test_cfg_to_args(self):
517n/a opts = {'description-file': 'README', 'extra-files': '',
518n/a 'setup-hooks': 'packaging.tests.test_config.version_hook'}
519n/a self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8')
520n/a self.write_file('README', 'loooong description')
521n/a
522n/a with warnings.catch_warnings():
523n/a warnings.simplefilter('ignore', DeprecationWarning)
524n/a args = cfg_to_args()
525n/a # use Distribution to get the contents of the setup.cfg file
526n/a dist = Distribution()
527n/a dist.parse_config_files()
528n/a metadata = dist.metadata
529n/a
530n/a self.assertEqual(args['name'], metadata['Name'])
531n/a # + .dev1 because the test SETUP_CFG also tests a hook function in
532n/a # test_config.py for appending to the version string
533n/a self.assertEqual(args['version'] + '.dev1', metadata['Version'])
534n/a self.assertEqual(args['author'], metadata['Author'])
535n/a self.assertEqual(args['author_email'], metadata['Author-Email'])
536n/a self.assertEqual(args['maintainer'], metadata['Maintainer'])
537n/a self.assertEqual(args['maintainer_email'],
538n/a metadata['Maintainer-Email'])
539n/a self.assertEqual(args['description'], metadata['Summary'])
540n/a self.assertEqual(args['long_description'], metadata['Description'])
541n/a self.assertEqual(args['classifiers'], metadata['Classifier'])
542n/a self.assertEqual(args['requires'], metadata['Requires-Dist'])
543n/a self.assertEqual(args['provides'], metadata['Provides-Dist'])
544n/a
545n/a self.assertEqual(args['package_dir'].get(''), dist.package_dir)
546n/a self.assertEqual(args['packages'], dist.packages)
547n/a self.assertEqual(args['scripts'], dist.scripts)
548n/a self.assertEqual(args['py_modules'], dist.py_modules)
549n/a
550n/a def test_generate_setup_py(self):
551n/a os.chdir(self.mkdtemp())
552n/a self.write_file('setup.cfg', textwrap.dedent("""\
553n/a [metadata]
554n/a name = SPAM
555n/a classifier = Programming Language :: Python
556n/a """))
557n/a generate_setup_py()
558n/a self.assertTrue(os.path.exists('setup.py'), 'setup.py not created')
559n/a rc, out, err = assert_python_ok('setup.py', '--name')
560n/a self.assertEqual(out, b'SPAM\n')
561n/a self.assertEqual(err, b'')
562n/a
563n/a # a generated setup.py should complain if no setup.cfg is present
564n/a os.unlink('setup.cfg')
565n/a rc, out, err = assert_python_failure('setup.py', '--name')
566n/a self.assertIn(b'setup.cfg', err)
567n/a
568n/a def test_encode_multipart(self):
569n/a fields = [('username', 'wok'), ('password', 'secret')]
570n/a files = [('picture', 'wok.png', b'PNG89')]
571n/a content_type, body = encode_multipart(fields, files, b'-x')
572n/a self.assertEqual(b'multipart/form-data; boundary=-x', content_type)
573n/a self.assertEqual(EXPECTED_MULTIPART_OUTPUT, body.split(b'\r\n'))
574n/a
575n/a
576n/aclass GlobTestCaseBase(support.TempdirManager,
577n/a support.LoggingCatcher,
578n/a unittest.TestCase):
579n/a
580n/a def build_files_tree(self, files):
581n/a tempdir = self.mkdtemp()
582n/a for filepath in files:
583n/a is_dir = filepath.endswith('/')
584n/a filepath = os.path.join(tempdir, *filepath.split('/'))
585n/a if is_dir:
586n/a dirname = filepath
587n/a else:
588n/a dirname = os.path.dirname(filepath)
589n/a if dirname and not os.path.exists(dirname):
590n/a os.makedirs(dirname)
591n/a if not is_dir:
592n/a self.write_file(filepath, 'babar')
593n/a return tempdir
594n/a
595n/a @staticmethod
596n/a def os_dependent_path(path):
597n/a path = path.rstrip('/').split('/')
598n/a return os.path.join(*path)
599n/a
600n/a def clean_tree(self, spec):
601n/a files = []
602n/a for path, includes in spec.items():
603n/a if includes:
604n/a files.append(self.os_dependent_path(path))
605n/a return files
606n/a
607n/a
608n/aclass GlobTestCase(GlobTestCaseBase):
609n/a
610n/a def assertGlobMatch(self, glob, spec):
611n/a tempdir = self.build_files_tree(spec)
612n/a expected = self.clean_tree(spec)
613n/a os.chdir(tempdir)
614n/a result = list(iglob(glob))
615n/a self.assertCountEqual(expected, result)
616n/a
617n/a def test_regex_rich_glob(self):
618n/a matches = RICH_GLOB.findall(
619n/a r"babar aime les {fraises} est les {huitres}")
620n/a self.assertEqual(["fraises", "huitres"], matches)
621n/a
622n/a def test_simple_glob(self):
623n/a glob = '*.tp?'
624n/a spec = {'coucou.tpl': True,
625n/a 'coucou.tpj': True,
626n/a 'Donotwant': False}
627n/a self.assertGlobMatch(glob, spec)
628n/a
629n/a def test_simple_glob_in_dir(self):
630n/a glob = os.path.join('babar', '*.tp?')
631n/a spec = {'babar/coucou.tpl': True,
632n/a 'babar/coucou.tpj': True,
633n/a 'babar/toto.bin': False,
634n/a 'Donotwant': False}
635n/a self.assertGlobMatch(glob, spec)
636n/a
637n/a def test_recursive_glob_head(self):
638n/a glob = os.path.join('**', 'tip', '*.t?l')
639n/a spec = {'babar/zaza/zuzu/tip/coucou.tpl': True,
640n/a 'babar/z/tip/coucou.tpl': True,
641n/a 'babar/tip/coucou.tpl': True,
642n/a 'babar/zeop/tip/babar/babar.tpl': False,
643n/a 'babar/z/tip/coucou.bin': False,
644n/a 'babar/toto.bin': False,
645n/a 'zozo/zuzu/tip/babar.tpl': True,
646n/a 'zozo/tip/babar.tpl': True,
647n/a 'Donotwant': False}
648n/a self.assertGlobMatch(glob, spec)
649n/a
650n/a def test_recursive_glob_tail(self):
651n/a glob = os.path.join('babar', '**')
652n/a spec = {'babar/zaza/': True,
653n/a 'babar/zaza/zuzu/': True,
654n/a 'babar/zaza/zuzu/babar.xml': True,
655n/a 'babar/zaza/zuzu/toto.xml': True,
656n/a 'babar/zaza/zuzu/toto.csv': True,
657n/a 'babar/zaza/coucou.tpl': True,
658n/a 'babar/bubu.tpl': True,
659n/a 'zozo/zuzu/tip/babar.tpl': False,
660n/a 'zozo/tip/babar.tpl': False,
661n/a 'Donotwant': False}
662n/a self.assertGlobMatch(glob, spec)
663n/a
664n/a def test_recursive_glob_middle(self):
665n/a glob = os.path.join('babar', '**', 'tip', '*.t?l')
666n/a spec = {'babar/zaza/zuzu/tip/coucou.tpl': True,
667n/a 'babar/z/tip/coucou.tpl': True,
668n/a 'babar/tip/coucou.tpl': True,
669n/a 'babar/zeop/tip/babar/babar.tpl': False,
670n/a 'babar/z/tip/coucou.bin': False,
671n/a 'babar/toto.bin': False,
672n/a 'zozo/zuzu/tip/babar.tpl': False,
673n/a 'zozo/tip/babar.tpl': False,
674n/a 'Donotwant': False}
675n/a self.assertGlobMatch(glob, spec)
676n/a
677n/a def test_glob_set_tail(self):
678n/a glob = os.path.join('bin', '*.{bin,sh,exe}')
679n/a spec = {'bin/babar.bin': True,
680n/a 'bin/zephir.sh': True,
681n/a 'bin/celestine.exe': True,
682n/a 'bin/cornelius.bat': False,
683n/a 'bin/cornelius.xml': False,
684n/a 'toto/yurg': False,
685n/a 'Donotwant': False}
686n/a self.assertGlobMatch(glob, spec)
687n/a
688n/a def test_glob_set_middle(self):
689n/a glob = os.path.join('xml', '{babar,toto}.xml')
690n/a spec = {'xml/babar.xml': True,
691n/a 'xml/toto.xml': True,
692n/a 'xml/babar.xslt': False,
693n/a 'xml/cornelius.sgml': False,
694n/a 'xml/zephir.xml': False,
695n/a 'toto/yurg.xml': False,
696n/a 'Donotwant': False}
697n/a self.assertGlobMatch(glob, spec)
698n/a
699n/a def test_glob_set_head(self):
700n/a glob = os.path.join('{xml,xslt}', 'babar.*')
701n/a spec = {'xml/babar.xml': True,
702n/a 'xml/toto.xml': False,
703n/a 'xslt/babar.xslt': True,
704n/a 'xslt/toto.xslt': False,
705n/a 'toto/yurg.xml': False,
706n/a 'Donotwant': False}
707n/a self.assertGlobMatch(glob, spec)
708n/a
709n/a def test_glob_all(self):
710n/a dirs = '{%s,%s}' % (os.path.join('xml', '*'),
711n/a os.path.join('xslt', '**'))
712n/a glob = os.path.join(dirs, 'babar.xml')
713n/a spec = {'xml/a/babar.xml': True,
714n/a 'xml/b/babar.xml': True,
715n/a 'xml/a/c/babar.xml': False,
716n/a 'xslt/a/babar.xml': True,
717n/a 'xslt/b/babar.xml': True,
718n/a 'xslt/a/c/babar.xml': True,
719n/a 'toto/yurg.xml': False,
720n/a 'Donotwant': False}
721n/a self.assertGlobMatch(glob, spec)
722n/a
723n/a def test_invalid_glob_pattern(self):
724n/a invalids = [
725n/a 'ppooa**',
726n/a 'azzaeaz4**/',
727n/a '/**ddsfs',
728n/a '**##1e"&e',
729n/a 'DSFb**c009',
730n/a '{',
731n/a '{aaQSDFa',
732n/a '}',
733n/a 'aQSDFSaa}',
734n/a '{**a,',
735n/a ',**a}',
736n/a '{a**,',
737n/a ',b**}',
738n/a '{a**a,babar}',
739n/a '{bob,b**z}',
740n/a ]
741n/a for pattern in invalids:
742n/a self.assertRaises(ValueError, iglob, pattern)
743n/a
744n/a
745n/aclass EggInfoToDistInfoTestCase(support.TempdirManager,
746n/a support.LoggingCatcher,
747n/a unittest.TestCase):
748n/a
749n/a def get_metadata_file_paths(self, distinfo_path):
750n/a req_metadata_files = ['METADATA', 'RECORD', 'INSTALLER']
751n/a metadata_file_paths = []
752n/a for metadata_file in req_metadata_files:
753n/a path = os.path.join(distinfo_path, metadata_file)
754n/a metadata_file_paths.append(path)
755n/a return metadata_file_paths
756n/a
757n/a def test_egginfo_to_distinfo_setuptools(self):
758n/a distinfo = 'hello-0.1.1-py3.3.dist-info'
759n/a egginfo = 'hello-0.1.1-py3.3.egg-info'
760n/a dirs = [egginfo]
761n/a files = ['hello.py', 'hello.pyc']
762n/a extra_metadata = ['dependency_links.txt', 'entry_points.txt',
763n/a 'not-zip-safe', 'PKG-INFO', 'top_level.txt',
764n/a 'SOURCES.txt']
765n/a for f in extra_metadata:
766n/a files.append(os.path.join(egginfo, f))
767n/a
768n/a tempdir, record_file = self.build_dist_tree(files, dirs)
769n/a distinfo_path = os.path.join(tempdir, distinfo)
770n/a egginfo_path = os.path.join(tempdir, egginfo)
771n/a metadata_file_paths = self.get_metadata_file_paths(distinfo_path)
772n/a
773n/a egginfo_to_distinfo(record_file)
774n/a # test that directories and files get created
775n/a self.assertTrue(os.path.isdir(distinfo_path))
776n/a self.assertTrue(os.path.isdir(egginfo_path))
777n/a
778n/a for mfile in metadata_file_paths:
779n/a self.assertTrue(os.path.isfile(mfile))
780n/a
781n/a def test_egginfo_to_distinfo_distutils(self):
782n/a distinfo = 'hello-0.1.1-py3.3.dist-info'
783n/a egginfo = 'hello-0.1.1-py3.3.egg-info'
784n/a # egginfo is a file in distutils which contains the metadata
785n/a files = ['hello.py', 'hello.pyc', egginfo]
786n/a
787n/a tempdir, record_file = self.build_dist_tree(files, dirs=[])
788n/a distinfo_path = os.path.join(tempdir, distinfo)
789n/a egginfo_path = os.path.join(tempdir, egginfo)
790n/a metadata_file_paths = self.get_metadata_file_paths(distinfo_path)
791n/a
792n/a egginfo_to_distinfo(record_file)
793n/a # test that directories and files get created
794n/a self.assertTrue(os.path.isdir(distinfo_path))
795n/a self.assertTrue(os.path.isfile(egginfo_path))
796n/a
797n/a for mfile in metadata_file_paths:
798n/a self.assertTrue(os.path.isfile(mfile))
799n/a
800n/a def build_dist_tree(self, files, dirs):
801n/a tempdir = self.mkdtemp()
802n/a record_file_path = os.path.join(tempdir, 'RECORD')
803n/a file_paths, dir_paths = ([], [])
804n/a for d in dirs:
805n/a path = os.path.join(tempdir, d)
806n/a os.makedirs(path)
807n/a dir_paths.append(path)
808n/a for f in files:
809n/a path = os.path.join(tempdir, f)
810n/a with open(path, 'w') as _f:
811n/a _f.write(f)
812n/a file_paths.append(path)
813n/a
814n/a with open(record_file_path, 'w') as record_file:
815n/a for fpath in file_paths:
816n/a record_file.write(fpath + '\n')
817n/a for dpath in dir_paths:
818n/a record_file.write(dpath + '\n')
819n/a
820n/a return (tempdir, record_file_path)
821n/a
822n/a
823n/aclass PackagingLibChecks(support.TempdirManager,
824n/a support.LoggingCatcher,
825n/a unittest.TestCase):
826n/a
827n/a def setUp(self):
828n/a super(PackagingLibChecks, self).setUp()
829n/a self._empty_dir = self.mkdtemp()
830n/a
831n/a def test_empty_package_is_not_based_on_anything(self):
832n/a self.assertFalse(is_setuptools(self._empty_dir))
833n/a self.assertFalse(is_distutils(self._empty_dir))
834n/a self.assertFalse(is_packaging(self._empty_dir))
835n/a
836n/a def test_setup_py_importing_setuptools_is_setuptools_based(self):
837n/a self.assertTrue(is_setuptools(self._setuptools_setup_py_pkg()))
838n/a
839n/a def test_egg_info_dir_and_setup_py_is_setuptools_based(self):
840n/a self.assertTrue(is_setuptools(self._setuptools_egg_info_pkg()))
841n/a
842n/a def test_egg_info_and_non_setuptools_setup_py_is_setuptools_based(self):
843n/a self.assertTrue(is_setuptools(self._egg_info_with_no_setuptools()))
844n/a
845n/a def test_setup_py_not_importing_setuptools_is_not_setuptools_based(self):
846n/a self.assertFalse(is_setuptools(self._random_setup_py_pkg()))
847n/a
848n/a def test_setup_py_importing_distutils_is_distutils_based(self):
849n/a self.assertTrue(is_distutils(self._distutils_setup_py_pkg()))
850n/a
851n/a def test_pkg_info_file_and_setup_py_is_distutils_based(self):
852n/a self.assertTrue(is_distutils(self._distutils_pkg_info()))
853n/a
854n/a def test_pkg_info_and_non_distutils_setup_py_is_distutils_based(self):
855n/a self.assertTrue(is_distutils(self._pkg_info_with_no_distutils()))
856n/a
857n/a def test_setup_py_not_importing_distutils_is_not_distutils_based(self):
858n/a self.assertFalse(is_distutils(self._random_setup_py_pkg()))
859n/a
860n/a def test_setup_cfg_with_no_metadata_section_is_not_packaging_based(self):
861n/a self.assertFalse(is_packaging(self._setup_cfg_with_no_metadata_pkg()))
862n/a
863n/a def test_setup_cfg_with_valid_metadata_section_is_packaging_based(self):
864n/a self.assertTrue(is_packaging(self._valid_setup_cfg_pkg()))
865n/a
866n/a def test_setup_cfg_and_invalid_setup_cfg_is_not_packaging_based(self):
867n/a self.assertFalse(is_packaging(self._invalid_setup_cfg_pkg()))
868n/a
869n/a def test_get_install_method_with_setuptools_pkg(self):
870n/a path = self._setuptools_setup_py_pkg()
871n/a self.assertEqual("setuptools", get_install_method(path))
872n/a
873n/a def test_get_install_method_with_distutils_pkg(self):
874n/a path = self._distutils_pkg_info()
875n/a self.assertEqual("distutils", get_install_method(path))
876n/a
877n/a def test_get_install_method_with_packaging_pkg(self):
878n/a path = self._valid_setup_cfg_pkg()
879n/a self.assertEqual("packaging", get_install_method(path))
880n/a
881n/a def test_get_install_method_with_unknown_pkg(self):
882n/a path = self._invalid_setup_cfg_pkg()
883n/a self.assertRaises(InstallationException, get_install_method, path)
884n/a
885n/a def test_is_setuptools_logs_setup_py_text_found(self):
886n/a is_setuptools(self._setuptools_setup_py_pkg())
887n/a expected = ['setup.py file found.',
888n/a 'No egg-info directory found.',
889n/a 'Found setuptools text in setup.py.']
890n/a self.assertEqual(expected, self.get_logs(logging.DEBUG))
891n/a
892n/a def test_is_setuptools_logs_setup_py_text_not_found(self):
893n/a directory = self._random_setup_py_pkg()
894n/a is_setuptools(directory)
895n/a expected = ['setup.py file found.', 'No egg-info directory found.',
896n/a 'No setuptools text found in setup.py.']
897n/a self.assertEqual(expected, self.get_logs(logging.DEBUG))
898n/a
899n/a def test_is_setuptools_logs_egg_info_dir_found(self):
900n/a is_setuptools(self._setuptools_egg_info_pkg())
901n/a expected = ['setup.py file found.', 'Found egg-info directory.']
902n/a self.assertEqual(expected, self.get_logs(logging.DEBUG))
903n/a
904n/a def test_is_distutils_logs_setup_py_text_found(self):
905n/a is_distutils(self._distutils_setup_py_pkg())
906n/a expected = ['setup.py file found.',
907n/a 'No PKG-INFO file found.',
908n/a 'Found distutils text in setup.py.']
909n/a self.assertEqual(expected, self.get_logs(logging.DEBUG))
910n/a
911n/a def test_is_distutils_logs_setup_py_text_not_found(self):
912n/a directory = self._random_setup_py_pkg()
913n/a is_distutils(directory)
914n/a expected = ['setup.py file found.', 'No PKG-INFO file found.',
915n/a 'No distutils text found in setup.py.']
916n/a self.assertEqual(expected, self.get_logs(logging.DEBUG))
917n/a
918n/a def test_is_distutils_logs_pkg_info_file_found(self):
919n/a is_distutils(self._distutils_pkg_info())
920n/a expected = ['setup.py file found.', 'PKG-INFO file found.']
921n/a self.assertEqual(expected, self.get_logs(logging.DEBUG))
922n/a
923n/a def test_is_packaging_logs_setup_cfg_found(self):
924n/a is_packaging(self._valid_setup_cfg_pkg())
925n/a expected = ['setup.cfg file found.']
926n/a self.assertEqual(expected, self.get_logs(logging.DEBUG))
927n/a
928n/a def test_is_packaging_logs_setup_cfg_not_found(self):
929n/a is_packaging(self._empty_dir)
930n/a expected = ['No setup.cfg file found.']
931n/a self.assertEqual(expected, self.get_logs(logging.DEBUG))
932n/a
933n/a def _write_setuptools_setup_py(self, directory):
934n/a self.write_file((directory, 'setup.py'),
935n/a "from setuptools import setup")
936n/a
937n/a def _write_distutils_setup_py(self, directory):
938n/a self.write_file([directory, 'setup.py'],
939n/a "from distutils.core import setup")
940n/a
941n/a def _write_packaging_setup_cfg(self, directory):
942n/a self.write_file([directory, 'setup.cfg'],
943n/a ("[metadata]\n"
944n/a "name = mypackage\n"
945n/a "version = 0.1.0\n"))
946n/a
947n/a def _setuptools_setup_py_pkg(self):
948n/a tmp = self.mkdtemp()
949n/a self._write_setuptools_setup_py(tmp)
950n/a return tmp
951n/a
952n/a def _distutils_setup_py_pkg(self):
953n/a tmp = self.mkdtemp()
954n/a self._write_distutils_setup_py(tmp)
955n/a return tmp
956n/a
957n/a def _valid_setup_cfg_pkg(self):
958n/a tmp = self.mkdtemp()
959n/a self._write_packaging_setup_cfg(tmp)
960n/a return tmp
961n/a
962n/a def _setuptools_egg_info_pkg(self):
963n/a tmp = self.mkdtemp()
964n/a self._write_setuptools_setup_py(tmp)
965n/a tempfile.mkdtemp(suffix='.egg-info', dir=tmp)
966n/a return tmp
967n/a
968n/a def _distutils_pkg_info(self):
969n/a tmp = self._distutils_setup_py_pkg()
970n/a self.write_file([tmp, 'PKG-INFO'], '', encoding='UTF-8')
971n/a return tmp
972n/a
973n/a def _setup_cfg_with_no_metadata_pkg(self):
974n/a tmp = self.mkdtemp()
975n/a self.write_file([tmp, 'setup.cfg'],
976n/a ("[othersection]\n"
977n/a "foo = bar\n"))
978n/a return tmp
979n/a
980n/a def _invalid_setup_cfg_pkg(self):
981n/a tmp = self.mkdtemp()
982n/a self.write_file([tmp, 'setup.cfg'],
983n/a ("[metadata]\n"
984n/a "name = john\n"
985n/a "last_name = doe\n"))
986n/a return tmp
987n/a
988n/a def _egg_info_with_no_setuptools(self):
989n/a tmp = self._random_setup_py_pkg()
990n/a tempfile.mkdtemp(suffix='.egg-info', dir=tmp)
991n/a return tmp
992n/a
993n/a def _pkg_info_with_no_distutils(self):
994n/a tmp = self._random_setup_py_pkg()
995n/a self.write_file([tmp, 'PKG-INFO'], '', encoding='UTF-8')
996n/a return tmp
997n/a
998n/a def _random_setup_py_pkg(self):
999n/a tmp = self.mkdtemp()
1000n/a self.write_file((tmp, 'setup.py'), "from mypackage import setup")
1001n/a return tmp
1002n/a
1003n/a
1004n/adef test_suite():
1005n/a suite = unittest.makeSuite(UtilTestCase)
1006n/a suite.addTest(unittest.makeSuite(GlobTestCase))
1007n/a suite.addTest(unittest.makeSuite(EggInfoToDistInfoTestCase))
1008n/a suite.addTest(unittest.makeSuite(PackagingLibChecks))
1009n/a return suite
1010n/a
1011n/a
1012n/aif __name__ == "__main__":
1013n/a unittest.main(defaultTest="test_suite")