def test_dont_install_setup_requires(self, tmpdir_cwd): files = { 'setup.py': DALS(""" from setuptools import setup setup( name="qux", version="0.0.0", py_modules=["hello"], setup_requires=["does-not-exist >99"], ) """), 'hello.py': DALS(""" def run(): print('hello') """), } path.build(files) build_backend = self.get_build_backend() dist_dir = os.path.abspath('pip-dist-info') os.makedirs(dist_dir) # does-not-exist can't be satisfied, so if it attempts to install # setup_requires, it will fail. build_backend.prepare_metadata_for_build_wheel(dist_dir)
def test_tests_are_run_once(capfd): params = dict(packages=['dummy'], ) files = { 'setup.py': 'from setuptools import setup; setup(' + ','.join(f'{name}={params[name]!r}' for name in params) + ')', 'dummy': { '__init__.py': '', 'test_dummy.py': DALS(""" import unittest class TestTest(unittest.TestCase): def test_test(self): print('Foo') """), }, } path.build(files) dist = Distribution(params) dist.script_name = 'setup.py' cmd = test(dist) cmd.ensure_finalized() cmd.run() out, err = capfd.readouterr() assert out.endswith('Foo\n') assert len(out.split('Foo')) == 2
def test_license_is_a_string(self, tmpdir_cwd, env): setup_config = DALS(""" [metadata] name=foo version=0.0.1 license=file:MIT """) setup_script = DALS(""" from setuptools import setup setup() """) path.build({ 'setup.py': setup_script, 'setup.cfg': setup_config, }) # This command should fail with a ValueError, but because it's # currently configured to use a subprocess, the actual traceback # object is lost and we need to parse it from stderr with pytest.raises(AssertionError) as exc: self._run_egg_info_command(tmpdir_cwd, env) # Hopefully this is not too fragile: the only argument to the # assertion error should be a traceback, ending with: # ValueError: .... # # assert not 1 tb = exc.value.args[0].split('\n') assert tb[-3].lstrip().startswith('ValueError')
def test_egg_info_save_version_info_setup_defaults(self, tmpdir_cwd, env): """ When running save_version_info on an existing setup.cfg with the 'default' values present from a previous run, the file should remain unchanged. """ setup_cfg = os.path.join(env.paths['home'], 'setup.cfg') path.build({ setup_cfg: DALS(""" [egg_info] tag_build = tag_date = 0 """), }) dist = Distribution() ei = egg_info(dist) ei.initialize_options() ei.save_version_info(setup_cfg) with open(setup_cfg, 'r') as f: content = f.read() assert '[egg_info]' in content assert 'tag_build =' in content assert 'tag_date = 0' in content expected_order = 'tag_build', 'tag_date', self._validate_content_order(content, expected_order)
def test_build_with_empty_setuppy(self, build_backend, build_hook): files = {'setup.py': ''} path.build(files) with pytest.raises(ValueError, match=re.escape('No distribution was found.')): getattr(build_backend, build_hook)("temp")
def test_build_sdist_setup_py_exists(self, tmpdir_cwd): # If build_sdist is called from a script other than setup.py, # ensure setup.py is included path.build(defns[0]) build_backend = self.get_build_backend() targz_path = build_backend.build_sdist("temp") with tarfile.open(os.path.join("temp", targz_path)) as tar: assert any('setup.py' in name for name in tar.getnames())
def _create_project(self): path.build({ 'setup.py': self.setup_script, 'hello.py': DALS(""" def run(): print('hello') """) })
def _setup_script_with_requires(self, requires, use_setup_cfg=False): setup_script = DALS(''' from setuptools import setup setup(name='foo', zip_safe=False, %s) ''') % ('' if use_setup_cfg else requires) setup_config = requires if use_setup_cfg else '' path.build({ 'setup.py': setup_script, 'setup.cfg': setup_config, })
def sample_project(tmpdir_cwd): path.build({ 'setup.py': DALS(""" from setuptools import setup setup(name='foo') """), 'build': { 'index.html': 'Hello world.', 'empty': {}, } })
def sphinx_doc_sample_project(tmpdir_cwd): path.build({ 'setup.py': 'from setuptools import setup; setup()', 'build': { 'docs': { 'conf.py': 'project="test"', 'index.rst': ".. toctree::\ :maxdepth: 2\ :caption: Contents:", }, }, })
def test_build_with_existing_file_present(self, build_type, tmpdir_cwd): # Building a sdist/wheel should still succeed if there's # already a sdist/wheel in the destination directory. files = { 'setup.py': "from setuptools import setup\nsetup()", 'VERSION': "0.0.1", 'setup.cfg': DALS(""" [metadata] name = foo version = file: VERSION """), 'pyproject.toml': DALS(""" [build-system] requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" """), } path.build(files) dist_dir = os.path.abspath('preexisting-' + build_type) build_backend = self.get_build_backend() build_method = getattr(build_backend, 'build_' + build_type) # Build a first sdist/wheel. # Note: this also check the destination directory is # successfully created if it does not exist already. first_result = build_method(dist_dir) # Change version. with open("VERSION", "wt") as version_file: version_file.write("0.0.2") # Build a *second* sdist/wheel. second_result = build_method(dist_dir) assert os.path.isfile(os.path.join(dist_dir, first_result)) assert first_result != second_result # And if rebuilding the exact same sdist/wheel? open(os.path.join(dist_dir, second_result), 'w').close() third_result = build_method(dist_dir) assert third_result == second_result assert os.path.getsize(os.path.join(dist_dir, third_result)) > 0
def test_setup_requires_with_transitive_extra_dependency( self, monkeypatch): # Use case: installing a package with a build dependency on # an already installed `dep[extra]`, which in turn depends # on `extra_dep` (whose is not already installed). with contexts.save_pkg_resources_state(): with contexts.tempdir() as temp_dir: # Create source distribution for `extra_dep`. make_trivial_sdist( os.path.join(temp_dir, 'extra_dep-1.0.tar.gz'), 'extra_dep', '1.0') # Create source tree for `dep`. dep_pkg = os.path.join(temp_dir, 'dep') os.mkdir(dep_pkg) path.build( { 'setup.py': DALS(""" import setuptools setuptools.setup( name='dep', version='2.0', extras_require={'extra': ['extra_dep']}, ) """), 'setup.cfg': '', }, prefix=dep_pkg) # "Install" dep. run_setup(os.path.join(dep_pkg, 'setup.py'), [str('dist_info')]) working_set.add_entry(dep_pkg) # Create source tree for test package. test_pkg = os.path.join(temp_dir, 'test_pkg') test_setup_py = os.path.join(test_pkg, 'setup.py') os.mkdir(test_pkg) with open(test_setup_py, 'w') as fp: fp.write( DALS(''' from setuptools import installer, setup setup(setup_requires='dep[extra]') ''')) # Check... monkeypatch.setenv(str('PIP_FIND_LINKS'), str(temp_dir)) monkeypatch.setenv(str('PIP_NO_INDEX'), str('1')) monkeypatch.setenv(str('PIP_RETRIES'), str('0')) monkeypatch.setenv(str('PIP_TIMEOUT'), str('0')) run_setup(test_setup_py, [str('--version')])
def test_egg_info_tag_only_once(self, tmpdir_cwd, env): self._create_project() path.build({ 'setup.cfg': DALS(""" [egg_info] tag_build = dev tag_date = 0 tag_svn_revision = 0 """), }) self._run_egg_info_command(tmpdir_cwd, env) egg_info_dir = os.path.join('.', 'foo.egg-info') with open(os.path.join(egg_info_dir, 'PKG-INFO')) as pkginfo_file: pkg_info_lines = pkginfo_file.read().split('\n') assert 'Version: 0.0.0.dev0' in pkg_info_lines
def test_manifest_template_is_read(self, tmpdir_cwd, env): self._create_project() path.build({ 'MANIFEST.in': DALS(""" recursive-include docs *.rst """), 'docs': { 'usage.rst': "Run 'hi'", } }) self._run_egg_info_command(tmpdir_cwd, env) egg_info_dir = os.path.join('.', 'foo.egg-info') sources_txt = os.path.join(egg_info_dir, 'SOURCES.txt') with open(sources_txt) as f: assert 'docs/usage.rst' in f.read().split('\n')
def build_wheel(extra_file_defs=None, **kwargs): file_defs = { 'setup.py': (DALS(''' # -*- coding: utf-8 -*- from setuptools import setup import setuptools setup(**%r) ''') % kwargs).encode('utf-8'), } if extra_file_defs: file_defs.update(extra_file_defs) with tempdir() as source_dir: path.build(file_defs, source_dir) subprocess.check_call( (sys.executable, 'setup.py', '-q', 'bdist_wheel'), cwd=source_dir) yield glob.glob(os.path.join(source_dir, 'dist', '*.whl'))[0]
def env(self): with contexts.tempdir(prefix='setuptools-test.') as env_dir: env = Environment(env_dir) os.chmod(env_dir, stat.S_IRWXU) subs = 'home', 'lib', 'scripts', 'data', 'egg-base' env.paths = dict( (dirname, os.path.join(env_dir, dirname)) for dirname in subs) list(map(os.mkdir, env.paths.values())) path.build({ env.paths['home']: { '.pydistutils.cfg': DALS(""" [egg_info] egg-base = %(egg-base)s """ % env.paths) } }) yield env
def test_build_sdist_builds_targz_even_if_zip_indicated(self, tmpdir_cwd): files = { 'setup.py': DALS(""" __import__('setuptools').setup( name='foo', version='0.0.0', py_modules=['hello'] )"""), 'hello.py': '', 'setup.cfg': DALS(""" [sdist] formats=zip """) } path.build(files) build_backend = self.get_build_backend() build_backend.build_sdist("temp")
def test_setup_cfg_license_files(self, tmpdir_cwd, env, files, incl_licenses, excl_licenses): self._create_project() path.build(files) environment.run_setup_py(cmd=['egg_info'], pypath=os.pathsep.join( [env.paths['lib'], str(tmpdir_cwd)])) egg_info_dir = os.path.join('.', 'foo.egg-info') with open(os.path.join(egg_info_dir, 'SOURCES.txt')) as sources_file: sources_lines = list(line.strip() for line in sources_file) for lf in incl_licenses: assert sources_lines.count(lf) == 1 for lf in excl_licenses: assert sources_lines.count(lf) == 0
def test_setup_cfg_license_file(self, tmpdir_cwd, env, files, license_in_sources): self._create_project() path.build(files) environment.run_setup_py(cmd=['egg_info'], pypath=os.pathsep.join( [env.paths['lib'], str(tmpdir_cwd)])) egg_info_dir = os.path.join('.', 'foo.egg-info') with open(os.path.join(egg_info_dir, 'SOURCES.txt')) as sources_file: sources_text = sources_file.read() if license_in_sources: assert 'LICENSE' in sources_text else: assert 'LICENSE' not in sources_text # for invalid license test assert 'INVALID_LICENSE' not in sources_text
def test_build_sdist_pyproject_toml_exists(self, tmpdir_cwd): files = { 'setup.py': DALS(""" __import__('setuptools').setup( name='foo', version='0.0.0', py_modules=['hello'] )"""), 'hello.py': '', 'pyproject.toml': DALS(""" [build-system] requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta """), } path.build(files) build_backend = self.get_build_backend() targz_path = build_backend.build_sdist("temp") with tarfile.open(os.path.join("temp", targz_path)) as tar: assert any('pyproject.toml' in name for name in tar.getnames())
def test_setup_requires_with_allow_hosts(self, mock_index): ''' The `allow-hosts` option in not supported anymore. ''' files = { 'test_pkg': { 'setup.py': DALS(''' from setuptools import setup setup(setup_requires='python-xlib') '''), 'setup.cfg': DALS(''' [easy_install] allow_hosts = * '''), } } with contexts.save_pkg_resources_state(): with contexts.tempdir() as temp_dir: path.build(files, prefix=temp_dir) setup_py = str(pathlib.Path(temp_dir, 'test_pkg', 'setup.py')) with pytest.raises(distutils.errors.DistutilsError): run_setup(setup_py, [str('--version')]) assert len(mock_index.requests) == 0
def test_build_sdist_setup_py_manifest_excluded(self, tmpdir_cwd): # Ensure that MANIFEST.in can exclude setup.py files = { 'setup.py': DALS(""" __import__('setuptools').setup( name='foo', version='0.0.0', py_modules=['hello'] )"""), 'hello.py': '', 'MANIFEST.in': DALS(""" exclude setup.py """) } path.build(files) build_backend = self.get_build_backend() targz_path = build_backend.build_sdist("temp") with tarfile.open(os.path.join("temp", targz_path)) as tar: assert not any('setup.py' in name for name in tar.getnames())
def test_setup_requires(self, setup_literal, requirements, use_wheel, tmpdir_cwd): files = { 'setup.py': DALS(""" from setuptools import setup setup( name="qux", version="0.0.0", py_modules=["hello"], setup_requires={setup_literal}, ) """).format(setup_literal=setup_literal), 'hello.py': DALS(""" def run(): print('hello') """), } path.build(files) build_backend = self.get_build_backend() if use_wheel: base_requirements = ['wheel'] get_requires = build_backend.get_requires_for_build_wheel else: base_requirements = [] get_requires = build_backend.get_requires_for_build_sdist # Ensure that the build requirements are properly parsed expected = sorted(base_requirements + requirements) actual = get_requires() assert expected == sorted(actual)
def test_license_file_attr_pkg_info(self, tmpdir_cwd, env): """All matched license files should have a corresponding License-File.""" self._create_project() path.build({ "setup.cfg": DALS(""" [metadata] license_files = NOTICE* LICENSE* """), "LICENSE-ABC": "ABC license", "LICENSE-XYZ": "XYZ license", "NOTICE": "included", "IGNORE": "not include", }) environment.run_setup_py(cmd=['egg_info'], pypath=os.pathsep.join( [env.paths['lib'], str(tmpdir_cwd)])) egg_info_dir = os.path.join('.', 'foo.egg-info') with open(os.path.join(egg_info_dir, 'PKG-INFO')) as pkginfo_file: pkg_info_lines = pkginfo_file.read().split('\n') license_file_lines = [ line for line in pkg_info_lines if line.startswith('License-File:') ] # Only 'NOTICE', LICENSE-ABC', and 'LICENSE-XYZ' should have been matched # Also assert that order from license_files is keeped assert "License-File: NOTICE" == license_file_lines[0] assert "License-File: LICENSE-ABC" in license_file_lines[1:] assert "License-File: LICENSE-XYZ" in license_file_lines[1:]
def test_sys_argv_passthrough(self, tmpdir_cwd): path.build(self._sys_argv_0_passthrough) build_backend = self.get_build_backend() with pytest.raises(AssertionError): build_backend.build_sdist("temp")
def test_glob(monkeypatch, tmpdir, tree, pattern, matches): monkeypatch.chdir(tmpdir) path.build({name: '' for name in tree.split()}) assert list(sorted(glob(pattern))) == list(sorted(matches))
def build_backend(self, tmpdir, request): path.build(request.param, prefix=str(tmpdir)) with tmpdir.as_cwd(): yield self.get_build_backend()
def test_build_sdist_relative_path_import(self, tmpdir_cwd): path.build(self._relative_path_import_files) build_backend = self.get_build_backend() with pytest.raises(ImportError, match="^No module named 'hello'$"): build_backend.build_sdist("temp")
def test_sys_argv_passthrough(self, tmpdir_cwd): path.build(self._sys_argv_0_passthrough) build_backend = self.get_build_backend() build_backend.build_sdist("temp")
def test_build_sdist_relative_path_import(self, tmpdir_cwd): # This must fail in build_meta, but must pass in build_meta_legacy path.build(self._relative_path_import_files) build_backend = self.get_build_backend() build_backend.build_sdist("temp")