PageRenderTime 61ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/lib_pypy/dbm.py

https://bitbucket.org/nbtaylor/pypy
Python | 180 lines | 171 code | 9 blank | 0 comment | 9 complexity | 0e17cb14124ab8ecc5565617a8879198 MD5 | raw file
  1. from ctypes import Structure, c_char_p, c_int, c_void_p, CDLL
  2. import ctypes.util
  3. import os, sys
  4. class error(Exception):
  5. def __init__(self, msg):
  6. self.msg = msg
  7. def __str__(self):
  8. return self.msg
  9. class datum(Structure):
  10. _fields_ = [
  11. ('dptr', c_char_p),
  12. ('dsize', c_int),
  13. ]
  14. def __init__(self, text):
  15. if not isinstance(text, str):
  16. raise TypeError("datum: expected string, not %s" % type(text))
  17. Structure.__init__(self, text, len(text))
  18. class dbm(object):
  19. def __init__(self, dbmobj):
  20. self._aobj = dbmobj
  21. def close(self):
  22. if not self._aobj:
  23. raise error('DBM object has already been closed')
  24. getattr(lib, funcs['close'])(self._aobj)
  25. self._aobj = None
  26. def __del__(self):
  27. if self._aobj:
  28. self.close()
  29. def keys(self):
  30. if not self._aobj:
  31. raise error('DBM object has already been closed')
  32. allkeys = []
  33. k = getattr(lib, funcs['firstkey'])(self._aobj)
  34. while k.dptr:
  35. allkeys.append(k.dptr[:k.dsize])
  36. k = getattr(lib, funcs['nextkey'])(self._aobj)
  37. return allkeys
  38. def get(self, key, default=None):
  39. if not self._aobj:
  40. raise error('DBM object has already been closed')
  41. dat = datum(key)
  42. k = getattr(lib, funcs['fetch'])(self._aobj, dat)
  43. if k.dptr:
  44. return k.dptr[:k.dsize]
  45. if getattr(lib, funcs['error'])(self._aobj):
  46. getattr(lib, funcs['clearerr'])(self._aobj)
  47. raise error("")
  48. return default
  49. def __len__(self):
  50. return len(self.keys())
  51. def __getitem__(self, key):
  52. value = self.get(key)
  53. if value is None:
  54. raise KeyError(key)
  55. return value
  56. def __setitem__(self, key, value):
  57. if not self._aobj:
  58. raise error('DBM object has already been closed')
  59. dat = datum(key)
  60. data = datum(value)
  61. status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_REPLACE)
  62. if getattr(lib, funcs['error'])(self._aobj):
  63. getattr(lib, funcs['clearerr'])(self._aobj)
  64. raise error("")
  65. return status
  66. def setdefault(self, key, default=''):
  67. if not self._aobj:
  68. raise error('DBM object has already been closed')
  69. dat = datum(key)
  70. k = getattr(lib, funcs['fetch'])(self._aobj, dat)
  71. if k.dptr:
  72. return k.dptr[:k.dsize]
  73. data = datum(default)
  74. status = getattr(lib, funcs['store'])(self._aobj, dat, data, lib.DBM_INSERT)
  75. if status < 0:
  76. getattr(lib, funcs['clearerr'])(self._aobj)
  77. raise error("cannot add item to database")
  78. return default
  79. def __contains__(self, key):
  80. if not self._aobj:
  81. raise error('DBM object has already been closed')
  82. dat = datum(key)
  83. k = getattr(lib, funcs['fetch'])(self._aobj, dat)
  84. if k.dptr:
  85. return True
  86. return False
  87. has_key = __contains__
  88. def __delitem__(self, key):
  89. if not self._aobj:
  90. raise error('DBM object has already been closed')
  91. dat = datum(key)
  92. status = getattr(lib, funcs['delete'])(self._aobj, dat)
  93. if status < 0:
  94. raise KeyError(key)
  95. ### initialization: Berkeley DB versus normal DB
  96. def _init_func(name, argtypes=None, restype=None):
  97. try:
  98. func = getattr(lib, '__db_ndbm_' + name)
  99. funcs[name] = '__db_ndbm_' + name
  100. except AttributeError:
  101. func = getattr(lib, 'dbm_' + name)
  102. funcs[name] = 'dbm_' + name
  103. if argtypes is not None:
  104. func.argtypes = argtypes
  105. if restype is not None:
  106. func.restype = restype
  107. if sys.platform != 'darwin':
  108. libpath = ctypes.util.find_library('db')
  109. if not libpath:
  110. # XXX this is hopeless...
  111. for c in '56789':
  112. libpath = ctypes.util.find_library('db-4.%s' % c)
  113. if libpath:
  114. break
  115. else:
  116. raise ImportError("Cannot find dbm library")
  117. lib = CDLL(libpath) # Linux
  118. _platform = 'bdb'
  119. else:
  120. lib = CDLL("/usr/lib/libdbm.dylib") # OS X
  121. _platform = 'osx'
  122. library = "GNU gdbm"
  123. funcs = {}
  124. _init_func('open', (c_char_p, c_int, c_int), restype=c_void_p)
  125. _init_func('close', (c_void_p,), restype=c_void_p)
  126. _init_func('firstkey', (c_void_p,), restype=datum)
  127. _init_func('nextkey', (c_void_p,), restype=datum)
  128. _init_func('fetch', (c_void_p, datum), restype=datum)
  129. _init_func('store', (c_void_p, datum, datum, c_int), restype=c_int)
  130. _init_func('error', (c_void_p,), restype=c_int)
  131. _init_func('delete', (c_void_p, datum), restype=c_int)
  132. lib.DBM_INSERT = 0
  133. lib.DBM_REPLACE = 1
  134. def open(filename, flag='r', mode=0666):
  135. "open a DBM database"
  136. if not isinstance(filename, str):
  137. raise TypeError("expected string")
  138. openflag = 0
  139. try:
  140. openflag = {
  141. 'r': os.O_RDONLY,
  142. 'rw': os.O_RDWR,
  143. 'w': os.O_RDWR | os.O_CREAT,
  144. 'c': os.O_RDWR | os.O_CREAT,
  145. 'n': os.O_RDWR | os.O_CREAT | os.O_TRUNC,
  146. }[flag]
  147. except KeyError, e:
  148. raise error("arg 2 to open should be 'r', 'w', 'c', or 'n'")
  149. a_db = getattr(lib, funcs['open'])(filename, openflag, mode)
  150. if a_db == 0:
  151. raise error("Could not open file %s.db" % filename)
  152. return dbm(a_db)
  153. __all__ = ('datum', 'dbm', 'error', 'funcs', 'open', 'library')