blob: 3123418ca4f62439c337bf742498b76d2b6c8b31 [file] [log] [blame]
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +00001"""Maintain a cache of stat() information on files.
2
Guido van Rossume7b146f2000-02-04 15:28:42 +00003There are functions to reset the cache or to selectively remove items.
4"""
Guido van Rossumc6360141990-10-13 19:23:40 +00005
Tim Peters0149e842001-01-28 05:07:00 +00006import os as _os
Guido van Rossum40d93041990-10-21 16:17:34 +00007from stat import *
Guido van Rossumc6360141990-10-13 19:23:40 +00008
Skip Montanaro0de65802001-02-15 22:15:14 +00009__all__ = ["stat","reset","forget","forget_prefix","forget_dir",
10 "forget_except_prefix","isdir"]
11
Tim Peters0149e842001-01-28 05:07:00 +000012# 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.
Guido van Rossumc6360141990-10-13 19:23:40 +000016
Tim Peters0149e842001-01-28 05:07:00 +000017cache = {}
Guido van Rossumc6360141990-10-13 19:23:40 +000018
Guido van Rossumc6360141990-10-13 19:23:40 +000019def stat(path):
Tim Peters495ad3c2001-01-15 01:36:40 +000020 """Stat a file, possibly out of the cache."""
Tim Peters0149e842001-01-28 05:07:00 +000021 ret = cache.get(path, None)
22 if ret is None:
23 cache[path] = ret = _os.stat(path)
Tim Peters495ad3c2001-01-15 01:36:40 +000024 return ret
Guido van Rossumc6360141990-10-13 19:23:40 +000025
Guido van Rossumc6360141990-10-13 19:23:40 +000026def reset():
Tim Peters0149e842001-01-28 05:07:00 +000027 """Clear the cache."""
28 cache.clear()
Guido van Rossumc6360141990-10-13 19:23:40 +000029
Tim Peters0149e842001-01-28 05:07:00 +000030# For thread saftey, always use forget() internally too.
Guido van Rossumc6360141990-10-13 19:23:40 +000031def forget(path):
Tim Peters495ad3c2001-01-15 01:36:40 +000032 """Remove a given item from the cache, if it exists."""
Tim Peters0149e842001-01-28 05:07:00 +000033 try:
Tim Peters495ad3c2001-01-15 01:36:40 +000034 del cache[path]
Tim Peters0149e842001-01-28 05:07:00 +000035 except KeyError:
36 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000037
Guido van Rossumc6360141990-10-13 19:23:40 +000038def forget_prefix(prefix):
Tim Peters495ad3c2001-01-15 01:36:40 +000039 """Remove all pathnames with a given prefix."""
Tim Peters495ad3c2001-01-15 01:36:40 +000040 for path in cache.keys():
Tim Peters0149e842001-01-28 05:07:00 +000041 if path.startswith(prefix):
42 forget(path)
Guido van Rossumc6360141990-10-13 19:23:40 +000043
Guido van Rossumc6360141990-10-13 19:23:40 +000044def forget_dir(prefix):
Tim Peters0149e842001-01-28 05:07:00 +000045 """Forget a directory and all entries except for entries in subdirs."""
Guido van Rossumc6360141990-10-13 19:23:40 +000046
Tim Peters0149e842001-01-28 05:07:00 +000047 # 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)
Guido van Rossumc6360141990-10-13 19:23:40 +000060
Guido van Rossumc6360141990-10-13 19:23:40 +000061def forget_except_prefix(prefix):
Tim Peters495ad3c2001-01-15 01:36:40 +000062 """Remove all pathnames except with a given prefix.
Guido van Rossumc6360141990-10-13 19:23:40 +000063
Tim Peters0149e842001-01-28 05:07:00 +000064 Normally used with prefix = '/' after a chdir().
65 """
66
67 for path in cache.keys():
68 if not path.startswith(prefix):
69 forget(path)
Guido van Rossumc6360141990-10-13 19:23:40 +000070
Guido van Rossumc6360141990-10-13 19:23:40 +000071def isdir(path):
Tim Peters0149e842001-01-28 05:07:00 +000072 """Return 1 if directory, else 0."""
Tim Peters495ad3c2001-01-15 01:36:40 +000073 try:
74 st = stat(path)
Tim Peters0149e842001-01-28 05:07:00 +000075 except _os.error:
Tim Peters495ad3c2001-01-15 01:36:40 +000076 return 0
77 return S_ISDIR(st[ST_MODE])