This commit was manufactured by cvs2svn to create tag 'r22a4-fork'.
[python/dscho.git] / Lib / statcache.py
blob3123418ca4f62439c337bf742498b76d2b6c8b31
1 """Maintain a cache of stat() information on files.
3 There are functions to reset the cache or to selectively remove items.
4 """
6 import os as _os
7 from stat import *
9 __all__ = ["stat","reset","forget","forget_prefix","forget_dir",
10 "forget_except_prefix","isdir"]
12 # The cache. Keys are pathnames, values are os.stat outcomes.
13 # Remember that multiple threads may be calling this! So, e.g., that
14 # cache.has_key(path) returns 1 doesn't mean the cache will still contain
15 # path on the next line. Code defensively.
17 cache = {}
19 def stat(path):
20 """Stat a file, possibly out of the cache."""
21 ret = cache.get(path, None)
22 if ret is None:
23 cache[path] = ret = _os.stat(path)
24 return ret
26 def reset():
27 """Clear the cache."""
28 cache.clear()
30 # For thread saftey, always use forget() internally too.
31 def forget(path):
32 """Remove a given item from the cache, if it exists."""
33 try:
34 del cache[path]
35 except KeyError:
36 pass
38 def forget_prefix(prefix):
39 """Remove all pathnames with a given prefix."""
40 for path in cache.keys():
41 if path.startswith(prefix):
42 forget(path)
44 def forget_dir(prefix):
45 """Forget a directory and all entries except for entries in subdirs."""
47 # Remove trailing separator, if any. This is tricky to do in a
48 # x-platform way. For example, Windows accepts both / and \ as
49 # separators, and if there's nothing *but* a separator we want to
50 # preserve that this is the root. Only os.path has the platform
51 # knowledge we need.
52 from os.path import split, join
53 prefix = split(join(prefix, "xxx"))[0]
54 forget(prefix)
55 for path in cache.keys():
56 # First check that the path at least starts with the prefix, so
57 # that when it doesn't we can avoid paying for split().
58 if path.startswith(prefix) and split(path)[0] == prefix:
59 forget(path)
61 def forget_except_prefix(prefix):
62 """Remove all pathnames except with a given prefix.
64 Normally used with prefix = '/' after a chdir().
65 """
67 for path in cache.keys():
68 if not path.startswith(prefix):
69 forget(path)
71 def isdir(path):
72 """Return 1 if directory, else 0."""
73 try:
74 st = stat(path)
75 except _os.error:
76 return 0
77 return S_ISDIR(st[ST_MODE])