2000-02-04 11:39:30 -04:00
|
|
|
"""Maintain a cache of stat() information on files.
|
|
|
|
|
2000-02-04 11:28:42 -04:00
|
|
|
There are functions to reset the cache or to selectively remove items.
|
|
|
|
"""
|
1990-10-13 16:23:40 -03:00
|
|
|
|
2002-04-09 23:04:00 -03:00
|
|
|
import warnings
|
|
|
|
warnings.warn("The statcache module is obsolete. Use os.stat() instead.",
|
|
|
|
DeprecationWarning)
|
|
|
|
del warnings
|
|
|
|
|
2001-01-28 01:07:00 -04:00
|
|
|
import os as _os
|
1990-10-21 13:17:34 -03:00
|
|
|
from stat import *
|
1990-10-13 16:23:40 -03:00
|
|
|
|
2001-02-15 18:15:14 -04:00
|
|
|
__all__ = ["stat","reset","forget","forget_prefix","forget_dir",
|
|
|
|
"forget_except_prefix","isdir"]
|
|
|
|
|
2001-01-28 01:07:00 -04:00
|
|
|
# The cache. Keys are pathnames, values are os.stat outcomes.
|
|
|
|
# Remember that multiple threads may be calling this! So, e.g., that
|
|
|
|
# cache.has_key(path) returns 1 doesn't mean the cache will still contain
|
|
|
|
# path on the next line. Code defensively.
|
1990-10-13 16:23:40 -03:00
|
|
|
|
2001-01-28 01:07:00 -04:00
|
|
|
cache = {}
|
1990-10-13 16:23:40 -03:00
|
|
|
|
|
|
|
def stat(path):
|
2001-01-14 21:36:40 -04:00
|
|
|
"""Stat a file, possibly out of the cache."""
|
2001-01-28 01:07:00 -04:00
|
|
|
ret = cache.get(path, None)
|
|
|
|
if ret is None:
|
|
|
|
cache[path] = ret = _os.stat(path)
|
2001-01-14 21:36:40 -04:00
|
|
|
return ret
|
1990-10-13 16:23:40 -03:00
|
|
|
|
|
|
|
def reset():
|
2001-01-28 01:07:00 -04:00
|
|
|
"""Clear the cache."""
|
|
|
|
cache.clear()
|
1990-10-13 16:23:40 -03:00
|
|
|
|
2001-01-28 01:07:00 -04:00
|
|
|
# For thread saftey, always use forget() internally too.
|
1990-10-13 16:23:40 -03:00
|
|
|
def forget(path):
|
2001-01-14 21:36:40 -04:00
|
|
|
"""Remove a given item from the cache, if it exists."""
|
2001-01-28 01:07:00 -04:00
|
|
|
try:
|
2001-01-14 21:36:40 -04:00
|
|
|
del cache[path]
|
2001-01-28 01:07:00 -04:00
|
|
|
except KeyError:
|
|
|
|
pass
|
1990-10-13 16:23:40 -03:00
|
|
|
|
|
|
|
def forget_prefix(prefix):
|
2001-01-14 21:36:40 -04:00
|
|
|
"""Remove all pathnames with a given prefix."""
|
|
|
|
for path in cache.keys():
|
2001-01-28 01:07:00 -04:00
|
|
|
if path.startswith(prefix):
|
|
|
|
forget(path)
|
1990-10-13 16:23:40 -03:00
|
|
|
|
|
|
|
def forget_dir(prefix):
|
2001-01-28 01:07:00 -04:00
|
|
|
"""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]
|
2001-01-14 21:36:40 -04:00
|
|
|
forget(prefix)
|
|
|
|
for path in cache.keys():
|
2001-01-28 01:07:00 -04:00
|
|
|
# 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)
|
1990-10-13 16:23:40 -03:00
|
|
|
|
|
|
|
def forget_except_prefix(prefix):
|
2001-01-14 21:36:40 -04:00
|
|
|
"""Remove all pathnames except with a given prefix.
|
1990-10-13 16:23:40 -03:00
|
|
|
|
2001-01-28 01:07:00 -04:00
|
|
|
Normally used with prefix = '/' after a chdir().
|
|
|
|
"""
|
|
|
|
|
|
|
|
for path in cache.keys():
|
|
|
|
if not path.startswith(prefix):
|
|
|
|
forget(path)
|
1990-10-13 16:23:40 -03:00
|
|
|
|
|
|
|
def isdir(path):
|
2002-04-09 15:12:58 -03:00
|
|
|
"""Return True if directory, else False."""
|
2001-01-14 21:36:40 -04:00
|
|
|
try:
|
|
|
|
st = stat(path)
|
2001-01-28 01:07:00 -04:00
|
|
|
except _os.error:
|
2002-04-07 03:36:23 -03:00
|
|
|
return False
|
2001-01-14 21:36:40 -04:00
|
|
|
return S_ISDIR(st[ST_MODE])
|