Skip to content

Commit

Permalink
Include schemes with records, when calling finalise_installation (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
FFY00 authored Oct 13, 2021
1 parent 628ab4c commit 2968e5f
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 68 deletions.
11 changes: 5 additions & 6 deletions src/installer/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
from installer.exceptions import InvalidWheelSource
from installer.records import RecordEntry
from installer.sources import WheelSource
from installer.utils import SCHEME_NAMES, parse_entrypoints, parse_metadata_file
from installer.utils import SCHEME_NAMES, Scheme, parse_entrypoints, parse_metadata_file

if TYPE_CHECKING:
from typing import Dict, Tuple

from installer._compat.typing import Binary, FSPath
from installer.utils import Scheme


__all__ = ["install"]
Expand Down Expand Up @@ -94,7 +93,7 @@ def install(source, destination, additional_metadata):
attr=attr,
section=section,
)
written_records.append(record)
written_records.append((Scheme("scripts"), record))

# Write all the files from the wheel.
for record_elements, stream in source.get_contents():
Expand All @@ -115,7 +114,7 @@ def install(source, destination, additional_metadata):
path=destination_path,
stream=stream,
)
written_records.append(record)
written_records.append((scheme, record))

# Write all the installation-specific metadata
for filename, contents in additional_metadata.items():
Expand All @@ -127,9 +126,9 @@ def install(source, destination, additional_metadata):
path=path,
stream=other_stream,
)
written_records.append(record)
written_records.append((root_scheme, record))

written_records.append(RecordEntry(record_file_path, None, None))
written_records.append((root_scheme, RecordEntry(record_file_path, None, None)))
destination.finalize_installation(
scheme=root_scheme,
record_file_path=record_file_path,
Expand Down
6 changes: 3 additions & 3 deletions src/installer/destinations.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
)

if TYPE_CHECKING:
from typing import BinaryIO, Dict, Iterable
from typing import BinaryIO, Dict, Iterable, Tuple

from installer._compat.typing import FSPath, Text
from installer.scripts import LauncherKind, ScriptSection
Expand Down Expand Up @@ -65,7 +65,7 @@ def write_file(self, scheme, path, stream):
raise NotImplementedError

def finalize_installation(self, scheme, record_file_path, records):
# type: (Scheme, FSPath, Iterable[RecordEntry]) -> None
# type: (Scheme, FSPath, Iterable[Tuple[Scheme, RecordEntry]]) -> None
"""Finalize installation, after all the files are written.
Handles (re)writing of the ``RECORD`` file.
Expand Down Expand Up @@ -180,7 +180,7 @@ def write_script(self, name, module, attr, section):
return entry

def finalize_installation(self, scheme, record_file_path, records):
# type: (Scheme, FSPath, Iterable[RecordEntry]) -> None
# type: (Scheme, FSPath, Iterable[Tuple[Scheme, RecordEntry]]) -> None
"""Finalize installation, by writing the ``RECORD`` file.
:param scheme: scheme to write the ``RECORD`` file in
Expand Down
4 changes: 2 additions & 2 deletions src/installer/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,13 @@ def fix_shebang(stream, interpreter):


