Skip to content

Commit

Permalink
fix: leading zeros can confuse human sorting. #1709
Browse files Browse the repository at this point in the history
  • Loading branch information
nedbat committed Dec 12, 2023
1 parent 1adda03 commit 170f1ea
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ Unreleased
matching any of the lines, closing `issue 684`_. Thanks, `Jan Rusak,
Maciej Kowalczyk and Joanna Ejzel <pull 1705_>`_.

- Fix: XML reports could fail with a TypeError if files had numeric components
that were duplicates except for leading zeroes, like ``file1.py`` and
``file001.py``. Fixes `issue 1709`_.

- The ``coverage annotate`` command used to announce that it would be removed
in a future version. Enough people got in touch to say that they use it, so
it will stay. Don't expect it to keep up with other new features though.
Expand All @@ -36,6 +40,7 @@ Unreleased

.. _issue 684: https://github.com/nedbat/coveragepy/issues/684
.. _pull 1705: https://github.com/nedbat/coveragepy/pull/1705
.. _issue 1709: https://github.com/nedbat/coveragepy/issues/1709


.. scriv-start-here
Expand Down
10 changes: 7 additions & 3 deletions coverage/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,13 @@ def import_local_file(modname: str, modfile: Optional[str] = None) -> ModuleType
return mod


def _human_key(s: str) -> List[Union[str, int]]:
def _human_key(s: str) -> Tuple[List[Union[str, int]], str]:
"""Turn a string into a list of string and number chunks.
"z23a" -> ["z", 23, "a"]
"z23a" -> (["z", 23, "a"], "z23a")
The original string is appended as a last value to ensure the
key is unique enough so that "x1y" and "x001y" can be distinguished.
"""
def tryint(s: str) -> Union[str, int]:
"""If `s` is a number, return an int, else `s` unchanged."""
Expand All @@ -349,7 +353,7 @@ def tryint(s: str) -> Union[str, int]:
except ValueError:
return s

return [tryint(c) for c in re.split(r"(\d+)", s)]
return ([tryint(c) for c in re.split(r"(\d+)", s)], s)

def human_sorted(strings: Iterable[str]) -> List[str]:
"""Sort the given iterable of strings the way that humans expect.
Expand Down
4 changes: 3 additions & 1 deletion tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def test_failure(self) -> None:


HUMAN_DATA = [
("z1 a2z a2a a3 a1", "a1 a2a a2z a3 z1"),
("z1 a2z a01 a2a a3 a1", "a01 a1 a2a a2z a3 z1"),
("a10 a9 a100 a1", "a1 a9 a10 a100"),
("4.0 3.10-win 3.10-mac 3.9-mac 3.9-win", "3.9-mac 3.9-win 3.10-mac 3.10-win 4.0"),
]
Expand All @@ -149,6 +149,8 @@ def test_human_sorted(words: str, ordered: str) -> None:
@pytest.mark.parametrize("words, ordered", HUMAN_DATA)
def test_human_sorted_items(words: str, ordered: str) -> None:
keys = words.split()
# Check that we never try to compare the values in the items
human_sorted_items([(k, object()) for k in keys])
items = [(k, 1) for k in keys] + [(k, 2) for k in keys]
okeys = ordered.split()
oitems = [(k, v) for k in okeys for v in [1, 2]]
Expand Down
12 changes: 12 additions & 0 deletions tests/test_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,18 @@ def test_no_duplicate_packages(self) -> None:
named_sub_package = dom.findall(".//package[@name='namespace.package.subpackage']")
assert len(named_sub_package) == 1

def test_bug_1709(self) -> None:
self.make_file("main.py", "import x1y, x01y, x001y")
self.make_file("x1y.py", "print('x1y')")
self.make_file("x01y.py", "print('x01y')")
self.make_file("x001y.py", "print('x001y')")

cov = coverage.Coverage()
self.start_import_stop(cov, "main")
assert self.stdout() == "x1y\nx01y\nx001y\n"
# This used to raise: TypeError: '<' not supported between instances of 'Element' and 'Element'
cov.xml_report()


def unbackslash(v: Any) -> Any:
"""Find strings in `v`, and replace backslashes with slashes throughout."""
Expand Down

0 comments on commit 170f1ea

Please sign in to comment.