statcache.py 2.4 KB
Newer Older
1 2
"""Maintain a cache of stat() information on files.

3 4
There are functions to reset the cache or to selectively remove items.
"""
Guido van Rossum's avatar
Guido van Rossum committed
5

6 7 8 9 10
import warnings
warnings.warn("The statcache module is obsolete.  Use os.stat() instead.",
              DeprecationWarning)
del warnings

11
import os as _os
12
from stat import *
Guido van Rossum's avatar
Guido van Rossum committed
13

14 15 16
__all__ = ["stat","reset","forget","forget_prefix","forget_dir",
           "forget_except_prefix","isdir"]

17 18
# The cache.  Keys are pathnames, values are os.stat outcomes.
# Remember that multiple threads may be calling this!  So, e.g., that
19
# path in cache returns 1 doesn't mean the cache will still contain
20
# path on the next line.  Code defensively.
Guido van Rossum's avatar
Guido van Rossum committed
21

22
cache = {}
Guido van Rossum's avatar
Guido van Rossum committed
23 24

def stat(path):
Tim Peters's avatar
Tim Peters committed
25
    """Stat a file, possibly out of the cache."""
26 27 28
    ret = cache.get(path, None)
    if ret is None:
        cache[path] = ret = _os.stat(path)
Tim Peters's avatar
Tim Peters committed
29
    return ret
Guido van Rossum's avatar
Guido van Rossum committed
30 31

def reset():
32 33
    """Clear the cache."""
    cache.clear()
Guido van Rossum's avatar
Guido van Rossum committed
34

35
# For thread saftey, always use forget() internally too.
Guido van Rossum's avatar
Guido van Rossum committed
36
def forget(path):
Tim Peters's avatar
Tim Peters committed
37
    """Remove a given item from the cache, if it exists."""
38
    try:
Tim Peters's avatar
Tim Peters committed
39
        del cache[path]
40 41
    except KeyError:
        pass
Guido van Rossum's avatar
Guido van Rossum committed
42 43

def forget_prefix(prefix):
Tim Peters's avatar
Tim Peters committed
44 45
    """Remove all pathnames with a given prefix."""
    for path in cache.keys():
46 47
        if path.startswith(prefix):
            forget(path)
Guido van Rossum's avatar
Guido van Rossum committed
48 49

def forget_dir(prefix):
50 51 52 53 54 55 56 57 58
    """Forget a directory and all entries except for entries in subdirs."""

    # Remove trailing separator, if any.  This is tricky to do in a
    # x-platform way.  For example, Windows accepts both / and \ as
    # separators, and if there's nothing *but* a separator we want to
    # preserve that this is the root.  Only os.path has the platform
    # knowledge we need.
    from os.path import split, join
    prefix = split(join(prefix, "xxx"))[0]
Tim Peters's avatar
Tim Peters committed
59 60
    forget(prefix)
    for path in cache.keys():
61 62 63 64
        # First check that the path at least starts with the prefix, so
        # that when it doesn't we can avoid paying for split().
        if path.startswith(prefix) and split(path)[0] == prefix:
            forget(path)
Guido van Rossum's avatar
Guido van Rossum committed
65 66

def forget_except_prefix(prefix):
Tim Peters's avatar
Tim Peters committed
67
    """Remove all pathnames except with a given prefix.
Guido van Rossum's avatar
Guido van Rossum committed
68

69 70 71 72 73 74
    Normally used with prefix = '/' after a chdir().
    """

    for path in cache.keys():
        if not path.startswith(prefix):
            forget(path)
Guido van Rossum's avatar
Guido van Rossum committed
75 76

def isdir(path):
77
    """Return True if directory, else False."""
Tim Peters's avatar
Tim Peters committed
78 79
    try:
        st = stat(path)
80
    except _os.error:
81
        return False
82
    return S_ISDIR(st.st_mode)