You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
2.3 KiB
77 lines
2.3 KiB
"""Maintain a cache of stat() information on files. |
|
|
|
There are functions to reset the cache or to selectively remove items. |
|
""" |
|
|
|
import os as _os |
|
from stat import * |
|
|
|
__all__ = ["stat","reset","forget","forget_prefix","forget_dir", |
|
"forget_except_prefix","isdir"] |
|
|
|
# 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. |
|
|
|
cache = {} |
|
|
|
def stat(path): |
|
"""Stat a file, possibly out of the cache.""" |
|
ret = cache.get(path, None) |
|
if ret is None: |
|
cache[path] = ret = _os.stat(path) |
|
return ret |
|
|
|
def reset(): |
|
"""Clear the cache.""" |
|
cache.clear() |
|
|
|
# For thread saftey, always use forget() internally too. |
|
def forget(path): |
|
"""Remove a given item from the cache, if it exists.""" |
|
try: |
|
del cache[path] |
|
except KeyError: |
|
pass |
|
|
|
def forget_prefix(prefix): |
|
"""Remove all pathnames with a given prefix.""" |
|
for path in cache.keys(): |
|
if path.startswith(prefix): |
|
forget(path) |
|
|
|
def forget_dir(prefix): |
|
"""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] |
|
forget(prefix) |
|
for path in cache.keys(): |
|
# 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) |
|
|
|
def forget_except_prefix(prefix): |
|
"""Remove all pathnames except with a given prefix. |
|
|
|
Normally used with prefix = '/' after a chdir(). |
|
""" |
|
|
|
for path in cache.keys(): |
|
if not path.startswith(prefix): |
|
forget(path) |
|
|
|
def isdir(path): |
|
"""Return 1 if directory, else 0.""" |
|
try: |
|
st = stat(path) |
|
except _os.error: |
|
return 0 |
|
return S_ISDIR(st[ST_MODE])
|
|
|