dblite.py
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:6k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. # dblite.py module contributed by Ralf W. Grosse-Kunstleve.
  2. # Extended for Unicode by Steven Knight.
  3. import cPickle
  4. import time
  5. import shutil
  6. import os
  7. import types
  8. import __builtin__
  9. keep_all_files = 00000
  10. ignore_corrupt_dbfiles = 0
  11. def corruption_warning(filename):
  12.     print "Warning: Discarding corrupt database:", filename
  13. if hasattr(types, 'UnicodeType'):
  14.     def is_string(s):
  15.         t = type(s)
  16.         return t is types.StringType or t is types.UnicodeType
  17. else:
  18.     def is_string(s):
  19.         return type(s) is types.StringType
  20. try:
  21.     unicode('a')
  22. except NameError:
  23.     def unicode(s): return s
  24. dblite_suffix = '.dblite'
  25. tmp_suffix = '.tmp'
  26. class dblite:
  27.   # Squirrel away references to the functions in various modules
  28.   # that we'll use when our __del__() method calls our sync() method
  29.   # during shutdown.  We might get destroyed when Python is in the midst
  30.   # of tearing down the different modules we import in an essentially
  31.   # arbitrary order, and some of the various modules's global attributes
  32.   # may already be wiped out from under us.
  33.   #
  34.   # See the discussion at:
  35.   #   http://mail.python.org/pipermail/python-bugs-list/2003-March/016877.html
  36.   _open = __builtin__.open
  37.   _cPickle_dump = cPickle.dump
  38.   _os_chmod = os.chmod
  39.   _os_rename = os.rename
  40.   _os_unlink = os.unlink
  41.   _shutil_copyfile = shutil.copyfile
  42.   _time_time = time.time
  43.   def __init__(self, file_base_name, flag, mode):
  44.     assert flag in (None, "r", "w", "c", "n")
  45.     if (flag is None): flag = "r"
  46.     base, ext = os.path.splitext(file_base_name)
  47.     if ext == dblite_suffix:
  48.       # There's already a suffix on the file name, don't add one.
  49.       self._file_name = file_base_name
  50.       self._tmp_name = base + tmp_suffix
  51.     else:
  52.       self._file_name = file_base_name + dblite_suffix
  53.       self._tmp_name = file_base_name + tmp_suffix
  54.     self._flag = flag
  55.     self._mode = mode
  56.     self._dict = {}
  57.     self._needs_sync = 00000
  58.     if (self._flag == "n"):
  59.       self._open(self._file_name, "wb", self._mode)
  60.     else:
  61.       try:
  62.         f = self._open(self._file_name, "rb")
  63.       except IOError, e:
  64.         if (self._flag != "c"):
  65.           raise e
  66.         self._open(self._file_name, "wb", self._mode)
  67.       else:
  68.         p = f.read()
  69.         if (len(p) > 0):
  70.           try:
  71.             self._dict = cPickle.loads(p)
  72.           except (cPickle.UnpicklingError, EOFError):
  73.             if (ignore_corrupt_dbfiles == 0): raise
  74.             if (ignore_corrupt_dbfiles == 1):
  75.               corruption_warning(self._file_name)
  76.   def __del__(self):
  77.     if (self._needs_sync):
  78.       self.sync()
  79.   def sync(self):
  80.     self._check_writable()
  81.     f = self._open(self._tmp_name, "wb", self._mode)
  82.     self._cPickle_dump(self._dict, f, 1)
  83.     f.close()
  84.     # Windows doesn't allow renaming if the file exists, so unlink
  85.     # it first, chmod'ing it to make sure we can do so.  On UNIX, we
  86.     # may not be able to chmod the file if it's owned by someone else
  87.     # (e.g. from a previous run as root).  We should still be able to
  88.     # unlink() the file if the directory's writable, though, so ignore
  89.     # any OSError exception  thrown by the chmod() call.
  90.     try: self._os_chmod(self._file_name, 0777)
  91.     except OSError: pass
  92.     self._os_unlink(self._file_name)
  93.     self._os_rename(self._tmp_name, self._file_name)
  94.     self._needs_sync = 00000
  95.     if (keep_all_files):
  96.       self._shutil_copyfile(
  97.         self._file_name,
  98.         self._file_name + "_" + str(int(self._time_time())))
  99.   def _check_writable(self):
  100.     if (self._flag == "r"):
  101.       raise IOError("Read-only database: %s" % self._file_name)
  102.   def __getitem__(self, key):
  103.     return self._dict[key]
  104.   def __setitem__(self, key, value):
  105.     self._check_writable()
  106.     if (not is_string(key)):
  107.       raise TypeError, "key `%s' must be a string but is %s" % (key, type(key))
  108.     if (not is_string(value)):
  109.       raise TypeError, "value `%s' must be a string but is %s" % (value, type(value))
  110.     self._dict[key] = value
  111.     self._needs_sync = 0001
  112.   def keys(self):
  113.     return self._dict.keys()
  114.   def has_key(self, key):
  115.     return key in self._dict
  116.   def __contains__(self, key):
  117.     return key in self._dict
  118.   def iterkeys(self):
  119.     return self._dict.iterkeys()
  120.   __iter__ = iterkeys
  121.   def __len__(self):
  122.     return len(self._dict)
  123. def open(file, flag=None, mode=0666):
  124.   return dblite(file, flag, mode)
  125. def _exercise():
  126.   db = open("tmp", "n")
  127.   assert len(db) == 0
  128.   db["foo"] = "bar"
  129.   assert db["foo"] == "bar"
  130.   db[unicode("ufoo")] = unicode("ubar")
  131.   assert db[unicode("ufoo")] == unicode("ubar")
  132.   db.sync()
  133.   db = open("tmp", "c")
  134.   assert len(db) == 2, len(db)
  135.   assert db["foo"] == "bar"
  136.   db["bar"] = "foo"
  137.   assert db["bar"] == "foo"
  138.   db[unicode("ubar")] = unicode("ufoo")
  139.   assert db[unicode("ubar")] == unicode("ufoo")
  140.   db.sync()
  141.   db = open("tmp", "r")
  142.   assert len(db) == 4, len(db)
  143.   assert db["foo"] == "bar"
  144.   assert db["bar"] == "foo"
  145.   assert db[unicode("ufoo")] == unicode("ubar")
  146.   assert db[unicode("ubar")] == unicode("ufoo")
  147.   try:
  148.     db.sync()
  149.   except IOError, e:
  150.     assert str(e) == "Read-only database: tmp.dblite"
  151.   else:
  152.     raise RuntimeError, "IOError expected."
  153.   db = open("tmp", "w")
  154.   assert len(db) == 4
  155.   db["ping"] = "pong"
  156.   db.sync()
  157.   try:
  158.     db[(1,2)] = "tuple"
  159.   except TypeError, e:
  160.     assert str(e) == "key `(1, 2)' must be a string but is <type 'tuple'>", str(e)
  161.   else:
  162.     raise RuntimeError, "TypeError exception expected"
  163.   try:
  164.     db["list"] = [1,2]
  165.   except TypeError, e:
  166.     assert str(e) == "value `[1, 2]' must be a string but is <type 'list'>", str(e)
  167.   else:
  168.     raise RuntimeError, "TypeError exception expected"
  169.   db = open("tmp", "r")
  170.   assert len(db) == 5
  171.   db = open("tmp", "n")
  172.   assert len(db) == 0
  173.   _open("tmp.dblite", "w")
  174.   db = open("tmp", "r")
  175.   _open("tmp.dblite", "w").write("x")
  176.   try:
  177.     db = open("tmp", "r")
  178.   except cPickle.UnpicklingError:
  179.     pass
  180.   else:
  181.     raise RuntimeError, "cPickle exception expected."
  182.   global ignore_corrupt_dbfiles
  183.   ignore_corrupt_dbfiles = 2
  184.   db = open("tmp", "r")
  185.   assert len(db) == 0
  186.   os.unlink("tmp.dblite")
  187.   try:
  188.     db = open("tmp", "w")
  189.   except IOError, e:
  190.     assert str(e) == "[Errno 2] No such file or directory: 'tmp.dblite'", str(e)
  191.   else:
  192.     raise RuntimeError, "IOError expected."
  193.   print "OK"
  194. if (__name__ == "__main__"):
  195.   _exercise()