You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
9.3 KiB
263 lines
9.3 KiB
import pytest |
|
import yaml |
|
|
|
from pathlib import Path |
|
from pprint import pprint |
|
|
|
from pyproject_preprocess_record import parse_record, read_record, save_parsed_record |
|
|
|
from pyproject_save_files import argparser, generate_file_list, BuildrootPath |
|
from pyproject_save_files import main as save_files_main |
|
from pyproject_save_files import module_names_from_path |
|
|
|
DIR = Path(__file__).parent |
|
PREFIX = Path("/usr") |
|
BINDIR = BuildrootPath("/usr/bin") |
|
DATADIR = BuildrootPath("/usr/share") |
|
SITELIB = BuildrootPath("/usr/lib/python3.7/site-packages") |
|
SITEARCH = BuildrootPath("/usr/lib64/python3.7/site-packages") |
|
|
|
yaml_file = DIR / "pyproject_save_files_test_data.yaml" |
|
yaml_data = yaml.safe_load(yaml_file.read_text()) |
|
EXPECTED_DICT = yaml_data["classified"] |
|
EXPECTED_FILES = yaml_data["dumped"] |
|
TEST_RECORDS = yaml_data["records"] |
|
TEST_METADATAS = yaml_data["metadata"] |
|
|
|
|
|
@pytest.fixture |
|
def tldr_root(tmp_path): |
|
prepare_pyproject_record(tmp_path, package="tldr") |
|
return tmp_path |
|
|
|
|
|
@pytest.fixture |
|
def pyproject_record(tmp_path): |
|
return tmp_path / "pyproject-record" |
|
|
|
|
|
def prepare_pyproject_record(tmp_path, package=None, content=None): |
|
""" |
|
Creates RECORD from test data and then uses |
|
functions from pyproject_process_record to convert |
|
it to pyproject-record file which is then |
|
further processed by functions from pyproject_save_files. |
|
""" |
|
record_file = tmp_path / "RECORD" |
|
pyproject_record = tmp_path / "pyproject-record" |
|
|
|
if package is not None: |
|
# Get test data and write dist-info/RECORD file |
|
record_path = BuildrootPath(TEST_RECORDS[package]["path"]) |
|
record_file.write_text(TEST_RECORDS[package]["content"]) |
|
if package in TEST_METADATAS: |
|
metadata_path = BuildrootPath(TEST_METADATAS[package]["path"]).to_real(tmp_path) |
|
metadata_path.parent.mkdir(parents=True, exist_ok=True) |
|
metadata_path.write_text(TEST_METADATAS[package]["content"]) |
|
# Parse RECORD file |
|
parsed_record = parse_record(record_path, read_record(record_file)) |
|
# Save JSON content to pyproject-record |
|
save_parsed_record(record_path, parsed_record, pyproject_record) |
|
elif content is not None: |
|
save_parsed_record(*content, output_file=pyproject_record) |
|
|
|
|
|
@pytest.fixture |
|
def output_files(tmp_path): |
|
return tmp_path / "pyproject_files" |
|
|
|
@pytest.fixture |
|
def output_modules(tmp_path): |
|
return tmp_path / "pyproject_modules" |
|
|
|
|
|
def test_parse_record_tldr(): |
|
record_path = BuildrootPath(TEST_RECORDS["tldr"]["path"]) |
|
record_content = read_record(DIR / "test_RECORD") |
|
output = list(parse_record(record_path, record_content)) |
|
pprint(output) |
|
expected = [ |
|
str(BINDIR / "__pycache__/tldr.cpython-37.pyc"), |
|
str(BINDIR / "tldr"), |
|
str(BINDIR / "tldr.py"), |
|
str(SITELIB / "__pycache__/tldr.cpython-37.pyc"), |
|
str(SITELIB / "tldr-0.5.dist-info/INSTALLER"), |
|
str(SITELIB / "tldr-0.5.dist-info/LICENSE"), |
|
str(SITELIB / "tldr-0.5.dist-info/METADATA"), |
|
str(SITELIB / "tldr-0.5.dist-info/RECORD"), |
|
str(SITELIB / "tldr-0.5.dist-info/WHEEL"), |
|
str(SITELIB / "tldr-0.5.dist-info/top_level.txt"), |
|
str(SITELIB / "tldr.py"), |
|
] |
|
assert output == expected |
|
|
|
|
|
def test_parse_record_tensorflow(): |
|
long = "tensorflow_core/include/tensorflow/core/common_runtime/base_collective_executor.h" |
|
record_path = SITEARCH / "tensorflow-2.1.0.dist-info/RECORD" |
|
record_content = [ |
|
["../../../bin/toco_from_protos", "sha256=hello", "289"], |
|
[f"../../../lib/python3.7/site-packages/{long}", "sha256=darkness", "1024"], |
|
["tensorflow-2.1.0.dist-info/METADATA", "sha256=friend", "2859"], |
|
] |
|
output = list(parse_record(record_path, record_content)) |
|
pprint(output) |
|
expected = [ |
|
str(BINDIR / "toco_from_protos"), |
|
str(SITELIB / long), |
|
str(SITEARCH / "tensorflow-2.1.0.dist-info/METADATA"), |
|
] |
|
assert output == expected |
|
|
|
|
|
def remove_others(expected): |
|
return [ |
|
p for p in expected |
|
if not ( |
|
p.startswith(str(BINDIR)) or |
|
p.endswith(".pth") or |
|
p.endswith("*") or |
|
p.rpartition(' ')[-1].startswith(str(DATADIR)) |
|
) |
|
] |
|
|
|
|
|
@pytest.mark.parametrize("include_auto", (True, False)) |
|
@pytest.mark.parametrize("package, glob, expected_files, expected_modules", EXPECTED_FILES) |
|
def test_generate_file_list(package, glob, expected_files, include_auto, expected_modules): |
|
paths_dict = EXPECTED_DICT[package] |
|
modules_glob = {glob} |
|
if not include_auto: |
|
expected_files = remove_others(expected_files) |
|
tested = generate_file_list(paths_dict, modules_glob, include_auto) |
|
|
|
assert tested == expected_files |
|
|
|
|
|
def test_generate_file_list_unused_glob(): |
|
paths_dict = EXPECTED_DICT["kerberos"] |
|
modules_glob = {"kerberos", "unused_glob1", "unused_glob2", "kerb*"} |
|
with pytest.raises(ValueError) as excinfo: |
|
generate_file_list(paths_dict, modules_glob, True) |
|
|
|
assert "unused_glob1, unused_glob2" in str(excinfo.value) |
|
assert "kerb" not in str(excinfo.value) |
|
|
|
|
|
@pytest.mark.parametrize( |
|
"path, expected", |
|
[ |
|
("foo/bar/baz.py", {"foo", "foo.bar", "foo.bar.baz"}), |
|
("foo/bar.py", {"foo", "foo.bar"}), |
|
("foo.py", {"foo"}), |
|
("foo/bar.so.2", set()), |
|
("foo.cpython-37m-x86_64-linux-gnu.so", {"foo"}), |
|
("foo/_api/v2/__init__.py", set()), |
|
("foo/__init__.py", {"foo"}), |
|
("foo/_priv.py", set()), |
|
("foo/_bar/lib.so", set()), |
|
("foo/bar/baz.so", {"foo", "foo.bar", "foo.bar.baz"}), |
|
("foo/bar/baz.pth", set()), |
|
("foo/bar/baz.pyc", set()), |
|
("def.py", set()), |
|
("foo-bar/baz.py", set()), |
|
("foobar/12baz.py", set()), |
|
("foo/\nbar/baz.py", set()), |
|
("foo/+bar/baz.py", set()), |
|
("foo/__init__.cpython-39-x86_64-linux-gnu.so", {"foo"}), |
|
("foo/bar/__pycache__/abc.cpython-37.pyc", set()), |
|
], |
|
) |
|
def test_module_names_from_path(path, expected): |
|
tested = Path(path) |
|
assert module_names_from_path(tested) == expected |
|
|
|
|
|
def default_options(output_files, output_modules, mock_root, pyproject_record): |
|
return [ |
|
"--output-files", |
|
str(output_files), |
|
"--output-modules", |
|
str(output_modules), |
|
"--buildroot", |
|
str(mock_root), |
|
"--sitelib", |
|
str(SITELIB), |
|
"--sitearch", |
|
str(SITEARCH), |
|
"--python-version", |
|
"3.7", # test data are for 3.7, |
|
"--pyproject-record", |
|
str(pyproject_record), |
|
"--prefix", |
|
str(PREFIX), |
|
] |
|
|
|
|
|
@pytest.mark.parametrize("include_auto", (True, False)) |
|
@pytest.mark.parametrize("package, glob, expected_files, expected_modules", EXPECTED_FILES) |
|
def test_cli(tmp_path, package, glob, expected_files, expected_modules, include_auto, pyproject_record): |
|
prepare_pyproject_record(tmp_path, package) |
|
output_files = tmp_path / "files" |
|
output_modules = tmp_path / "modules" |
|
globs = [glob, "+auto"] if include_auto else [glob] |
|
cli_args = argparser().parse_args([*default_options(output_files, output_modules, tmp_path, pyproject_record), *globs]) |
|
save_files_main(cli_args) |
|
|
|
if not include_auto: |
|
expected_files = remove_others(expected_files) |
|
tested_files = output_files.read_text() |
|
assert tested_files == "\n".join(expected_files) + "\n" |
|
|
|
tested_modules = output_modules.read_text().split() |
|
|
|
assert tested_modules == expected_modules |
|
|
|
|
|
def test_cli_no_pyproject_record(tmp_path, pyproject_record): |
|
output_files = tmp_path / "files" |
|
output_modules = tmp_path / "modules" |
|
cli_args = argparser().parse_args([*default_options(output_files, output_modules, tmp_path, pyproject_record), "tldr*"]) |
|
|
|
with pytest.raises(FileNotFoundError): |
|
save_files_main(cli_args) |
|
|
|
|
|
def test_cli_too_many_RECORDS(tldr_root, output_files, output_modules, pyproject_record): |
|
# Two calls to simulate how %pyproject_install process more than one RECORD file |
|
prepare_pyproject_record(tldr_root, |
|
content=("foo/bar/dist-info/RECORD", [])) |
|
prepare_pyproject_record(tldr_root, |
|
content=("foo/baz/dist-info/RECORD", [])) |
|
cli_args = argparser().parse_args([*default_options(output_files, output_modules, tldr_root, pyproject_record), "tldr*"]) |
|
|
|
with pytest.raises(FileExistsError): |
|
save_files_main(cli_args) |
|
|
|
|
|
def test_cli_bad_argument(tldr_root, output_files, output_modules, pyproject_record): |
|
cli_args = argparser().parse_args( |
|
[*default_options(output_files, output_modules, tldr_root, pyproject_record), "tldr*", "+foodir"] |
|
) |
|
|
|
with pytest.raises(ValueError): |
|
save_files_main(cli_args) |
|
|
|
|
|
def test_cli_bad_option(tldr_root, output_files, output_modules, pyproject_record): |
|
prepare_pyproject_record(tldr_root.parent, content=("RECORD1", [])) |
|
cli_args = argparser().parse_args( |
|
[*default_options(output_files, output_modules, tldr_root, pyproject_record), "tldr*", "you_cannot_have_this"] |
|
) |
|
|
|
with pytest.raises(ValueError): |
|
save_files_main(cli_args) |
|
|
|
|
|
def test_cli_bad_namespace(tldr_root, output_files, output_modules, pyproject_record): |
|
cli_args = argparser().parse_args( |
|
[*default_options(output_files, output_modules, tldr_root, pyproject_record), "tldr.didntread"] |
|
) |
|
|
|
with pytest.raises(ValueError): |
|
save_files_main(cli_args)
|
|
|