def construct_record_file(records):
# type: (Iterable[RecordEntry]) -> BinaryIO
# type: (Iterable[Tuple[Scheme, RecordEntry]]) -> BinaryIO
"""Construct a RECORD file given some records.
The original stream should be closed by the caller.
"""
stream = io.BytesIO()
for record in records:
for scheme, record in records:
stream.write(str(record).encode("utf-8") + b"\n")
stream.seek(0)
return stream
Expand Down
122 changes: 82 additions & 40 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,16 +205,28 @@ def main():
scheme="purelib",
record_file_path="fancy-1.0.0.dist-info/RECORD",
records=[
("fancy", "fancy", "main", "console"),
("fancy-gui", "fancy", "main", "gui"),
("fancy/__init__.py", "purelib", 0),
("fancy/__main__.py", "purelib", 0),
("fancy-1.0.0.dist-info/METADATA", "purelib", 0),
("fancy-1.0.0.dist-info/WHEEL", "purelib", 0),
("fancy-1.0.0.dist-info/entry_points.txt", "purelib", 0),
("fancy-1.0.0.dist-info/top_level.txt", "purelib", 0),
("fancy-1.0.0.dist-info/fun_file.txt", "purelib", 0),
RecordEntry("fancy-1.0.0.dist-info/RECORD", None, None),
("scripts", ("fancy", "fancy", "main", "console")),
("scripts", ("fancy-gui", "fancy", "main", "gui")),
("purelib", ("fancy/__init__.py", "purelib", 0)),
("purelib", ("fancy/__main__.py", "purelib", 0)),
("purelib", ("fancy-1.0.0.dist-info/METADATA", "purelib", 0)),
("purelib", ("fancy-1.0.0.dist-info/WHEEL", "purelib", 0)),
(
"purelib",
("fancy-1.0.0.dist-info/entry_points.txt", "purelib", 0),
),
(
"purelib",
("fancy-1.0.0.dist-info/top_level.txt", "purelib", 0),
),
(
"purelib",
("fancy-1.0.0.dist-info/fun_file.txt", "purelib", 0),
),
(
"purelib",
RecordEntry("fancy-1.0.0.dist-info/RECORD", None, None),
),
],
),
]
Expand Down Expand Up @@ -305,13 +317,22 @@ def main():
scheme="purelib",
record_file_path="fancy-1.0.0.dist-info/RECORD",
records=[
("fancy/__init__.py", "purelib", 0),
("fancy/__main__.py", "purelib", 0),
("fancy-1.0.0.dist-info/METADATA", "purelib", 0),
("fancy-1.0.0.dist-info/WHEEL", "purelib", 0),
("fancy-1.0.0.dist-info/top_level.txt", "purelib", 0),
("fancy-1.0.0.dist-info/fun_file.txt", "purelib", 0),
RecordEntry("fancy-1.0.0.dist-info/RECORD", None, None),
("purelib", ("fancy/__init__.py", "purelib", 0)),
("purelib", ("fancy/__main__.py", "purelib", 0)),
("purelib", ("fancy-1.0.0.dist-info/METADATA", "purelib", 0)),
("purelib", ("fancy-1.0.0.dist-info/WHEEL", "purelib", 0)),
(
"purelib",
("fancy-1.0.0.dist-info/top_level.txt", "purelib", 0),
),
(
"purelib",
("fancy-1.0.0.dist-info/fun_file.txt", "purelib", 0),
),
(
"purelib",
RecordEntry("fancy-1.0.0.dist-info/RECORD", None, None),
),
],
),
]
Expand Down Expand Up @@ -426,16 +447,28 @@ def main():
scheme="platlib",
record_file_path="fancy-1.0.0.dist-info/RECORD",
records=[
("fancy", "fancy", "main", "console"),
("fancy-gui", "fancy", "main", "gui"),
("fancy/__init__.py", "platlib", 0),
("fancy/__main__.py", "platlib", 0),
("fancy-1.0.0.dist-info/METADATA", "platlib", 0),
("fancy-1.0.0.dist-info/WHEEL", "platlib", 0),
("fancy-1.0.0.dist-info/entry_points.txt", "platlib", 0),
("fancy-1.0.0.dist-info/top_level.txt", "platlib", 0),
("fancy-1.0.0.dist-info/fun_file.txt", "platlib", 0),
RecordEntry("fancy-1.0.0.dist-info/RECORD", None, None),
("scripts", ("fancy", "fancy", "main", "console")),
("scripts", ("fancy-gui", "fancy", "main", "gui")),
("platlib", ("fancy/__init__.py", "platlib", 0)),
("platlib", ("fancy/__main__.py", "platlib", 0)),
("platlib", ("fancy-1.0.0.dist-info/METADATA", "platlib", 0)),
("platlib", ("fancy-1.0.0.dist-info/WHEEL", "platlib", 0)),
(
"platlib",
("fancy-1.0.0.dist-info/entry_points.txt", "platlib", 0),
),
(
"platlib",
("fancy-1.0.0.dist-info/top_level.txt", "platlib", 0),
),
(
"platlib",
("fancy-1.0.0.dist-info/fun_file.txt", "platlib", 0),
),
(
"platlib",
RecordEntry("fancy-1.0.0.dist-info/RECORD", None, None),
),
],
),
]
Expand Down Expand Up @@ -691,19 +724,28 @@ def test_handles_data_properly(self, mock_destination):
scheme="purelib",
record_file_path="fancy-1.0.0.dist-info/RECORD",
records=[
("fancy", "fancy", "main", "console"),
("fancy-gui", "fancy", "main", "gui"),
("fancy/data.py", "data", 0),
("fancy/headers.py", "headers", 0),
("fancy/platlib.py", "platlib", 0),
("fancy/purelib.py", "purelib", 0),
("fancy/scripts.py", "scripts", 0),
("fancy/__init__.py", "purelib", 0),
("fancy-1.0.0.dist-info/METADATA", "purelib", 0),
("fancy-1.0.0.dist-info/WHEEL", "purelib", 0),
("fancy-1.0.0.dist-info/entry_points.txt", "purelib", 0),
("fancy-1.0.0.dist-info/top_level.txt", "purelib", 0),
RecordEntry("fancy-1.0.0.dist-info/RECORD", None, None),
("scripts", ("fancy", "fancy", "main", "console")),
("scripts", ("fancy-gui", "fancy", "main", "gui")),
("data", ("fancy/data.py", "data", 0)),
("headers", ("fancy/headers.py", "headers", 0)),
("platlib", ("fancy/platlib.py", "platlib", 0)),
("purelib", ("fancy/purelib.py", "purelib", 0)),
("scripts", ("fancy/scripts.py", "scripts", 0)),
("purelib", ("fancy/__init__.py", "purelib", 0)),
("purelib", ("fancy-1.0.0.dist-info/METADATA", "purelib", 0)),
("purelib", ("fancy-1.0.0.dist-info/WHEEL", "purelib", 0)),
(
"purelib",
("fancy-1.0.0.dist-info/entry_points.txt", "purelib", 0),
),
(
"purelib",
("fancy-1.0.0.dist-info/top_level.txt", "purelib", 0),
),
(
"purelib",
RecordEntry("fancy-1.0.0.dist-info/RECORD", None, None),
),
],
),
]
Expand Down
44 changes: 35 additions & 9 deletions tests/test_destinations.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,43 @@ def test_write_script(self, destination):

