You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			96 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			96 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
"""Timestamp comparison of files and groups of files."""
 | 
						|
 | 
						|
from __future__ import annotations
 | 
						|
 | 
						|
import functools
 | 
						|
import os.path
 | 
						|
from collections.abc import Callable, Iterable
 | 
						|
from typing import Literal, TypeVar
 | 
						|
 | 
						|
from jaraco.functools import splat
 | 
						|
 | 
						|
from .compat.py39 import zip_strict
 | 
						|
from .errors import DistutilsFileError
 | 
						|
 | 
						|
_SourcesT = TypeVar(
 | 
						|
    "_SourcesT", bound="str | bytes | os.PathLike[str] | os.PathLike[bytes]"
 | 
						|
)
 | 
						|
_TargetsT = TypeVar(
 | 
						|
    "_TargetsT", bound="str | bytes | os.PathLike[str] | os.PathLike[bytes]"
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def _newer(source, target):
 | 
						|
    return not os.path.exists(target) or (
 | 
						|
        os.path.getmtime(source) > os.path.getmtime(target)
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
def newer(
 | 
						|
    source: str | bytes | os.PathLike[str] | os.PathLike[bytes],
 | 
						|
    target: str | bytes | os.PathLike[str] | os.PathLike[bytes],
 | 
						|
) -> bool:
 | 
						|
    """
 | 
						|
    Is source modified more recently than target.
 | 
						|
 | 
						|
    Returns True if 'source' is modified more recently than
 | 
						|
    'target' or if 'target' does not exist.
 | 
						|
 | 
						|
    Raises DistutilsFileError if 'source' does not exist.
 | 
						|
    """
 | 
						|
    if not os.path.exists(source):
 | 
						|
        raise DistutilsFileError(f"file {os.path.abspath(source)!r} does not exist")
 | 
						|
 | 
						|
    return _newer(source, target)
 | 
						|
 | 
						|
 | 
						|
def newer_pairwise(
 | 
						|
    sources: Iterable[_SourcesT],
 | 
						|
    targets: Iterable[_TargetsT],
 | 
						|
    newer: Callable[[_SourcesT, _TargetsT], bool] = newer,
 | 
						|
) -> tuple[list[_SourcesT], list[_TargetsT]]:
 | 
						|
    """
 | 
						|
    Filter filenames where sources are newer than targets.
 | 
						|
 | 
						|
    Walk two filename iterables in parallel, testing if each source is newer
 | 
						|
    than its corresponding target.  Returns a pair of lists (sources,
 | 
						|
    targets) where source is newer than target, according to the semantics
 | 
						|
    of 'newer()'.
 | 
						|
    """
 | 
						|
    newer_pairs = filter(splat(newer), zip_strict(sources, targets))
 | 
						|
    return tuple(map(list, zip(*newer_pairs))) or ([], [])
 | 
						|
 | 
						|
 | 
						|
def newer_group(
 | 
						|
    sources: Iterable[str | bytes | os.PathLike[str] | os.PathLike[bytes]],
 | 
						|
    target: str | bytes | os.PathLike[str] | os.PathLike[bytes],
 | 
						|
    missing: Literal["error", "ignore", "newer"] = "error",
 | 
						|
) -> bool:
 | 
						|
    """
 | 
						|
    Is target out-of-date with respect to any file in sources.
 | 
						|
 | 
						|
    Return True if 'target' is out-of-date with respect to any file
 | 
						|
    listed in 'sources'. In other words, if 'target' exists and is newer
 | 
						|
    than every file in 'sources', return False; otherwise return True.
 | 
						|
    ``missing`` controls how to handle a missing source file:
 | 
						|
 | 
						|
    - error (default): allow the ``stat()`` call to fail.
 | 
						|
    - ignore: silently disregard any missing source files.
 | 
						|
    - newer: treat missing source files as "target out of date". This
 | 
						|
      mode is handy in "dry-run" mode: it will pretend to carry out
 | 
						|
      commands that wouldn't work because inputs are missing, but
 | 
						|
      that doesn't matter because dry-run won't run the commands.
 | 
						|
    """
 | 
						|
 | 
						|
    def missing_as_newer(source):
 | 
						|
        return missing == 'newer' and not os.path.exists(source)
 | 
						|
 | 
						|
    ignored = os.path.exists if missing == 'ignore' else None
 | 
						|
    return not os.path.exists(target) or any(
 | 
						|
        missing_as_newer(source) or _newer(source, target)
 | 
						|
        for source in filter(ignored, sources)
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
newer_pairwise_group = functools.partial(newer_pairwise, newer=newer_group)
 |