| """Tests for packaging.util.""" |
| import os |
| import sys |
| import time |
| import logging |
| import tempfile |
| import textwrap |
| import warnings |
| import subprocess |
| from io import StringIO |
| |
| from packaging.errors import ( |
| PackagingPlatformError, PackagingFileError, |
| PackagingExecError, InstallationException) |
| from packaging import util |
| from packaging.dist import Distribution |
| from packaging.util import ( |
| convert_path, change_root, split_quoted, strtobool, run_2to3, |
| get_compiler_versions, _MAC_OS_X_LD_VERSION, byte_compile, find_packages, |
| spawn, get_pypirc_path, generate_pypirc, read_pypirc, resolve_name, iglob, |
| RICH_GLOB, egginfo_to_distinfo, is_setuptools, is_distutils, is_packaging, |
| get_install_method, cfg_to_args, generate_setup_py, encode_multipart) |
| |
| from packaging.tests import support, unittest |
| from packaging.tests.test_config import SETUP_CFG |
| from test.script_helper import assert_python_ok, assert_python_failure |
| |
| |
| PYPIRC = """\ |
| [distutils] |
| index-servers = |
| pypi |
| server1 |
| |
| [pypi] |
| username:me |
| password:xxxx |
| |
| [server1] |
| repository:http://example.com |
| username:tarek |
| password:secret |
| """ |
| |
| PYPIRC_OLD = """\ |
| [server-login] |
| username:tarek |
| password:secret |
| """ |
| |
| WANTED = """\ |
| [distutils] |
| index-servers = |
| pypi |
| |
| [pypi] |
| username:tarek |
| password:xxx |
| """ |
| |
| EXPECTED_MULTIPART_OUTPUT = [ |
| b'---x', |
| b'Content-Disposition: form-data; name="username"', |
| b'', |
| b'wok', |
| b'---x', |
| b'Content-Disposition: form-data; name="password"', |
| b'', |
| b'secret', |
| b'---x', |
| b'Content-Disposition: form-data; name="picture"; filename="wok.png"', |
| b'', |
| b'PNG89', |
| b'---x--', |
| b'', |
| ] |
| |
| |
| class FakePopen: |
| test_class = None |
| |
| def __init__(self, args, bufsize=0, executable=None, |
| stdin=None, stdout=None, stderr=None, |
| preexec_fn=None, close_fds=False, |
| shell=False, cwd=None, env=None, universal_newlines=False, |
| startupinfo=None, creationflags=0, |
| restore_signals=True, start_new_session=False, |
| pass_fds=()): |
| if isinstance(args, str): |
| args = args.split() |
| self.cmd = args[0] |
| exes = self.test_class._exes |
| if self.cmd not in exes: |
| # we don't want to call the system, returning an empty |
| # output so it doesn't match |
| self.stdout = StringIO() |
| self.stderr = StringIO() |
| else: |
| self.stdout = StringIO(exes[self.cmd]) |
| self.stderr = StringIO() |
| |
| def communicate(self, input=None, timeout=None): |
| return self.stdout.read(), self.stderr.read() |
| |
| def wait(self, timeout=None): |
| return 0 |
| |
| |
| class UtilTestCase(support.EnvironRestorer, |
| support.TempdirManager, |
| support.LoggingCatcher, |
| unittest.TestCase): |
| |
| restore_environ = ['HOME', 'PLAT'] |
| |
| def setUp(self): |
| super(UtilTestCase, self).setUp() |
| self.addCleanup(os.chdir, os.getcwd()) |
| tempdir = self.mkdtemp() |
| self.rc = os.path.join(tempdir, '.pypirc') |
| os.environ['HOME'] = tempdir |
| os.chdir(tempdir) |
| # saving the environment |
| self.name = os.name |
| self.platform = sys.platform |
| self.version = sys.version |
| self.sep = os.sep |
| self.join = os.path.join |
| self.isabs = os.path.isabs |
| self.splitdrive = os.path.splitdrive |
| |
| # patching os.uname |
| if hasattr(os, 'uname'): |
| self.uname = os.uname |
| self._uname = os.uname() |
| else: |
| self.uname = None |
| self._uname = None |
| os.uname = self._get_uname |
| |
| def _get_uname(self): |
| return self._uname |
| |
| def tearDown(self): |
| # getting back the environment |
| os.name = self.name |
| sys.platform = self.platform |
| sys.version = self.version |
| os.sep = self.sep |
| os.path.join = self.join |
| os.path.isabs = self.isabs |
| os.path.splitdrive = self.splitdrive |
| if self.uname is not None: |
| os.uname = self.uname |
| else: |
| del os.uname |
| super(UtilTestCase, self).tearDown() |
| |
| def mock_popen(self): |
| self.old_find_executable = util.find_executable |
| util.find_executable = self._find_executable |
| self._exes = {} |
| self.old_popen = subprocess.Popen |
| self.old_stdout = sys.stdout |
| self.old_stderr = sys.stderr |
| FakePopen.test_class = self |
| subprocess.Popen = FakePopen |
| self.addCleanup(self.unmock_popen) |
| |
| def unmock_popen(self): |
| util.find_executable = self.old_find_executable |
| subprocess.Popen = self.old_popen |
| sys.stdout = self.old_stdout |
| sys.stderr = self.old_stderr |
| |
| def test_set_platform(self): |
| self.addCleanup(util.set_platform, util.get_platform()) |
| util.set_platform("fake") |
| self.assertEqual("fake", util.get_platform()) |
| |
| def test_convert_path(self): |
| # linux/mac |
| os.sep = '/' |
| |
| def _join(path): |
| return '/'.join(path) |
| os.path.join = _join |
| |
| self.assertEqual(convert_path('/home/to/my/stuff'), |
| '/home/to/my/stuff') |
| |
| # win |
| os.sep = '\\' |
| |
| def _join(*path): |
| return '\\'.join(path) |
| os.path.join = _join |
| |
| self.assertRaises(ValueError, convert_path, '/home/to/my/stuff') |
| self.assertRaises(ValueError, convert_path, 'home/to/my/stuff/') |
| |
| self.assertEqual(convert_path('home/to/my/stuff'), |
| 'home\\to\\my\\stuff') |
| self.assertEqual(convert_path('.'), |
| os.curdir) |
| |
| def test_change_root(self): |
| # linux/mac |
| os.name = 'posix' |
| |
| def _isabs(path): |
| return path[0] == '/' |
| os.path.isabs = _isabs |
| |
| def _join(*path): |
| return '/'.join(path) |
| os.path.join = _join |
| |
| self.assertEqual(change_root('/root', '/old/its/here'), |
| '/root/old/its/here') |
| self.assertEqual(change_root('/root', 'its/here'), |
| '/root/its/here') |
| |
| # windows |
| os.name = 'nt' |
| |
| def _isabs(path): |
| return path.startswith('c:\\') |
| os.path.isabs = _isabs |
| |
| def _splitdrive(path): |
| if path.startswith('c:'): |
| return '', path.replace('c:', '') |
| return '', path |
| os.path.splitdrive = _splitdrive |
| |
| def _join(*path): |
| return '\\'.join(path) |
| os.path.join = _join |
| |
| self.assertEqual(change_root('c:\\root', 'c:\\old\\its\\here'), |
| 'c:\\root\\old\\its\\here') |
| self.assertEqual(change_root('c:\\root', 'its\\here'), |
| 'c:\\root\\its\\here') |
| |
| # BugsBunny os (it's a great os) |
| os.name = 'BugsBunny' |
| self.assertRaises(PackagingPlatformError, |
| change_root, 'c:\\root', 'its\\here') |
| |
| # XXX platforms to be covered: os2, mac |
| |
| def test_split_quoted(self): |
| self.assertEqual(split_quoted('""one"" "two" \'three\' \\four'), |
| ['one', 'two', 'three', 'four']) |
| |
| def test_strtobool(self): |
| yes = ('y', 'Y', 'yes', 'True', 't', 'true', 'True', 'On', 'on', '1') |
| no = ('n', 'no', 'f', 'false', 'off', '0', 'Off', 'No', 'N') |
| |
| for y in yes: |
| self.assertTrue(strtobool(y)) |
| |
| for n in no: |
| self.assertFalse(strtobool(n)) |
| |
| def test_find_exe_version(self): |
| # the ld version scheme under MAC OS is: |
| # ^@(#)PROGRAM:ld PROJECT:ld64-VERSION |
| # |
| # where VERSION is a 2-digit number for major |
| # revisions. For instance under Leopard, it's |
| # currently 77 |
| # |
| # Dots are used when branching is done. |
| # |
| # The SnowLeopard ld64 is currently 95.2.12 |
| |
| for output, version in (('@(#)PROGRAM:ld PROJECT:ld64-77', '77'), |
| ('@(#)PROGRAM:ld PROJECT:ld64-95.2.12', |
| '95.2.12')): |
| result = _MAC_OS_X_LD_VERSION.search(output) |
| self.assertEqual(result.group(1), version) |
| |
| def _find_executable(self, name): |
| if name in self._exes: |
| return name |
| return None |
| |
| def test_get_compiler_versions(self): |
| self.mock_popen() |
| # get_versions calls distutils.spawn.find_executable on |
| # 'gcc', 'ld' and 'dllwrap' |
| self.assertEqual(get_compiler_versions(), (None, None, None)) |
| |
| # Let's fake we have 'gcc' and it returns '3.4.5' |
| self._exes['gcc'] = 'gcc (GCC) 3.4.5 (mingw special)\nFSF' |
| res = get_compiler_versions() |
| self.assertEqual(str(res[0]), '3.4.5') |
| |
| # and let's see what happens when the version |
| # doesn't match the regular expression |
| # (\d+\.\d+(\.\d+)*) |
| self._exes['gcc'] = 'very strange output' |
| res = get_compiler_versions() |
| self.assertEqual(res[0], None) |
| |
| # same thing for ld |
| if sys.platform != 'darwin': |
| self._exes['ld'] = 'GNU ld version 2.17.50 20060824' |
| res = get_compiler_versions() |
| self.assertEqual(str(res[1]), '2.17.50') |
| self._exes['ld'] = '@(#)PROGRAM:ld PROJECT:ld64-77' |
| res = get_compiler_versions() |
| self.assertEqual(res[1], None) |
| else: |
| self._exes['ld'] = 'GNU ld version 2.17.50 20060824' |
| res = get_compiler_versions() |
| self.assertEqual(res[1], None) |
| self._exes['ld'] = '@(#)PROGRAM:ld PROJECT:ld64-77' |
| res = get_compiler_versions() |
| self.assertEqual(str(res[1]), '77') |
| |
| # and dllwrap |
| self._exes['dllwrap'] = 'GNU dllwrap 2.17.50 20060824\nFSF' |
| res = get_compiler_versions() |
| self.assertEqual(str(res[2]), '2.17.50') |
| self._exes['dllwrap'] = 'Cheese Wrap' |
| res = get_compiler_versions() |
| self.assertEqual(res[2], None) |
| |
| def test_byte_compile_under_B(self): |
| # make sure byte compilation works under -B (dont_write_bytecode) |
| self.addCleanup(setattr, sys, 'dont_write_bytecode', |
| sys.dont_write_bytecode) |
| sys.dont_write_bytecode = True |
| byte_compile([]) |
| |
| def test_newer(self): |
| self.assertRaises(PackagingFileError, util.newer, 'xxx', 'xxx') |
| self.newer_f1 = self.mktempfile() |
| time.sleep(1) |
| self.newer_f2 = self.mktempfile() |
| self.assertTrue(util.newer(self.newer_f2.name, self.newer_f1.name)) |
| |
| def test_find_packages(self): |
| # let's create a structure we want to scan: |
| # |
| # pkg1 |
| # __init__ |
| # pkg2 |
| # __init__ |
| # pkg3 |
| # __init__ |
| # pkg6 |
| # __init__ |
| # pkg4 <--- not a pkg |
| # pkg8 |
| # __init__ |
| # pkg5 |
| # __init__ |
| # |
| root = self.mkdtemp() |
| pkg1 = os.path.join(root, 'pkg1') |
| os.makedirs(os.path.join(pkg1, 'pkg2')) |
| os.makedirs(os.path.join(pkg1, 'pkg3', 'pkg6')) |
| os.makedirs(os.path.join(pkg1, 'pkg4', 'pkg8')) |
| os.makedirs(os.path.join(root, 'pkg5')) |
| self.write_file((pkg1, '__init__.py')) |
| self.write_file((pkg1, 'pkg2', '__init__.py')) |
| self.write_file((pkg1, 'pkg3', '__init__.py')) |
| self.write_file((pkg1, 'pkg3', 'pkg6', '__init__.py')) |
| self.write_file((pkg1, 'pkg4', 'pkg8', '__init__.py')) |
| self.write_file((root, 'pkg5', '__init__.py')) |
| |
| res = find_packages([root], ['pkg1.pkg2']) |
| self.assertEqual(sorted(res), |
| ['pkg1', 'pkg1.pkg3', 'pkg1.pkg3.pkg6', 'pkg5']) |
| |
| def test_resolve_name(self): |
| # test raw module name |
| tmpdir = self.mkdtemp() |
| sys.path.append(tmpdir) |
| self.addCleanup(sys.path.remove, tmpdir) |
| self.write_file((tmpdir, 'hello.py'), '') |
| |
| os.makedirs(os.path.join(tmpdir, 'a', 'b')) |
| self.write_file((tmpdir, 'a', '__init__.py'), '') |
| self.write_file((tmpdir, 'a', 'b', '__init__.py'), '') |
| self.write_file((tmpdir, 'a', 'b', 'c.py'), 'class Foo: pass') |
| self.write_file((tmpdir, 'a', 'b', 'd.py'), textwrap.dedent("""\ |
| class FooBar: |
| class Bar: |
| def baz(self): |
| pass |
| """)) |
| |
| # check Python, C and built-in module |
| self.assertEqual(resolve_name('hello').__name__, 'hello') |
| self.assertEqual(resolve_name('_csv').__name__, '_csv') |
| self.assertEqual(resolve_name('sys').__name__, 'sys') |
| |
| # test module.attr |
| self.assertIs(resolve_name('builtins.str'), str) |
| self.assertIsNone(resolve_name('hello.__doc__')) |
| self.assertEqual(resolve_name('a.b.c.Foo').__name__, 'Foo') |
| self.assertEqual(resolve_name('a.b.d.FooBar.Bar.baz').__name__, 'baz') |
| |
| # error if module not found |
| self.assertRaises(ImportError, resolve_name, 'nonexistent') |
| self.assertRaises(ImportError, resolve_name, 'non.existent') |
| self.assertRaises(ImportError, resolve_name, 'a.no') |
| self.assertRaises(ImportError, resolve_name, 'a.b.no') |
| self.assertRaises(ImportError, resolve_name, 'a.b.no.no') |
| self.assertRaises(ImportError, resolve_name, 'inva-lid') |
| |
| # looking up built-in names is not supported |
| self.assertRaises(ImportError, resolve_name, 'str') |
| |
| # error if module found but not attr |
| self.assertRaises(ImportError, resolve_name, 'a.b.Spam') |
| self.assertRaises(ImportError, resolve_name, 'a.b.c.Spam') |
| |
| @support.skip_2to3_optimize |
| def test_run_2to3_on_code(self): |
| content = "print 'test'" |
| converted_content = "print('test')" |
| file_handle = self.mktempfile() |
| file_name = file_handle.name |
| file_handle.write(content) |
| file_handle.flush() |
| file_handle.seek(0) |
| run_2to3([file_name]) |
| new_content = "".join(file_handle.read()) |
| file_handle.close() |
| self.assertEqual(new_content, converted_content) |
| |
| @support.skip_2to3_optimize |
| def test_run_2to3_on_doctests(self): |
| # to check if text files containing doctests only get converted. |
| content = ">>> print 'test'\ntest\n" |
| converted_content = ">>> print('test')\ntest\n\n" |
| file_handle = self.mktempfile() |
| file_name = file_handle.name |
| file_handle.write(content) |
| file_handle.flush() |
| file_handle.seek(0) |
| run_2to3([file_name], doctests_only=True) |
| new_content = "".join(file_handle.readlines()) |
| file_handle.close() |
| self.assertEqual(new_content, converted_content) |
| |
| @unittest.skipUnless(os.name in ('nt', 'posix'), |
| 'runs only under posix or nt') |
| def test_spawn(self): |
| tmpdir = self.mkdtemp() |
| |
| # creating something executable |
| # through the shell that returns 1 |
| if os.name == 'posix': |
| exe = os.path.join(tmpdir, 'foo.sh') |
| self.write_file(exe, '#!/bin/sh\nexit 1') |
| os.chmod(exe, 0o777) |
| else: |
| exe = os.path.join(tmpdir, 'foo.bat') |
| self.write_file(exe, 'exit 1') |
| |
| os.chmod(exe, 0o777) |
| self.assertRaises(PackagingExecError, spawn, [exe]) |
| |
| # now something that works |
| if os.name == 'posix': |
| exe = os.path.join(tmpdir, 'foo.sh') |
| self.write_file(exe, '#!/bin/sh\nexit 0') |
| os.chmod(exe, 0o777) |
| else: |
| exe = os.path.join(tmpdir, 'foo.bat') |
| self.write_file(exe, 'exit 0') |
| |
| os.chmod(exe, 0o777) |
| spawn([exe]) # should work without any error |
| |
| def test_server_registration(self): |
| # This test makes sure we know how to: |
| # 1. handle several sections in .pypirc |
| # 2. handle the old format |
| |
| # new format |
| self.write_file(self.rc, PYPIRC) |
| config = read_pypirc() |
| |
| config = sorted(config.items()) |
| expected = [('password', 'xxxx'), ('realm', 'pypi'), |
| ('repository', 'http://pypi.python.org/pypi'), |
| ('server', 'pypi'), ('username', 'me')] |
| self.assertEqual(config, expected) |
| |
| # old format |
| self.write_file(self.rc, PYPIRC_OLD) |
| config = read_pypirc() |
| config = sorted(config.items()) |
| expected = [('password', 'secret'), ('realm', 'pypi'), |
| ('repository', 'http://pypi.python.org/pypi'), |
| ('server', 'server-login'), ('username', 'tarek')] |
| self.assertEqual(config, expected) |
| |
| def test_server_empty_registration(self): |
| rc = get_pypirc_path() |
| self.assertFalse(os.path.exists(rc)) |
| generate_pypirc('tarek', 'xxx') |
| self.assertTrue(os.path.exists(rc)) |
| with open(rc) as f: |
| content = f.read() |
| self.assertEqual(content, WANTED) |
| |
| def test_cfg_to_args(self): |
| opts = {'description-file': 'README', 'extra-files': '', |
| 'setup-hooks': 'packaging.tests.test_config.version_hook'} |
| self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8') |
| self.write_file('README', 'loooong description') |
| |
| with warnings.catch_warnings(): |
| warnings.simplefilter('ignore', DeprecationWarning) |
| args = cfg_to_args() |
| # use Distribution to get the contents of the setup.cfg file |
| dist = Distribution() |
| dist.parse_config_files() |
| metadata = dist.metadata |
| |
| self.assertEqual(args['name'], metadata['Name']) |
| # + .dev1 because the test SETUP_CFG also tests a hook function in |
| # test_config.py for appending to the version string |
| self.assertEqual(args['version'] + '.dev1', metadata['Version']) |
| self.assertEqual(args['author'], metadata['Author']) |
| self.assertEqual(args['author_email'], metadata['Author-Email']) |
| self.assertEqual(args['maintainer'], metadata['Maintainer']) |
| self.assertEqual(args['maintainer_email'], |
| metadata['Maintainer-Email']) |
| self.assertEqual(args['description'], metadata['Summary']) |
| self.assertEqual(args['long_description'], metadata['Description']) |
| self.assertEqual(args['classifiers'], metadata['Classifier']) |
| self.assertEqual(args['requires'], metadata['Requires-Dist']) |
| self.assertEqual(args['provides'], metadata['Provides-Dist']) |
| |
| self.assertEqual(args['package_dir'].get(''), dist.package_dir) |
| self.assertEqual(args['packages'], dist.packages) |
| self.assertEqual(args['scripts'], dist.scripts) |
| self.assertEqual(args['py_modules'], dist.py_modules) |
| |
| def test_generate_setup_py(self): |
| os.chdir(self.mkdtemp()) |
| self.write_file('setup.cfg', textwrap.dedent("""\ |
| [metadata] |
| name = SPAM |
| classifier = Programming Language :: Python |
| """)) |
| generate_setup_py() |
| self.assertTrue(os.path.exists('setup.py'), 'setup.py not created') |
| rc, out, err = assert_python_ok('setup.py', '--name') |
| self.assertEqual(out, b'SPAM\n') |
| self.assertEqual(err, b'') |
| |
| # a generated setup.py should complain if no setup.cfg is present |
| os.unlink('setup.cfg') |
| rc, out, err = assert_python_failure('setup.py', '--name') |
| self.assertIn(b'setup.cfg', err) |
| |
| def test_encode_multipart(self): |
| fields = [('username', 'wok'), ('password', 'secret')] |
| files = [('picture', 'wok.png', b'PNG89')] |
| content_type, body = encode_multipart(fields, files, b'-x') |
| self.assertEqual(b'multipart/form-data; boundary=-x', content_type) |
| self.assertEqual(EXPECTED_MULTIPART_OUTPUT, body.split(b'\r\n')) |
| |
| |
| class GlobTestCaseBase(support.TempdirManager, |
| support.LoggingCatcher, |
| unittest.TestCase): |
| |
| def build_files_tree(self, files): |
| tempdir = self.mkdtemp() |
| for filepath in files: |
| is_dir = filepath.endswith('/') |
| filepath = os.path.join(tempdir, *filepath.split('/')) |
| if is_dir: |
| dirname = filepath |
| else: |
| dirname = os.path.dirname(filepath) |
| if dirname and not os.path.exists(dirname): |
| os.makedirs(dirname) |
| if not is_dir: |
| self.write_file(filepath, 'babar') |
| return tempdir |
| |
| @staticmethod |
| def os_dependent_path(path): |
| path = path.rstrip('/').split('/') |
| return os.path.join(*path) |
| |
| def clean_tree(self, spec): |
| files = [] |
| for path, includes in spec.items(): |
| if includes: |
| files.append(self.os_dependent_path(path)) |
| return files |
| |
| |
| class GlobTestCase(GlobTestCaseBase): |
| |
| def assertGlobMatch(self, glob, spec): |
| tempdir = self.build_files_tree(spec) |
| expected = self.clean_tree(spec) |
| os.chdir(tempdir) |
| result = list(iglob(glob)) |
| self.assertCountEqual(expected, result) |
| |
| def test_regex_rich_glob(self): |
| matches = RICH_GLOB.findall( |
| r"babar aime les {fraises} est les {huitres}") |
| self.assertEqual(["fraises", "huitres"], matches) |
| |
| def test_simple_glob(self): |
| glob = '*.tp?' |
| spec = {'coucou.tpl': True, |
| 'coucou.tpj': True, |
| 'Donotwant': False} |
| self.assertGlobMatch(glob, spec) |
| |
| def test_simple_glob_in_dir(self): |
| glob = os.path.join('babar', '*.tp?') |
| spec = {'babar/coucou.tpl': True, |
| 'babar/coucou.tpj': True, |
| 'babar/toto.bin': False, |
| 'Donotwant': False} |
| self.assertGlobMatch(glob, spec) |
| |
| def test_recursive_glob_head(self): |
| glob = os.path.join('**', 'tip', '*.t?l') |
| spec = {'babar/zaza/zuzu/tip/coucou.tpl': True, |
| 'babar/z/tip/coucou.tpl': True, |
| 'babar/tip/coucou.tpl': True, |
| 'babar/zeop/tip/babar/babar.tpl': False, |
| 'babar/z/tip/coucou.bin': False, |
| 'babar/toto.bin': False, |
| 'zozo/zuzu/tip/babar.tpl': True, |
| 'zozo/tip/babar.tpl': True, |
| 'Donotwant': False} |
| self.assertGlobMatch(glob, spec) |
| |
| def test_recursive_glob_tail(self): |
| glob = os.path.join('babar', '**') |
| spec = {'babar/zaza/': True, |
| 'babar/zaza/zuzu/': True, |
| 'babar/zaza/zuzu/babar.xml': True, |
| 'babar/zaza/zuzu/toto.xml': True, |
| 'babar/zaza/zuzu/toto.csv': True, |
| 'babar/zaza/coucou.tpl': True, |
| 'babar/bubu.tpl': True, |
| 'zozo/zuzu/tip/babar.tpl': False, |
| 'zozo/tip/babar.tpl': False, |
| 'Donotwant': False} |
| self.assertGlobMatch(glob, spec) |
| |
| def test_recursive_glob_middle(self): |
| glob = os.path.join('babar', '**', 'tip', '*.t?l') |
| spec = {'babar/zaza/zuzu/tip/coucou.tpl': True, |
| 'babar/z/tip/coucou.tpl': True, |
| 'babar/tip/coucou.tpl': True, |
| 'babar/zeop/tip/babar/babar.tpl': False, |
| 'babar/z/tip/coucou.bin': False, |
| 'babar/toto.bin': False, |
| 'zozo/zuzu/tip/babar.tpl': False, |
| 'zozo/tip/babar.tpl': False, |
| 'Donotwant': False} |
| self.assertGlobMatch(glob, spec) |
| |
| def test_glob_set_tail(self): |
| glob = os.path.join('bin', '*.{bin,sh,exe}') |
| spec = {'bin/babar.bin': True, |
| 'bin/zephir.sh': True, |
| 'bin/celestine.exe': True, |
| 'bin/cornelius.bat': False, |
| 'bin/cornelius.xml': False, |
| 'toto/yurg': False, |
| 'Donotwant': False} |
| self.assertGlobMatch(glob, spec) |
| |
| def test_glob_set_middle(self): |
| glob = os.path.join('xml', '{babar,toto}.xml') |
| spec = {'xml/babar.xml': True, |
| 'xml/toto.xml': True, |
| 'xml/babar.xslt': False, |
| 'xml/cornelius.sgml': False, |
| 'xml/zephir.xml': False, |
| 'toto/yurg.xml': False, |
| 'Donotwant': False} |
| self.assertGlobMatch(glob, spec) |
| |
| def test_glob_set_head(self): |
| glob = os.path.join('{xml,xslt}', 'babar.*') |
| spec = {'xml/babar.xml': True, |
| 'xml/toto.xml': False, |
| 'xslt/babar.xslt': True, |
| 'xslt/toto.xslt': False, |
| 'toto/yurg.xml': False, |
| 'Donotwant': False} |
| self.assertGlobMatch(glob, spec) |
| |
| def test_glob_all(self): |
| dirs = '{%s,%s}' % (os.path.join('xml', '*'), |
| os.path.join('xslt', '**')) |
| glob = os.path.join(dirs, 'babar.xml') |
| spec = {'xml/a/babar.xml': True, |
| 'xml/b/babar.xml': True, |
| 'xml/a/c/babar.xml': False, |
| 'xslt/a/babar.xml': True, |
| 'xslt/b/babar.xml': True, |
| 'xslt/a/c/babar.xml': True, |
| 'toto/yurg.xml': False, |
| 'Donotwant': False} |
| self.assertGlobMatch(glob, spec) |
| |
| def test_invalid_glob_pattern(self): |
| invalids = [ |
| 'ppooa**', |
| 'azzaeaz4**/', |
| '/**ddsfs', |
| '**##1e"&e', |
| 'DSFb**c009', |
| '{', |
| '{aaQSDFa', |
| '}', |
| 'aQSDFSaa}', |
| '{**a,', |
| ',**a}', |
| '{a**,', |
| ',b**}', |
| '{a**a,babar}', |
| '{bob,b**z}', |
| ] |
| for pattern in invalids: |
| self.assertRaises(ValueError, iglob, pattern) |
| |
| |
| class EggInfoToDistInfoTestCase(support.TempdirManager, |
| support.LoggingCatcher, |
| unittest.TestCase): |
| |
| def get_metadata_file_paths(self, distinfo_path): |
| req_metadata_files = ['METADATA', 'RECORD', 'INSTALLER'] |
| metadata_file_paths = [] |
| for metadata_file in req_metadata_files: |
| path = os.path.join(distinfo_path, metadata_file) |
| metadata_file_paths.append(path) |
| return metadata_file_paths |
| |
| def test_egginfo_to_distinfo_setuptools(self): |
| distinfo = 'hello-0.1.1-py3.3.dist-info' |
| egginfo = 'hello-0.1.1-py3.3.egg-info' |
| dirs = [egginfo] |
| files = ['hello.py', 'hello.pyc'] |
| extra_metadata = ['dependency_links.txt', 'entry_points.txt', |
| 'not-zip-safe', 'PKG-INFO', 'top_level.txt', |
| 'SOURCES.txt'] |
| for f in extra_metadata: |
| files.append(os.path.join(egginfo, f)) |
| |
| tempdir, record_file = self.build_dist_tree(files, dirs) |
| distinfo_path = os.path.join(tempdir, distinfo) |
| egginfo_path = os.path.join(tempdir, egginfo) |
| metadata_file_paths = self.get_metadata_file_paths(distinfo_path) |
| |
| egginfo_to_distinfo(record_file) |
| # test that directories and files get created |
| self.assertTrue(os.path.isdir(distinfo_path)) |
| self.assertTrue(os.path.isdir(egginfo_path)) |
| |
| for mfile in metadata_file_paths: |
| self.assertTrue(os.path.isfile(mfile)) |
| |
| def test_egginfo_to_distinfo_distutils(self): |
| distinfo = 'hello-0.1.1-py3.3.dist-info' |
| egginfo = 'hello-0.1.1-py3.3.egg-info' |
| # egginfo is a file in distutils which contains the metadata |
| files = ['hello.py', 'hello.pyc', egginfo] |
| |
| tempdir, record_file = self.build_dist_tree(files, dirs=[]) |
| distinfo_path = os.path.join(tempdir, distinfo) |
| egginfo_path = os.path.join(tempdir, egginfo) |
| metadata_file_paths = self.get_metadata_file_paths(distinfo_path) |
| |
| egginfo_to_distinfo(record_file) |
| # test that directories and files get created |
| self.assertTrue(os.path.isdir(distinfo_path)) |
| self.assertTrue(os.path.isfile(egginfo_path)) |
| |
| for mfile in metadata_file_paths: |
| self.assertTrue(os.path.isfile(mfile)) |
| |
| def build_dist_tree(self, files, dirs): |
| tempdir = self.mkdtemp() |
| record_file_path = os.path.join(tempdir, 'RECORD') |
| file_paths, dir_paths = ([], []) |
| for d in dirs: |
| path = os.path.join(tempdir, d) |
| os.makedirs(path) |
| dir_paths.append(path) |
| for f in files: |
| path = os.path.join(tempdir, f) |
| with open(path, 'w') as _f: |
| _f.write(f) |
| file_paths.append(path) |
| |
| with open(record_file_path, 'w') as record_file: |
| for fpath in file_paths: |
| record_file.write(fpath + '\n') |
| for dpath in dir_paths: |
| record_file.write(dpath + '\n') |
| |
| return (tempdir, record_file_path) |
| |
| |
| class PackagingLibChecks(support.TempdirManager, |
| support.LoggingCatcher, |
| unittest.TestCase): |
| |
| def setUp(self): |
| super(PackagingLibChecks, self).setUp() |
| self._empty_dir = self.mkdtemp() |
| |
| def test_empty_package_is_not_based_on_anything(self): |
| self.assertFalse(is_setuptools(self._empty_dir)) |
| self.assertFalse(is_distutils(self._empty_dir)) |
| self.assertFalse(is_packaging(self._empty_dir)) |
| |
| def test_setup_py_importing_setuptools_is_setuptools_based(self): |
| self.assertTrue(is_setuptools(self._setuptools_setup_py_pkg())) |
| |
| def test_egg_info_dir_and_setup_py_is_setuptools_based(self): |
| self.assertTrue(is_setuptools(self._setuptools_egg_info_pkg())) |
| |
| def test_egg_info_and_non_setuptools_setup_py_is_setuptools_based(self): |
| self.assertTrue(is_setuptools(self._egg_info_with_no_setuptools())) |
| |
| def test_setup_py_not_importing_setuptools_is_not_setuptools_based(self): |
| self.assertFalse(is_setuptools(self._random_setup_py_pkg())) |
| |
| def test_setup_py_importing_distutils_is_distutils_based(self): |
| self.assertTrue(is_distutils(self._distutils_setup_py_pkg())) |
| |
| def test_pkg_info_file_and_setup_py_is_distutils_based(self): |
| self.assertTrue(is_distutils(self._distutils_pkg_info())) |
| |
| def test_pkg_info_and_non_distutils_setup_py_is_distutils_based(self): |
| self.assertTrue(is_distutils(self._pkg_info_with_no_distutils())) |
| |
| def test_setup_py_not_importing_distutils_is_not_distutils_based(self): |
| self.assertFalse(is_distutils(self._random_setup_py_pkg())) |
| |
| def test_setup_cfg_with_no_metadata_section_is_not_packaging_based(self): |
| self.assertFalse(is_packaging(self._setup_cfg_with_no_metadata_pkg())) |
| |
| def test_setup_cfg_with_valid_metadata_section_is_packaging_based(self): |
| self.assertTrue(is_packaging(self._valid_setup_cfg_pkg())) |
| |
| def test_setup_cfg_and_invalid_setup_cfg_is_not_packaging_based(self): |
| self.assertFalse(is_packaging(self._invalid_setup_cfg_pkg())) |
| |
| def test_get_install_method_with_setuptools_pkg(self): |
| path = self._setuptools_setup_py_pkg() |
| self.assertEqual("setuptools", get_install_method(path)) |
| |
| def test_get_install_method_with_distutils_pkg(self): |
| path = self._distutils_pkg_info() |
| self.assertEqual("distutils", get_install_method(path)) |
| |
| def test_get_install_method_with_packaging_pkg(self): |
| path = self._valid_setup_cfg_pkg() |
| self.assertEqual("packaging", get_install_method(path)) |
| |
| def test_get_install_method_with_unknown_pkg(self): |
| path = self._invalid_setup_cfg_pkg() |
| self.assertRaises(InstallationException, get_install_method, path) |
| |
| def test_is_setuptools_logs_setup_py_text_found(self): |
| is_setuptools(self._setuptools_setup_py_pkg()) |
| expected = ['setup.py file found.', |
| 'No egg-info directory found.', |
| 'Found setuptools text in setup.py.'] |
| self.assertEqual(expected, self.get_logs(logging.DEBUG)) |
| |
| def test_is_setuptools_logs_setup_py_text_not_found(self): |
| directory = self._random_setup_py_pkg() |
| is_setuptools(directory) |
| expected = ['setup.py file found.', 'No egg-info directory found.', |
| 'No setuptools text found in setup.py.'] |
| self.assertEqual(expected, self.get_logs(logging.DEBUG)) |
| |
| def test_is_setuptools_logs_egg_info_dir_found(self): |
| is_setuptools(self._setuptools_egg_info_pkg()) |
| expected = ['setup.py file found.', 'Found egg-info directory.'] |
| self.assertEqual(expected, self.get_logs(logging.DEBUG)) |
| |
| def test_is_distutils_logs_setup_py_text_found(self): |
| is_distutils(self._distutils_setup_py_pkg()) |
| expected = ['setup.py file found.', |
| 'No PKG-INFO file found.', |
| 'Found distutils text in setup.py.'] |
| self.assertEqual(expected, self.get_logs(logging.DEBUG)) |
| |
| def test_is_distutils_logs_setup_py_text_not_found(self): |
| directory = self._random_setup_py_pkg() |
| is_distutils(directory) |
| expected = ['setup.py file found.', 'No PKG-INFO file found.', |
| 'No distutils text found in setup.py.'] |
| self.assertEqual(expected, self.get_logs(logging.DEBUG)) |
| |
| def test_is_distutils_logs_pkg_info_file_found(self): |
| is_distutils(self._distutils_pkg_info()) |
| expected = ['setup.py file found.', 'PKG-INFO file found.'] |
| self.assertEqual(expected, self.get_logs(logging.DEBUG)) |
| |
| def test_is_packaging_logs_setup_cfg_found(self): |
| is_packaging(self._valid_setup_cfg_pkg()) |
| expected = ['setup.cfg file found.'] |
| self.assertEqual(expected, self.get_logs(logging.DEBUG)) |
| |
| def test_is_packaging_logs_setup_cfg_not_found(self): |
| is_packaging(self._empty_dir) |
| expected = ['No setup.cfg file found.'] |
| self.assertEqual(expected, self.get_logs(logging.DEBUG)) |
| |
| def _write_setuptools_setup_py(self, directory): |
| self.write_file((directory, 'setup.py'), |
| "from setuptools import setup") |
| |
| def _write_distutils_setup_py(self, directory): |
| self.write_file([directory, 'setup.py'], |
| "from distutils.core import setup") |
| |
| def _write_packaging_setup_cfg(self, directory): |
| self.write_file([directory, 'setup.cfg'], |
| ("[metadata]\n" |
| "name = mypackage\n" |
| "version = 0.1.0\n")) |
| |
| def _setuptools_setup_py_pkg(self): |
| tmp = self.mkdtemp() |
| self._write_setuptools_setup_py(tmp) |
| return tmp |
| |
| def _distutils_setup_py_pkg(self): |
| tmp = self.mkdtemp() |
| self._write_distutils_setup_py(tmp) |
| return tmp |
| |
| def _valid_setup_cfg_pkg(self): |
| tmp = self.mkdtemp() |
| self._write_packaging_setup_cfg(tmp) |
| return tmp |
| |
| def _setuptools_egg_info_pkg(self): |
| tmp = self.mkdtemp() |
| self._write_setuptools_setup_py(tmp) |
| tempfile.mkdtemp(suffix='.egg-info', dir=tmp) |
| return tmp |
| |
| def _distutils_pkg_info(self): |
| tmp = self._distutils_setup_py_pkg() |
| self.write_file([tmp, 'PKG-INFO'], '', encoding='UTF-8') |
| return tmp |
| |
| def _setup_cfg_with_no_metadata_pkg(self): |
| tmp = self.mkdtemp() |
| self.write_file([tmp, 'setup.cfg'], |
| ("[othersection]\n" |
| "foo = bar\n")) |
| return tmp |
| |
| def _invalid_setup_cfg_pkg(self): |
| tmp = self.mkdtemp() |
| self.write_file([tmp, 'setup.cfg'], |
| ("[metadata]\n" |
| "name = john\n" |
| "last_name = doe\n")) |
| return tmp |
| |
| def _egg_info_with_no_setuptools(self): |
| tmp = self._random_setup_py_pkg() |
| tempfile.mkdtemp(suffix='.egg-info', dir=tmp) |
| return tmp |
| |
| def _pkg_info_with_no_distutils(self): |
| tmp = self._random_setup_py_pkg() |
| self.write_file([tmp, 'PKG-INFO'], '', encoding='UTF-8') |
| return tmp |
| |
| def _random_setup_py_pkg(self): |
| tmp = self.mkdtemp() |
| self.write_file((tmp, 'setup.py'), "from mypackage import setup") |
| return tmp |
| |
| |
| def test_suite(): |
| suite = unittest.makeSuite(UtilTestCase) |
| suite.addTest(unittest.makeSuite(GlobTestCase)) |
| suite.addTest(unittest.makeSuite(EggInfoToDistInfoTestCase)) |
| suite.addTest(unittest.makeSuite(PackagingLibChecks)) |
| return suite |
| |
| |
| if __name__ == "__main__": |
| unittest.main(defaultTest="test_suite") |