def test_finalize_write_record(self, destination):
records = [
destination.write_file("data", "my_data1.bin", io.BytesIO(b"my data 1")),
destination.write_file("data", "my_data2.bin", io.BytesIO(b"my data 2")),
destination.write_file("data", "my_data3.bin", io.BytesIO(b"my data 3")),
destination.write_file("scripts", "my_script", io.BytesIO(b"my script")),
destination.write_file(
"scripts", "my_script2", io.BytesIO(b"#!python\nmy script")
(
"data",
destination.write_file(
"data", "my_data1.bin", io.BytesIO(b"my data 1")
),
),
(
"data",
destination.write_file(
"data", "my_data2.bin", io.BytesIO(b"my data 2")
),
),
destination.write_script(
"my_entrypoint", "my_module", "my_function", "console"
(
"data",
destination.write_file(
"data", "my_data3.bin", io.BytesIO(b"my data 3")
),
),
(
"scripts",
destination.write_file(
"scripts", "my_script", io.BytesIO(b"my script")
),
),
(
"scripts",
destination.write_file(
"scripts", "my_script2", io.BytesIO(b"#!python\nmy script")
),
),
(
"scripts",
destination.write_script(
"my_entrypoint", "my_module", "my_function", "console"
),
),
RecordEntry("RECORD", None, None),
("purelib", RecordEntry("RECORD", None, None)),
]

destination.finalize_installation("purelib", "RECORD", records)
Expand Down
27 changes: 20 additions & 7 deletions tests/test_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,31 @@ def record_input(request):

SAMPLE_RECORDS = [
(
"purelib",
("test1.py", "sha256=Y0sCextp4SQtQNU-MSs7SsdxD1W-gfKJtUlEbvZ3i-4", 6),
b"test1\n",
True,
),
(
"purelib",
("test2.py", "sha256=fW_Xd08Nh2JNptzxbQ09EEwxkedx--LznIau1LK_Gg8", 6),
b"test2\n",
True,
),
(
"purelib",
("test3.py", "sha256=qwPDTx7OCCEf4qgDn9ZCQZmz9de1X_E7ETSzZHdsRcU", 6),
b"test3\n",
True,
),
(
"purelib",
("test4.py", "sha256=Y0sCextp4SQtQNU-MSs7SsdxD1W-gfKJtUlEbvZ3i-4", 7),
b"test1\n",
False,
),
(
"purelib",
(
"test5.py",
"sha256=Y0sCextp4SQtQNU-MSs7SsdxD1W-gfKJtUlEbvZ3i-4",
Expand All @@ -62,7 +67,7 @@ def record_input(request):
b"test1\n",
True,
),
(("test6.py", None, None), b"test1\n", True),
("purelib", ("test6.py", None, None), b"test1\n", True),
]


Expand Down Expand Up @@ -100,8 +105,12 @@ def test_invalid_elements(self, path, hash_, size, caused_by):
def test_valid_elements(self, path, hash_, size):
RecordEntry.from_elements(path, hash_, size)

@pytest.mark.parametrize(("elements", "data", "passes_validation"), SAMPLE_RECORDS)
def test_populates_attributes_correctly(self, elements, data, passes_validation):
@pytest.mark.parametrize(
("scheme", "elements", "data", "passes_validation"), SAMPLE_RECORDS
)
def test_populates_attributes_correctly(
self, scheme, elements, data, passes_validation
):
path, hash_string, size = elements

record = RecordEntry.from_elements(path, hash_string, size)
Expand All @@ -114,13 +123,17 @@ def test_populates_attributes_correctly(self, elements, data, passes_validation)
assert record.hash_.name == "sha256"
assert record.hash_.value == hash_string[len("sha256=") :]

@pytest.mark.parametrize(("elements", "data", "passes_validation"), SAMPLE_RECORDS)
def test_validation(self, elements, data, passes_validation):
@pytest.mark.parametrize(
("scheme", "elements", "data", "passes_validation"), SAMPLE_RECORDS
)
def test_validation(self, scheme, elements, data, passes_validation):
record = RecordEntry.from_elements(*elements)
assert record.validate(data) == passes_validation

@pytest.mark.parametrize(("elements", "data", "passes_validation"), SAMPLE_RECORDS)
def test_string_representation(self, elements, data, passes_validation):
@pytest.mark.parametrize(
("scheme", "elements", "data", "passes_validation"), SAMPLE_RECORDS
)
def test_string_representation(self, scheme, elements, data, passes_validation):
record = RecordEntry.from_elements(*elements)

expected_string_value = ",".join(
Expand Down
3 changes: 2 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ def test_keep_data(self, data):
class TestConstructRecord:
def test_construct(self):
records = [
RecordEntry.from_elements(*elements) for elements, _, _ in SAMPLE_RECORDS
(scheme, RecordEntry.from_elements(*elements))
for scheme, elements, _, _ in SAMPLE_RECORDS
]
assert construct_record_file(records).read() == (
b"test1.py,sha256=Y0sCextp4SQtQNU-MSs7SsdxD1W-gfKJtUlEbvZ3i-4,6\n"
Expand Down

0 comments on commit 2968e5f

Please sign in to comment.