blob: d4783938049c6e5369075ef1f2ca67a2efe07797 [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
Neal Norwitzab3b9eb2002-04-10 02:04:00 +00006import warnings
7warnings.warn("The statcache module is obsolete. Use os.stat() instead.",
8 DeprecationWarning)
9del warnings
10
Tim Peters0149e842001-01-28 05:07:00 +000011import os as _os
Guido van Rossum40d93041990-10-21 16:17:34 +000012from stat import *
Guido van Rossumc6360141990-10-13 19:23:40 +000013
Skip Montanaro0de65802001-02-15 22:15:14 +000014__all__ = ["stat","reset","forget","forget_prefix","forget_dir",
15 "forget_except_prefix","isdir"]
16
Tim Peters0149e842001-01-28 05:07:00 +000017# The cache. Keys are pathnames, values are os.stat outcomes.
18# Remember that multiple threads may be calling this! So, e.g., that
Raymond Hettinger54f02222002-06-01 14:18:47 +000019# path in cache returns 1 doesn't mean the cache will still contain
Tim Peters0149e842001-01-28 05:07:00 +000020# path on the next line. Code defensively.
Guido van Rossumc6360141990-10-13 19:23:40 +000021
Tim Peters0149e842001-01-28 05:07:00 +000022cache = {}
Guido van Rossumc6360141990-10-13 19:23:40 +000023
Guido van Rossumc6360141990-10-13 19:23:40 +000024def stat(path):
Tim Peters495ad3c2001-01-15 01:36:40 +000025 """Stat a file, possibly out of the cache."""
Tim Peters0149e842001-01-28 05:07:00 +000026 ret = cache.get(path, None)
27 if ret is None:
28 cache[path] = ret = _os.stat(path)
Tim Peters495ad3c2001-01-15 01:36:40 +000029 return ret
Guido van Rossumc6360141990-10-13 19:23:40 +000030
Guido van Rossumc6360141990-10-13 19:23:40 +000031def reset():
Tim Peters0149e842001-01-28 05:07:00 +000032 """Clear the cache."""
33 cache.clear()
Guido van Rossumc6360141990-10-13 19:23:40 +000034
Tim Peters0149e842001-01-28 05:07:00 +000035# For thread saftey, always use forget() internally too.
Guido van Rossumc6360141990-10-13 19:23:40 +000036def forget(path):
Tim Peters495ad3c2001-01-15 01:36:40 +000037 """Remove a given item from the cache, if it exists."""
Tim Peters0149e842001-01-28 05:07:00 +000038 try:
Tim Peters495ad3c2001-01-15 01:36:40 +000039 del cache[path]
Tim Peters0149e842001-01-28 05:07:00 +000040 except KeyError:
41 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000042
Guido van Rossumc6360141990-10-13 19:23:40 +000043def forget_prefix(prefix):
Tim Peters495ad3c2001-01-15 01:36:40 +000044 """Remove all pathnames with a given prefix."""
Tim Peters495ad3c2001-01-15 01:36:40 +000045 for path in cache.keys():
Tim Peters0149e842001-01-28 05:07:00 +000046 if path.startswith(prefix):
47 forget(path)
Guido van Rossumc6360141990-10-13 19:23:40 +000048
Guido van Rossumc6360141990-10-13 19:23:40 +000049def forget_dir(prefix):
Tim Peters0149e842001-01-28 05:07:00 +000050 """Forget a directory and all entries except for entries in subdirs."""
Guido van Rossumc6360141990-10-13 19:23:40 +000051
Tim Peters0149e842001-01-28 05:07:00 +000052 # Remove trailing separator, if any. This is tricky to do in a
53 # x-platform way. For example, Windows accepts both / and \ as
54 # separators, and if there's nothing *but* a separator we want to
55 # preserve that this is the root. Only os.path has the platform
56 # knowledge we need.
57 from os.path import split, join
58 prefix = split(join(prefix, "xxx"))[0]
59 forget(prefix)
60 for path in cache.keys():
61 # First check that the path at least starts with the prefix, so
62 # that when it doesn't we can avoid paying for split().
63 if path.startswith(prefix) and split(path)[0] == prefix:
64 forget(path)
Guido van Rossumc6360141990-10-13 19:23:40 +000065
Guido van Rossumc6360141990-10-13 19:23:40 +000066def forget_except_prefix(prefix):
Tim Peters495ad3c2001-01-15 01:36:40 +000067 """Remove all pathnames except with a given prefix.
Guido van Rossumc6360141990-10-13 19:23:40 +000068
Tim Peters0149e842001-01-28 05:07:00 +000069 Normally used with prefix = '/' after a chdir().
70 """
71
72 for path in cache.keys():
73 if not path.startswith(prefix):
74 forget(path)
Guido van Rossumc6360141990-10-13 19:23:40 +000075
Guido van Rossumc6360141990-10-13 19:23:40 +000076def isdir(path):
Neal Norwitz803a8ea2002-04-09 18:12:58 +000077 """Return True if directory, else False."""
Tim Peters495ad3c2001-01-15 01:36:40 +000078 try:
79 st = stat(path)
Tim Peters0149e842001-01-28 05:07:00 +000080 except _os.error:
Guido van Rossum8ca162f2002-04-07 06:36:23 +000081 return False
Raymond Hettinger32200ae2002-06-01 19:51:15 +000082 return S_ISDIR(st.st_mode)