dep_util.py 3.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
"""distutils.dep_util

Utility functions for simple, timestamp-based dependency of files
and groups of files; also, function based entirely on such
timestamp dependency analysis."""

__revision__ = "$Id$"

import os
from distutils.errors import DistutilsFileError

12 13
def newer(source, target):
    """Tells if the target is newer than the source.
14

15 16 17 18 19 20 21 22
    Return true if 'source' exists and is more recently modified than
    'target', or if 'source' exists and 'target' doesn't.

    Return false if both exist and 'target' is the same age or younger
    than 'source'. Raise DistutilsFileError if 'source' does not exist.

    Note that this test is not very accurate: files created in the same second
    will have the same "age".
Greg Ward's avatar
Greg Ward committed
23 24
    """
    if not os.path.exists(source):
25 26
        raise DistutilsFileError("file '%s' does not exist" %
                                 os.path.abspath(source))
Greg Ward's avatar
Greg Ward committed
27
    if not os.path.exists(target):
28
        return True
29

30
    return os.stat(source).st_mtime > os.stat(target).st_mtime
31

32
def newer_pairwise(sources, targets):
33
    """Walk two filename lists in parallel, testing if each source is newer
Greg Ward's avatar
Greg Ward committed
34 35 36 37 38
    than its corresponding target.  Return a pair of lists (sources,
    targets) where source is newer than target, according to the semantics
    of 'newer()'.
    """
    if len(sources) != len(targets):
39
        raise ValueError("'sources' and 'targets' must be same length")
40 41 42 43

    # build a pair of lists (sources, targets) where  source is newer
    n_sources = []
    n_targets = []
44 45 46 47
    for source, target in zip(sources, targets):
        if newer(source, target):
            n_sources.append(source)
            n_targets.append(target)
48

49
    return n_sources, n_targets
50

51
def newer_group(sources, target, missing='error'):
Greg Ward's avatar
Greg Ward committed
52
    """Return true if 'target' is out-of-date with respect to any file
53 54 55
    listed in 'sources'.

    In other words, if 'target' exists and is newer
Greg Ward's avatar
Greg Ward committed
56 57 58 59 60 61 62 63 64 65
    than every file in 'sources', return false; otherwise return true.
    'missing' controls what we do when a source file is missing; the
    default ("error") is to blow up with an OSError from inside 'stat()';
    if it is "ignore", we silently drop any missing source files; if it is
    "newer", any missing source files make us assume that 'target' is
    out-of-date (this is handy in "dry-run" mode: it'll make you pretend to
    carry out commands that wouldn't work because inputs are missing, but
    that doesn't matter because you're not actually going to run the
    commands).
    """
66
    # If the target doesn't even exist, then it's definitely out-of-date.
Greg Ward's avatar
Greg Ward committed
67
    if not os.path.exists(target):
68
        return True
Fred Drake's avatar
Fred Drake committed
69

70 71 72 73
    # Otherwise we have to find out the hard way: if *any* source file
    # is more recent than 'target', then 'target' is out-of-date and
    # we can immediately return true.  If we fall through to the end
    # of the loop, then 'target' is up-to-date and we return false.
74 75
    target_mtime = os.stat(target).st_mtime

76
    for source in sources:
Greg Ward's avatar
Greg Ward committed
77
        if not os.path.exists(source):
78
            if missing == 'error':      # blow up when we stat() the file
Fred Drake's avatar
Fred Drake committed
79 80
                pass
            elif missing == 'ignore':   # missing source dropped from
81 82
                continue                #  target's dependency list
            elif missing == 'newer':    # missing source means target is
83
                return True             #  out-of-date
Fred Drake's avatar
Fred Drake committed
84

85 86
        if os.stat(source).st_mtime > target_mtime:
            return True
87

88
    return False