晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。 林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。 见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝) 既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。 南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。
| DIR:/opt/cloudlinux/venv/lib64/python3.11/site-packages/setuptools/tests/ |
| Current File : //opt/cloudlinux/venv/lib64/python3.11/site-packages/setuptools/tests/test_build_py.py |
import os
import shutil
import stat
import warnings
from pathlib import Path
from unittest.mock import Mock
import jaraco.path
import pytest
from setuptools import SetuptoolsDeprecationWarning
from setuptools.dist import Distribution
from .textwrap import DALS
def test_directories_in_package_data_glob(tmpdir_cwd):
"""
Directories matching the glob in package_data should
not be included in the package data.
Regression test for #261.
"""
dist = Distribution(
dict(
script_name='setup.py',
script_args=['build_py'],
packages=[''],
package_data={'': ['path/*']},
)
)
os.makedirs('path/subpath')
dist.parse_command_line()
dist.run_commands()
def test_recursive_in_package_data_glob(tmpdir_cwd):
"""
Files matching recursive globs (**) in package_data should
be included in the package data.
#1806
"""
dist = Distribution(
dict(
script_name='setup.py',
script_args=['build_py'],
packages=[''],
package_data={'': ['path/**/data']},
)
)
os.makedirs('path/subpath/subsubpath')
open('path/subpath/subsubpath/data', 'wb').close()
dist.parse_command_line()
dist.run_commands()
assert stat.S_ISREG(os.stat('build/lib/path/subpath/subsubpath/data').st_mode), (
"File is not included"
)
def test_read_only(tmpdir_cwd):
"""
Ensure read-only flag is not preserved in copy
for package modules and package data, as that
causes problems with deleting read-only files on
Windows.
#1451
"""
dist = Distribution(
dict(
script_name='setup.py',
script_args=['build_py'],
packages=['pkg'],
package_data={'pkg': ['data.dat']},
)
)
os.makedirs('pkg')
open('pkg/__init__.py', 'wb').close()
open('pkg/data.dat', 'wb').close()
os.chmod('pkg/__init__.py', stat.S_IREAD)
os.chmod('pkg/data.dat', stat.S_IREAD)
dist.parse_command_line()
dist.run_commands()
shutil.rmtree('build')
@pytest.mark.xfail(
'platform.system() == "Windows"',
reason="On Windows, files do not have executable bits",
raises=AssertionError,
strict=True,
)
def test_executable_data(tmpdir_cwd):
"""
Ensure executable bit is preserved in copy for
package data, as users rely on it for scripts.
#2041
"""
dist = Distribution(
dict(
script_name='setup.py',
script_args=['build_py'],
packages=['pkg'],
package_data={'pkg': ['run-me']},
)
)
os.makedirs('pkg')
open('pkg/__init__.py', 'wb').close()
open('pkg/run-me', 'wb').close()
os.chmod('pkg/run-me', 0o700)
dist.parse_command_line()
dist.run_commands()
assert os.stat('build/lib/pkg/run-me').st_mode & stat.S_IEXEC, (
"Script is not executable"
)
EXAMPLE_WITH_MANIFEST = {
"setup.cfg": DALS(
"""
[metadata]
name = mypkg
version = 42
[options]
include_package_data = True
packages = find:
[options.packages.find]
exclude = *.tests*
"""
),
"mypkg": {
"__init__.py": "",
"resource_file.txt": "",
"tests": {
"__init__.py": "",
"test_mypkg.py": "",
"test_file.txt": "",
},
},
"MANIFEST.in": DALS(
"""
global-include *.py *.txt
global-exclude *.py[cod]
prune dist
prune build
prune *.egg-info
"""
),
}
def test_excluded_subpackages(tmpdir_cwd):
jaraco.path.build(EXAMPLE_WITH_MANIFEST)
dist = Distribution({"script_name": "%PEP 517%"})
dist.parse_config_files()
build_py = dist.get_command_obj("build_py")
msg = r"Python recognizes 'mypkg\.tests' as an importable package"
with pytest.warns(SetuptoolsDeprecationWarning, match=msg):
# TODO: To fix #3260 we need some transition period to deprecate the
# existing behavior of `include_package_data`. After the transition, we
# should remove the warning and fix the behavior.
if os.getenv("SETUPTOOLS_USE_DISTUTILS") == "stdlib":
# pytest.warns reset the warning filter temporarily
# https://github.com/pytest-dev/pytest/issues/4011#issuecomment-423494810
warnings.filterwarnings(
"ignore",
"'encoding' argument not specified",
module="distutils.text_file",
# This warning is already fixed in pypa/distutils but not in stdlib
)
build_py.finalize_options()
build_py.run()
build_dir = Path(dist.get_command_obj("build_py").build_lib)
assert (build_dir / "mypkg/__init__.py").exists()
assert (build_dir / "mypkg/resource_file.txt").exists()
# Setuptools is configured to ignore `mypkg.tests`, therefore the following
# files/dirs should not be included in the distribution.
for f in [
"mypkg/tests/__init__.py",
"mypkg/tests/test_mypkg.py",
"mypkg/tests/test_file.txt",
"mypkg/tests",
]:
with pytest.raises(AssertionError):
# TODO: Enforce the following assertion once #3260 is fixed
# (remove context manager and the following xfail).
assert not (build_dir / f).exists()
pytest.xfail("#3260")
@pytest.mark.filterwarnings("ignore::setuptools.SetuptoolsDeprecationWarning")
def test_existing_egg_info(tmpdir_cwd, monkeypatch):
"""When provided with the ``existing_egg_info_dir`` attribute, build_py should not
attempt to run egg_info again.
"""
# == Pre-condition ==
# Generate an egg-info dir
jaraco.path.build(EXAMPLE_WITH_MANIFEST)
dist = Distribution({"script_name": "%PEP 517%"})
dist.parse_config_files()
assert dist.include_package_data
egg_info = dist.get_command_obj("egg_info")
dist.run_command("egg_info")
egg_info_dir = next(Path(egg_info.egg_base).glob("*.egg-info"))
assert egg_info_dir.is_dir()
# == Setup ==
build_py = dist.get_command_obj("build_py")
build_py.finalize_options()
egg_info = dist.get_command_obj("egg_info")
egg_info_run = Mock(side_effect=egg_info.run)
monkeypatch.setattr(egg_info, "run", egg_info_run)
# == Remove caches ==
# egg_info is called when build_py looks for data_files, which gets cached.
# We need to ensure it is not cached yet, otherwise it may impact on the tests
build_py.__dict__.pop('data_files', None)
dist.reinitialize_command(egg_info)
# == Sanity check ==
# Ensure that if existing_egg_info is not given, build_py attempts to run egg_info
build_py.existing_egg_info_dir = None
build_py.run()
egg_info_run.assert_called()
# == Remove caches ==
egg_info_run.reset_mock()
build_py.__dict__.pop('data_files', None)
dist.reinitialize_command(egg_info)
# == Actual test ==
# Ensure that if existing_egg_info_dir is given, egg_info doesn't run
build_py.existing_egg_info_dir = egg_info_dir
build_py.run()
egg_info_run.assert_not_called()
assert build_py.data_files
# Make sure the list of outputs is actually OK
outputs = map(lambda x: x.replace(os.sep, "/"), build_py.get_outputs())
assert outputs
example = str(Path(build_py.build_lib, "mypkg/__init__.py")).replace(os.sep, "/")
assert example in outputs
EXAMPLE_ARBITRARY_MAPPING = {
"pyproject.toml": DALS(
"""
[project]
name = "mypkg"
version = "42"
[tool.setuptools]
packages = ["mypkg", "mypkg.sub1", "mypkg.sub2", "mypkg.sub2.nested"]
[tool.setuptools.package-dir]
"" = "src"
"mypkg.sub2" = "src/mypkg/_sub2"
"mypkg.sub2.nested" = "other"
"""
),
"src": {
"mypkg": {
"__init__.py": "",
"resource_file.txt": "",
"sub1": {
"__init__.py": "",
"mod1.py": "",
},
"_sub2": {
"mod2.py": "",
},
},
},
"other": {
"__init__.py": "",
"mod3.py": "",
},
"MANIFEST.in": DALS(
"""
global-include *.py *.txt
global-exclude *.py[cod]
"""
),
}
def test_get_outputs(tmpdir_cwd):
jaraco.path.build(EXAMPLE_ARBITRARY_MAPPING)
dist = Distribution({"script_name": "%test%"})
dist.parse_config_files()
build_py = dist.get_command_obj("build_py")
build_py.editable_mode = True
build_py.ensure_finalized()
build_lib = build_py.build_lib.replace(os.sep, "/")
outputs = {x.replace(os.sep, "/") for x in build_py.get_outputs()}
assert outputs == {
f"{build_lib}/mypkg/__init__.py",
f"{build_lib}/mypkg/resource_file.txt",
f"{build_lib}/mypkg/sub1/__init__.py",
f"{build_lib}/mypkg/sub1/mod1.py",
f"{build_lib}/mypkg/sub2/mod2.py",
f"{build_lib}/mypkg/sub2/nested/__init__.py",
f"{build_lib}/mypkg/sub2/nested/mod3.py",
}
mapping = {
k.replace(os.sep, "/"): v.replace(os.sep, "/")
for k, v in build_py.get_output_mapping().items()
}
assert mapping == {
f"{build_lib}/mypkg/__init__.py": "src/mypkg/__init__.py",
f"{build_lib}/mypkg/resource_file.txt": "src/mypkg/resource_file.txt",
f"{build_lib}/mypkg/sub1/__init__.py": "src/mypkg/sub1/__init__.py",
f"{build_lib}/mypkg/sub1/mod1.py": "src/mypkg/sub1/mod1.py",
f"{build_lib}/mypkg/sub2/mod2.py": "src/mypkg/_sub2/mod2.py",
f"{build_lib}/mypkg/sub2/nested/__init__.py": "other/__init__.py",
f"{build_lib}/mypkg/sub2/nested/mod3.py": "other/mod3.py",
}
class TestTypeInfoFiles:
PYPROJECTS = {
"default_pyproject": DALS(
"""
[project]
name = "foo"
version = "1"
"""
),
"dont_include_package_data": DALS(
"""
[project]
name = "foo"
version = "1"
[tool.setuptools]
include-package-data = false
"""
),
"exclude_type_info": DALS(
"""
[project]
name = "foo"
version = "1"
[tool.setuptools]
include-package-data = false
[tool.setuptools.exclude-package-data]
"*" = ["py.typed", "*.pyi"]
"""
),
}
EXAMPLES = {
"simple_namespace": {
"directory_structure": {
"foo": {
"bar.pyi": "",
"py.typed": "",
"__init__.py": "",
}
},
"expected_type_files": {"foo/bar.pyi", "foo/py.typed"},
},
"nested_inside_namespace": {
"directory_structure": {
"foo": {
"bar": {
"py.typed": "",
"mod.pyi": "",
}
}
},
"expected_type_files": {"foo/bar/mod.pyi", "foo/bar/py.typed"},
},
"namespace_nested_inside_regular": {
"directory_structure": {
"foo": {
"namespace": {
"foo.pyi": "",
},
"__init__.pyi": "",
"py.typed": "",
}
},
"expected_type_files": {
"foo/namespace/foo.pyi",
"foo/__init__.pyi",
"foo/py.typed",
},
},
}
@pytest.mark.parametrize(
"pyproject",
[
"default_pyproject",
pytest.param(
"dont_include_package_data",
marks=pytest.mark.xfail(reason="pypa/setuptools#4350"),
),
],
)
@pytest.mark.parametrize("example", EXAMPLES.keys())
def test_type_files_included_by_default(self, tmpdir_cwd, pyproject, example):
structure = {
**self.EXAMPLES[example]["directory_structure"],
"pyproject.toml": self.PYPROJECTS[pyproject],
}
expected_type_files = self.EXAMPLES[example]["expected_type_files"]
jaraco.path.build(structure)
build_py = get_finalized_build_py()
outputs = get_outputs(build_py)
assert expected_type_files <= outputs
@pytest.mark.parametrize("pyproject", ["exclude_type_info"])
@pytest.mark.parametrize("example", EXAMPLES.keys())
def test_type_files_can_be_excluded(self, tmpdir_cwd, pyproject, example):
structure = {
**self.EXAMPLES[example]["directory_structure"],
"pyproject.toml": self.PYPROJECTS[pyproject],
}
expected_type_files = self.EXAMPLES[example]["expected_type_files"]
jaraco.path.build(structure)
build_py = get_finalized_build_py()
outputs = get_outputs(build_py)
assert expected_type_files.isdisjoint(outputs)
def test_stub_only_package(self, tmpdir_cwd):
structure = {
"pyproject.toml": DALS(
"""
[project]
name = "foo-stubs"
version = "1"
"""
),
"foo-stubs": {"__init__.pyi": "", "bar.pyi": ""},
}
expected_type_files = {"foo-stubs/__init__.pyi", "foo-stubs/bar.pyi"}
jaraco.path.build(structure)
build_py = get_finalized_build_py()
outputs = get_outputs(build_py)
assert expected_type_files <= outputs
def get_finalized_build_py(script_name="%build_py-test%"):
dist = Distribution({"script_name": script_name})
dist.parse_config_files()
build_py = dist.get_command_obj("build_py")
build_py.finalize_options()
return build_py
def get_outputs(build_py):
build_dir = Path(build_py.build_lib)
return {
os.path.relpath(x, build_dir).replace(os.sep, "/")
for x in build_py.get_outputs()
}
|