Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions distutils/_modified.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

import functools
import os
import os.path
from collections.abc import Callable, Iterable
from typing import Literal, TypeVar
Expand Down Expand Up @@ -91,4 +91,22 @@ def missing_as_newer(source):
)


newer_pairwise_group = functools.partial(newer_pairwise, newer=newer_group)
def _as_source_group(source):
if isinstance(source, (str, bytes, os.PathLike)):
return (source,)
return source


def newer_pairwise_group(sources, targets, missing: Literal["error", "ignore", "newer"] = "error"):
"""
Filter source groups that are newer than their paired targets.

Each item in *sources* is a group of files passed to ``newer_group``.
A single path is treated as a one-file group, so a string is not
iterated as individual characters.
"""

def _group_newer(source, target):
return newer_group(_as_source_group(source), target, missing=missing)

return newer_pairwise(sources, targets, newer=_group_newer)
18 changes: 18 additions & 0 deletions distutils/tests/test_modified.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,24 @@ def test_newer_pairwise_group(groups_target):
assert newer == ([groups_target.newer], [groups_target.target])


def test_newer_pairwise_group_single_path(tmp_path):
"""A string path is a one-file group, not an iterable of characters."""
src = tmp_path / "source.c"
old_tgt = tmp_path / "old.o"
new_tgt = tmp_path / "new.o"
src.write_text("", encoding="utf-8")
old_tgt.write_text("", encoding="utf-8")
new_tgt.write_text("", encoding="utf-8")
os.utime(src, (10, 10))
os.utime(old_tgt, (1, 1))
os.utime(new_tgt, (20, 20))

stale = newer_pairwise_group([str(src)], [str(new_tgt)])
dirty = newer_pairwise_group([str(src)], [str(old_tgt)])
assert stale == ([], [])
assert dirty == ([str(src)], [str(old_tgt)])


def test_newer_group_no_sources_no_target(tmp_path):
"""
Consider no sources and no target "newer".
Expand Down
1 change: 1 addition & 0 deletions newsfragments/411.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``newer_pairwise_group`` now treats a string path as a one-file group instead of iterating its characters. (pypa/distutils#411)