Commits

Anonymous committed 505fc47

added __doc__ strings etc.

  • Participants
  • Parent commits 6a04256
  • Branches legacy-trunk

Comments (0)

Files changed (3)

-"""A generic interface to all dbm clones."""
+"""A generic interface to all dbm clones.
+
+Instead of
+
+	import dbm
+	d = dbm.open(file, 'rw', 0666)
+
+use
+
+	import anydbm
+	d = anydbm.open(file)
+
+The returned object is a dbm, gdbm or (on the Mac) dbmac object,
+dependent on availability of the modules (tested in this order).
+
+It has the following interface (key and data are strings):
+
+	d[key] = data	# store data at key (may override data at
+			# existing key)
+	data = d[key]	# retrieve data at key (raise KeyError if no
+			# such key)
+	del d[key]	# delete data stored at key (raises KeyError
+			# if no such key)
+	flag = d.has_key(key)	# true if the key exists
+	list = d.keys()	# return a list of all existing keys (slow!)
+
+Future versions may change the order in which implementations are
+tested for existence, add interfaces to other db-like implementations
+(e.g. BSD Hash), and (in the presence of multiple implementations)
+decide which module to use based upon the extension or contents of an
+existing database file.
+
+The open function has an optional second argument.  This can be set to
+'r' to open the database for reading only.  Don't pas an explicit 'w'
+or 'rw' to open it for writing, as the different interfaces have
+different interpretation of their mode argument if it isn't 'r'.
+"""
 
 try:
 	import dbm
-	def open(file, mode = 'rw'):
-		return dbm.open(file, mode, 0666)
+	def open(filename, mode = 'rw'):
+		return dbm.open(filename, mode, 0666)
 except ImportError:
-	import dbmac
-	open = dbmac.open
+	try:
+		import gdbm
+		def open(filename, mode = 'w'):
+			return gdbm.open(filename, mode, 0666)
+	except ImportError:
+		import dbmac
+		open = dbmac.open
-# Generic (shallow and deep) copying operations
-# =============================================
-# 
-# The difference between shallow and deep copying is only relevant for
-# compound objects (objects that contain other objects, like lists or class
-# instances).
-# 
-# - A shallow copy constructs a new compound object and then (to the extent
-#   possible) inserts *the same objects* into in that the original contains.
-# 
-# - A deep copy constructs a new compound object and then, recursively,
-#   inserts *copies* into it of the objects found in the original.
-# 
-# Two problems often exist with deep copy operations that don't exist with
-# shallow copy operations:
-# 
-# (a) recursive objects (compound objects that, directly or indirectly,
-#     contain a reference to themselves) may cause a recursive loop
-# 
-# (b) because deep copy copies *everything* it may copy too much, e.g.
-#     administrative data structures that should be shared even between copies
-# 
-# Python's deep copy operation avoids these problems by:
-#
-# (a) keeping a table of objects already copied during the current copying pass
-# 
-# (b) letting user-defined classes override the copying operation or the set
-#     of components copied
-# 
-# This version does not copy types like module, class, function, method,
-# nor stack trace, stack frame, nor file, socket, window, nor array,
-# nor any similar types.
+"""\
+Generic (shallow and deep) copying operations
+=============================================
 
+Interface summary:
+
+	import copy
+
+	x = copy.copy(y)	# make a shallow copy of y
+	x = copy.deepcopy(y)	# make a deep copy of y
+
+For module specific errors, copy.Error is raised.
+
+The difference between shallow and deep copying is only relevant for
+compound objects (objects that contain other objects, like lists or
+class instances).
+
+- A shallow copy constructs a new compound object and then (to the
+  extent possible) inserts *the same objects* into in that the
+  original contains.
+
+- A deep copy constructs a new compound object and then, recursively,
+  inserts *copies* into it of the objects found in the original.
+
+Two problems often exist with deep copy operations that don't exist
+with shallow copy operations:
+
+(a) recursive objects (compound objects that, directly or indirectly,
+    contain a reference to themselves) may cause a recursive loop
+
+(b) because deep copy copies *everything* it may copy too much, e.g.
+    administrative data structures that should be shared even between
+    copies
+
+Python's deep copy operation avoids these problems by:
+
+(a) keeping a table of objects already copied during the current
+copying pass
+
+(b) letting user-defined classes override the copying operation or the
+    set of components copied
+
+This version does not copy types like module, class, function, method,
+nor stack trace, stack frame, nor file, socket, window, nor array, nor
+any similar types.
+
+Classes can use the same interfaces to control copying that they use
+to control pickling: they can define methods called __getinitargs__(),
+__getstate__() and __setstate__().  See the __doc__ string of module
+"pickle" for information on these methods.
+"""
 
 import types
 
 Error = 'copy.Error'
 
 def copy(x):
