1.1 --- a/WebStack/Repositories/Directory.py Sun Nov 20 02:35:21 2005 +0000
1.2 +++ b/WebStack/Repositories/Directory.py Sun Nov 20 02:35:55 2005 +0000
1.3 @@ -86,7 +86,11 @@
1.4 return map(self._convert_fsname, l)
1.5
1.6 def full_path(self, key):
1.7 - return os.path.join(self.path, self._convert_name(key))
1.8 + path = os.path.abspath(os.path.join(self.path, self._convert_name(key)))
1.9 + if not path.startswith(self.path):
1.10 + raise ValueError, key
1.11 + else:
1.12 + return path
1.13
1.14 def has_key(self, key):
1.15 return key in self.keys()
1.16 @@ -105,7 +109,17 @@
1.17 results.append(self[key])
1.18 return results
1.19
1.20 - def _wait_for_file(self, key):
1.21 + def lock(self, key, create=0):
1.22 +
1.23 + """
1.24 + Lock the file associated with the given 'key'. If the optional 'create'
1.25 + parameter is set to a true value (unlike the default), the file will be
1.26 + created if it did not already exist; otherwise, a KeyError will be
1.27 + raised.
1.28 +
1.29 + Return the full path to the file.
1.30 + """
1.31 +
1.32 filename = self.full_path(key)
1.33 if os.path.exists(filename) or os.path.exists(filename + ".edit"):
1.34 while 1:
1.35 @@ -115,9 +129,25 @@
1.36 time.sleep(self.delay)
1.37 else:
1.38 break
1.39 - return filename, 1
1.40 + elif create:
1.41 + f = open(filename + ".edit", "wb")
1.42 + f.close()
1.43 else:
1.44 - return filename, 0
1.45 + raise KeyError, key
1.46 + return filename
1.47 +
1.48 + def unlock(self, key):
1.49 +
1.50 + """
1.51 + Unlock the file associated with the given 'key'.
1.52 +
1.53 + Important note: this method should be used in a finally clause in order
1.54 + to avoid files being locked and never being unlocked by the same process
1.55 + because an unhandled exception was raised.
1.56 + """
1.57 +
1.58 + filename = self.full_path(key)
1.59 + os.rename(filename + ".edit", filename)
1.60
1.61 def __delitem__(self, key):
1.62 filename = self.full_path(key)
1.63 @@ -133,9 +163,7 @@
1.64 raise KeyError, key
1.65
1.66 def __getitem__(self, key):
1.67 - filename, exists = self._wait_for_file(key)
1.68 - if not exists:
1.69 - raise KeyError, key
1.70 + filename = self.lock(key, create=0)
1.71 try:
1.72 f = open(filename + ".edit", "rb")
1.73 s = ""
1.74 @@ -144,12 +172,12 @@
1.75 finally:
1.76 f.close()
1.77 finally:
1.78 - os.rename(filename + ".edit", filename)
1.79 + self.unlock(key)
1.80
1.81 return s
1.82
1.83 def __setitem__(self, key, value):
1.84 - filename, exists = self._wait_for_file(key)
1.85 + filename = self.lock(key, create=1)
1.86 try:
1.87 f = open(filename + ".edit", "wb")
1.88 try:
1.89 @@ -157,6 +185,6 @@
1.90 finally:
1.91 f.close()
1.92 finally:
1.93 - os.rename(filename + ".edit", filename)
1.94 + self.unlock(key)
1.95
1.96 # vim: tabstop=4 expandtab shiftwidth=4