blob: 056ec4039dcaa5c59ba04da02f5ca070441a5beb [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
Tim Peters0149e842001-01-28 05:07:00 +00009# The cache. Keys are pathnames, values are os.stat outcomes.
10# Remember that multiple threads may be calling this! So, e.g., that
11# cache.has_key(path) returns 1 doesn't mean the cache will still contain
12# path on the next line. Code defensively.
Guido van Rossumc6360141990-10-13 19:23:40 +000013
Tim Peters0149e842001-01-28 05:07:00 +000014cache = {}
Guido van Rossumc6360141990-10-13 19:23:40 +000015
Guido van Rossumc6360141990-10-13 19:23:40 +000016def stat(path):
Tim Peters495ad3c2001-01-15 01:36:40 +000017 """Stat a file, possibly out of the cache."""
Tim Peters0149e842001-01-28 05:07:00 +000018 ret = cache.get(path, None)
19 if ret is None:
20 cache[path] = ret = _os.stat(path)
Tim Peters495ad3c2001-01-15 01:36:40 +000021 return ret
Guido van Rossumc6360141990-10-13 19:23:40 +000022
Guido van Rossumc6360141990-10-13 19:23:40 +000023def reset():
Tim Peters0149e842001-01-28 05:07:00 +000024 """Clear the cache."""
25 cache.clear()
Guido van Rossumc6360141990-10-13 19:23:40 +000026
Tim Peters0149e842001-01-28 05:07:00 +000027# For thread saftey, always use forget() internally too.
Guido van Rossumc6360141990-10-13 19:23:40 +000028def forget(path):
Tim Peters495ad3c2001-01-15 01:36:40 +000029 """Remove a given item from the cache, if it exists."""
Tim Peters0149e842001-01-28 05:07:00 +000030 try:
Tim Peters495ad3c2001-01-15 01:36:40 +000031 del cache[path]
Tim Peters0149e842001-01-28 05:07:00 +000032 except KeyError:
33 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000034
Guido van Rossumc6360141990-10-13 19:23:40 +000035def forget_prefix(prefix):
Tim Peters495ad3c2001-01-15 01:36:40 +000036 """Remove all pathnames with a given prefix."""
Tim Peters495ad3c2001-01-15 01:36:40 +000037 for path in cache.keys():
Tim Peters0149e842001-01-28 05:07:00 +000038 if path.startswith(prefix):
39 forget(path)
Guido van Rossumc6360141990-10-13 19:23:40 +000040
Guido van Rossumc6360141990-10-13 19:23:40 +000041def forget_dir(prefix):
Tim Peters0149e842001-01-28 05:07:00 +000042 """Forget a directory and all entries except for entries in subdirs."""
Guido van Rossumc6360141990-10-13 19:23:40 +000043
Tim Peters0149e842001-01-28 05:07:00 +000044 # Remove trailing separator, if any. This is tricky to do in a
45 # x-platform way. For example, Windows accepts both / and \ as
46 # separators, and if there's nothing *but* a separator we want to
47 # preserve that this is the root. Only os.path has the platform
48 # knowledge we need.
49 from os.path import split, join
50 prefix = split(join(prefix, "xxx"))[0]
51 forget(prefix)
52 for path in cache.keys():
53 # First check that the path at least starts with the prefix, so
54 # that when it doesn't we can avoid paying for split().
55 if path.startswith(prefix) and split(path)[0] == prefix:
56 forget(path)
Guido van Rossumc6360141990-10-13 19:23:40 +000057
Guido van Rossumc6360141990-10-13 19:23:40 +000058def forget_except_prefix(prefix):
Tim Peters495ad3c2001-01-15 01:36:40 +000059 """Remove all pathnames except with a given prefix.
Guido van Rossumc6360141990-10-13 19:23:40 +000060
Tim Peters0149e842001-01-28 05:07:00 +000061 Normally used with prefix = '/' after a chdir().
62 """
63
64 for path in cache.keys():
65 if not path.startswith(prefix):
66 forget(path)
Guido van Rossumc6360141990-10-13 19:23:40 +000067
Guido van Rossumc6360141990-10-13 19:23:40 +000068def isdir(path):
Tim Peters0149e842001-01-28 05:07:00 +000069 """Return 1 if directory, else 0."""
Tim Peters495ad3c2001-01-15 01:36:40 +000070 try:
71 st = stat(path)
Tim Peters0149e842001-01-28 05:07:00 +000072 except _os.error:
Tim Peters495ad3c2001-01-15 01:36:40 +000073 return 0
74 return S_ISDIR(st[ST_MODE])