+	"""Shallow copy operation on arbitrary Python objects.
+
+	See the module's __doc__ string for more info.
+	"""
+
 	try:
 		copierfunction = _copy_dispatch[type(x)]
 	except KeyError:
 		try:
 			copier = x.__copy__
 		except AttributeError:
-			raise Error, "un(shallow)copyable object of type %s" % type(x)
+			raise Error, \
+			      "un(shallow)copyable object of type %s" % type(x)
 		y = copier()
 	else:
 		y = copierfunction(x)
 del d
 
 def deepcopy(x, memo = None):
+	"""Deep copy operation on arbitrary Python objects.
+
+	See the module's __doc__ string for more info.
+	"""
+
 	if memo is None:
 		memo = {}
 	d = id(x)
 		try:
 			copier = x.__deepcopy__
 		except AttributeError:
-			raise Error, "un-deep-copyable object of type %s" % type(x)
+			raise Error, \
+			      "un-deep-copyable object of type %s" % type(x)
 		y = copier(memo)
 	else:
 		y = copierfunction(x, memo)
-"""Manage shelves of pickled objects."""
+"""Manage shelves of pickled objects.
+
+A "shelf" is a persistent, dictionary-like object.  The difference
+with dbm databases is that the values (not the keys!) in a shelf can
+be essentially arbitrary Python objects -- anything that the "pickle"
+module can handle.  This includes most class instances, recursive data
+types, and objects containing lots of shared sub-objects.  The keys
+are ordinary strings.
+
+To summarize the interface (key is a string, data is an arbitrary
+object):
+
+	import shelve
+	d = shelve.open(filename)	# open, with (g)dbm filename
+
+	d[key] = data	# store data at key (overwrites old data if
+			# using an existing key)
+	data = d[key]	# retrieve data at key (raise KeyError if no
+			# such key)
+	del d[key]	# delete data stored at key (raises KeyError
+			# if no such key)
+	flag = d.has_key(key)	# true if the key exists
+	list = d.keys()	# a list of all existing keys (slow!)
+
+	d.close()	# close it
+
+Dependent on the implementation, closing a persistent dictionary may
+or may not be necessary to flush changes to disk.
+"""
 
 import pickle
 import StringIO
 
+
 class Shelf:
+	"""Base class for shelf implementations.
+
+	This is initialized with a dictionary-like object.
+	See the module's __doc__ string for an overview of the interface.
+	"""
 
 	def __init__(self, dict):
 		self.dict = dict
 		return self.dict.has_key(key)
 	
 	def __getitem__(self, key):
-		return pickle.Unpickler(StringIO.StringIO(self.dict[key])).load()
+		f = StringIO.StringIO(self.dict[key])
+		return pickle.Unpickler(f).load()
 	
 	def __setitem__(self, key, value):
 		f = StringIO.StringIO()
 		del self.dict[key]
 	
 	def close(self):
-		self.db.close()
+		if hasattr(self.db, 'close'):
+			self.db.close()
 		self.db = None
 
+	def __del__(self):
+		self.close()
+
+
 class DbShelf(Shelf):
+	"""Shelf implementation using the "anydbm" generic dbm interface.
+
+	This is initialized with the filename for the dbm database.
+	See the module's __doc__ string for an overview of the interface.
+	"""
 	
-	def __init__(self, file):
+	def __init__(self, filename):
 		import anydbm
-		Shelf.__init__(self, anydbm.open(file))
+		Shelf.__init__(self, anydbm.open(filename))
 
-def open(file):
-	return DbShelf(file)
+
+def open(filename):
+	"""Open a persistent dictionary for reading and writing.
+
+	Argument is the filename for the dbm database.
+	See the module's __doc__ string for an overview of the interface.
+	"""
+	
+	return DbShelf(filename)