I added an assert to track down the origin of the issue and was surprised to find out the was a lot of breakage, other than mine.
After fixing my code, I get the following when running the test suite.
platform linux -- Python 3.9.1, pytest-6.2.1, py-1.10.0, pluggy-0.13.1
rootdir: /home/anubis/git/installer
plugins: forked-1.3.0, xdist-2.2.0, cov-2.10.1
gw0 I / gw1 I / gw2 I / gw3 I / gw4 I / gw5 I / gw6 I / gw7 I
gw0 [74] / gw1 [74] / gw2 [74] / gw3 [74] / gw4 [74] / gw5 [74] / gw6 [74] / gw7 [74]
.....................F..FF.F.....F........F...F.................F.....F. [ 95%]
F. [100%]
=================================== FAILURES ===================================
__________ TestSchemeDictionaryDestination.test_finalize_write_record __________
[gw6] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_destinations.TestSchemeDictionaryDestination object at 0x7f1e33d62c40>
destination = <installer.destinations.SchemeDictionaryDestination object at 0x7f1e33d752b0>
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")
),
destination.write_script(
"my_entrypoint", "my_module", "my_function", "console"
),
]
> destination.finalize_installation("purelib", "RECORD", records)
tests/test_destinations.py:107:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/test-3-9/lib/python3.9/site-packages/installer/destinations.py:113: in finalize_installation
record = RecordEntry("RECORD", None, None)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7f1e33d75970>
path = 'RECORD', hash_ = None, size = None
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
_________________ TestRecordEntry.test_valid_elements[a.py--] __________________
[gw3] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_records.TestRecordEntry object at 0x7f4829b0c490>, path = 'a.py'
hash_ = '', size = ''
@pytest.mark.parametrize(
"path, hash_, size",
[
("a.py", "", ""),
("a.py", "", "3144"),
("a.py", "sha256=AVTFPZpEKzuHr7OvQZmhaU3LvwKz06AJw8mT\\_pNh2yI", ""),
("a.py", "sha256=AVTFPZpEKzuHr7OvQZmhaU3LvwKz06AJw8mT\\_pNh2yI", "3144"),
],
)
def test_valid_elements(self, path, hash_, size):
> RecordEntry.from_elements(path, hash_, size)
tests/test_records.py:101:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:187: in from_elements
return cls(path=path, hash_=hash_value, size=size_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7f4829b0c070>
path = 'a.py', hash_ = None, size = None
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
_______________ TestRecordEntry.test_valid_elements[a.py--3144] ________________
[gw4] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_records.TestRecordEntry object at 0x7fd644679400>, path = 'a.py'
hash_ = '', size = '3144'
@pytest.mark.parametrize(
"path, hash_, size",
[
("a.py", "", ""),
("a.py", "", "3144"),
("a.py", "sha256=AVTFPZpEKzuHr7OvQZmhaU3LvwKz06AJw8mT\\_pNh2yI", ""),
("a.py", "sha256=AVTFPZpEKzuHr7OvQZmhaU3LvwKz06AJw8mT\\_pNh2yI", "3144"),
],
)
def test_valid_elements(self, path, hash_, size):
> RecordEntry.from_elements(path, hash_, size)
tests/test_records.py:101:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:187: in from_elements
return cls(path=path, hash_=hash_value, size=size_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7fd644679700>
path = 'a.py', hash_ = None, size = 3144
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
_ TestRecordEntry.test_populates_attributes_correctly[elements5-test1\n-True] __
[gw5] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_records.TestRecordEntry object at 0x7fcb28978130>
elements = ('test6.py', None, None), data = b'test1\n', passes_validation = True
@pytest.mark.parametrize(("elements", "data", "passes_validation"), SAMPLE_RECORDS)
def test_populates_attributes_correctly(self, elements, data, passes_validation):
path, hash_string, size = elements
> record = RecordEntry.from_elements(path, hash_string, size)
tests/test_records.py:107:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:187: in from_elements
return cls(path=path, hash_=hash_value, size=size_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7fcb289897f0>
path = 'test6.py', hash_ = None, size = None
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
___________ TestRecordEntry.test_validation[elements5-test1\n-True] ____________
[gw1] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_records.TestRecordEntry object at 0x7fc7554a96d0>
elements = ('test6.py', None, None), data = b'test1\n', passes_validation = True
@pytest.mark.parametrize(("elements", "data", "passes_validation"), SAMPLE_RECORDS)
def test_validation(self, elements, data, passes_validation):
> record = RecordEntry.from_elements(*elements)
tests/test_records.py:119:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:187: in from_elements
return cls(path=path, hash_=hash_value, size=size_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7fc7554a95e0>
path = 'test6.py', hash_ = None, size = None
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
______ TestRecordEntry.test_string_representation[elements5-test1\n-True] ______
[gw7] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_records.TestRecordEntry object at 0x7fd3f8c3d670>
elements = ('test6.py', None, None), data = b'test1\n', passes_validation = True
@pytest.mark.parametrize(("elements", "data", "passes_validation"), SAMPLE_RECORDS)
def test_string_representation(self, elements, data, passes_validation):
> record = RecordEntry.from_elements(*elements)
tests/test_records.py:124:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:187: in from_elements
return cls(path=path, hash_=hash_value, size=size_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7fd3f8c3d6a0>
path = 'test6.py', hash_ = None, size = None
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
_ TestParseRecordFile.test_accepts_all_kinds_of_iterables[record_simple_list] __
[gw2] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_records.TestParseRecordFile object at 0x7fa168a29ac0>
record_input = ['file.py,sha256=AVTFPZpEKzuHr7OvQZmhaU3LvwKz06AJw8mT\\_pNh2yI,3144', 'distribution-1.0.dist-info/RECORD,,']
@pytest.mark.parametrize(
"record_input",
["record_simple_list", "record_simple_iter", "record_simple_file"],
indirect=True,
)
def test_accepts_all_kinds_of_iterables(self, record_input):
"""Should accepts any iterable, e.g. container, iterator, or file object."""
> records = list(parse_record_file(record_input))
tests/test_records.py:143:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:204: in parse_record_file
record = RecordEntry.from_elements(elements[0], elements[1], elements[2])
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:187: in from_elements
return cls(path=path, hash_=hash_value, size=size_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7fa168a29f40>
path = 'distribution-1.0.dist-info/RECORD', hash_ = None, size = None
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
_ TestParseRecordFile.test_accepts_all_kinds_of_iterables[record_simple_iter] __
[gw7] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_records.TestParseRecordFile object at 0x7fd3f8be87c0>
record_input = <list_iterator object at 0x7fd3f8be8fd0>
@pytest.mark.parametrize(
"record_input",
["record_simple_list", "record_simple_iter", "record_simple_file"],
indirect=True,
)
def test_accepts_all_kinds_of_iterables(self, record_input):
"""Should accepts any iterable, e.g. container, iterator, or file object."""
> records = list(parse_record_file(record_input))
tests/test_records.py:143:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:204: in parse_record_file
record = RecordEntry.from_elements(elements[0], elements[1], elements[2])
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:187: in from_elements
return cls(path=path, hash_=hash_value, size=size_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7fd3f8be8d00>
path = 'distribution-1.0.dist-info/RECORD', hash_ = None, size = None
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
_ TestParseRecordFile.test_accepts_all_kinds_of_iterables[record_simple_file] __
[gw2] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_records.TestParseRecordFile object at 0x7fa1689dae50>
record_input = <_io.TextIOWrapper name='/tmp/pytest-of-anubis/pytest-84/popen-gw2/test_accepts_all_kinds_of_iter0/RECORD' mode='r' encoding='UTF-8'>
@pytest.mark.parametrize(
"record_input",
["record_simple_list", "record_simple_iter", "record_simple_file"],
indirect=True,
)
def test_accepts_all_kinds_of_iterables(self, record_input):
"""Should accepts any iterable, e.g. container, iterator, or file object."""
> records = list(parse_record_file(record_input))
tests/test_records.py:143:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:204: in parse_record_file
record = RecordEntry.from_elements(elements[0], elements[1], elements[2])
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:187: in from_elements
return cls(path=path, hash_=hash_value, size=size_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7fa168a29760>
path = 'distribution-1.0.dist-info/RECORD', hash_ = None, size = None
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
______________________ TestConstructRecord.test_construct ______________________
[gw5] linux -- Python 3.9.1 /home/anubis/git/installer/.nox/test-3-9/bin/python
self = <test_utils.TestConstructRecord object at 0x7fcb289439a0>
def test_construct(self):
> records = [
RecordEntry.from_elements(*elements) for elements, _, _ in SAMPLE_RECORDS
]
tests/test_utils.py:154:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_utils.py:155: in <listcomp>
RecordEntry.from_elements(*elements) for elements, _, _ in SAMPLE_RECORDS
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:187: in from_elements
return cls(path=path, hash_=hash_value, size=size_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'RecordEntry' object has no attribute 'path'") raised in repr()] RecordEntry object at 0x7fcb28943820>
path = 'test6.py', hash_ = None, size = None
def __init__(self, path, hash_, size):
# type: (FSPath, Optional[Hash], Optional[int]) -> None
r"""Construct a ``RecordEntry`` object.
Most consumers should use :py:meth:`RecordEntry.from_elements`, since no
validation or parsing is performed by this constructor.
:param path: file's path
:param hash\_: hash of the file's contents
:param size: file's size in bytes
"""
super(RecordEntry, self).__init__()
> assert isinstance(hash_, Hash)
E AssertionError
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py:108: AssertionError
----------- coverage: platform linux, python 3.9.1-final-0 -----------
Name Stmts Miss Cover Missing
------------------------------------------------------------------------------------------------------------------
.nox/test-3-9/lib/python3.9/site-packages/installer/__init__.py 1 0 100%
.nox/test-3-9/lib/python3.9/site-packages/installer/_compat/__init__.py 0 0 100%
.nox/test-3-9/lib/python3.9/site-packages/installer/_compat/importlib_resources.py 3 0 100%
.nox/test-3-9/lib/python3.9/site-packages/installer/_compat/typing.py 4 0 100%
.nox/test-3-9/lib/python3.9/site-packages/installer/_scripts/__init__.py 0 0 100%
.nox/test-3-9/lib/python3.9/site-packages/installer/destinations.py 39 1 97% 114
.nox/test-3-9/lib/python3.9/site-packages/installer/records.py 67 1 99% 142
.nox/test-3-9/lib/python3.9/site-packages/installer/scripts.py 53 0 100%
.nox/test-3-9/lib/python3.9/site-packages/installer/sources.py 19 0 100%
.nox/test-3-9/lib/python3.9/site-packages/installer/utils.py 53 5 91% 151-155
------------------------------------------------------------------------------------------------------------------
TOTAL 239 7 97%
Coverage HTML written to dir /home/anubis/git/installer/.nox/test-3-9/htmlcov
FAIL Required test coverage of 100% not reached. Total coverage: 97.07%
=========================== short test summary info ============================
FAILED tests/test_destinations.py::TestSchemeDictionaryDestination::test_finalize_write_record
FAILED tests/test_records.py::TestRecordEntry::test_valid_elements[a.py--] - ...
FAILED tests/test_records.py::TestRecordEntry::test_valid_elements[a.py--3144]
FAILED tests/test_records.py::TestRecordEntry::test_populates_attributes_correctly[elements5-test1\n-True]
FAILED tests/test_records.py::TestRecordEntry::test_validation[elements5-test1\n-True]
FAILED tests/test_records.py::TestRecordEntry::test_string_representation[elements5-test1\n-True]
FAILED tests/test_records.py::TestParseRecordFile::test_accepts_all_kinds_of_iterables[record_simple_list]
FAILED tests/test_records.py::TestParseRecordFile::test_accepts_all_kinds_of_iterables[record_simple_iter]
FAILED tests/test_records.py::TestParseRecordFile::test_accepts_all_kinds_of_iterables[record_simple_file]
FAILED tests/test_utils.py::TestConstructRecord::test_construct - AssertionError
======================== 10 failed, 64 passed in 0.99s =========================
We should fix this and maybe consider actually adding an assert there to avoid people some trouble.