Merged revisions 60234-60244 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r60234 | gregory.p.smith | 2008-01-24 10:38:26 +0100 (Thu, 24 Jan 2008) | 4 lines

  Fix issue1789: The tutorial contained a misuse of the struct module.

  (also remove an unneeded import struct from test_largefile)
........
  r60237 | vinay.sajip | 2008-01-24 13:37:08 +0100 (Thu, 24 Jan 2008) | 1 line

  Added optional delay argument to FileHandler and subclasses.
........
  r60238 | vinay.sajip | 2008-01-24 13:37:33 +0100 (Thu, 24 Jan 2008) | 1 line

  Added optional delay argument to FileHandler and subclasses.
........
  r60239 | vinay.sajip | 2008-01-24 13:38:30 +0100 (Thu, 24 Jan 2008) | 1 line

  Added documentation for optional delay argument to FileHandler and subclasses.
........
  r60240 | vinay.sajip | 2008-01-24 13:43:33 +0100 (Thu, 24 Jan 2008) | 1 line

  Updated for optional delay argument to FileHandler and subclasses.
........
  r60243 | guido.van.rossum | 2008-01-24 16:53:22 +0100 (Thu, 24 Jan 2008) | 2 lines

  Fi debug turd -- a call accidentally left out.
........
diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst
index ce574d0..98e2862 100644
--- a/Doc/library/logging.rst
+++ b/Doc/library/logging.rst
@@ -1517,12 +1517,13 @@
 :class:`StreamHandler`.
 
 
-.. class:: FileHandler(filename[, mode[, encoding]])
+.. class:: FileHandler(filename[, mode[, encoding[, delay]]])
 
    Returns a new instance of the :class:`FileHandler` class. The specified file is
    opened and used as the stream for logging. If *mode* is not specified,
    :const:`'a'` is used.  If *encoding* is not *None*, it is used to open the file
-   with that encoding.  By default, the file grows indefinitely.
+   with that encoding.  If *delay* is true, then file opening is deferred until the
+   first call to :meth:`emit`. By default, the file grows indefinitely.
 
 
 .. method:: FileHandler.close()
@@ -1556,12 +1557,13 @@
 this value.
 
 
-.. class:: WatchedFileHandler(filename[,mode[, encoding]])
+.. class:: WatchedFileHandler(filename[,mode[, encoding[, delay]]])
 
    Returns a new instance of the :class:`WatchedFileHandler` class. The specified
    file is opened and used as the stream for logging. If *mode* is not specified,
    :const:`'a'` is used.  If *encoding* is not *None*, it is used to open the file
-   with that encoding.  By default, the file grows indefinitely.
+   with that encoding.  If *delay* is true, then file opening is deferred until the
+   first call to :meth:`emit`.  By default, the file grows indefinitely.
 
 
 .. method:: WatchedFileHandler.emit(record)
@@ -1578,11 +1580,13 @@
 module, supports rotation of disk log files.
 
 
-.. class:: RotatingFileHandler(filename[, mode[, maxBytes[, backupCount]]])
+.. class:: RotatingFileHandler(filename[, mode[, maxBytes[, backupCount[, encoding[, delay]]]]])
 
    Returns a new instance of the :class:`RotatingFileHandler` class. The specified
    file is opened and used as the stream for logging. If *mode* is not specified,
-   ``'a'`` is used. By default, the file grows indefinitely.
+   ``'a'`` is used.  If *encoding* is not *None*, it is used to open the file
+   with that encoding.  If *delay* is true, then file opening is deferred until the
+   first call to :meth:`emit`.  By default, the file grows indefinitely.
 
    You can use the *maxBytes* and *backupCount* values to allow the file to
    :dfn:`rollover` at a predetermined size. When the size is about to be exceeded,
@@ -1616,7 +1620,7 @@
 timed intervals.
 
 
-.. class:: TimedRotatingFileHandler(filename [,when [,interval [,backupCount]]])
+.. class:: TimedRotatingFileHandler(filename [,when [,interval [,backupCount[, encoding[, delay]]]]])
 
    Returns a new instance of the :class:`TimedRotatingFileHandler` class. The
    specified file is opened and used as the stream for logging. On rotating it also
@@ -2053,7 +2057,13 @@
    record is computed using *msg* % *args*. If the formatting string contains
    ``'(asctime)'``, :meth:`formatTime` is called to format the event time. If there
    is exception information, it is formatted using :meth:`formatException` and
-   appended to the message.
+   appended to the message. Note that the formatted exception information is cached
+   in attribute *exc_text*. This is useful because the exception information can
+   be pickled and sent across the wire, but you should be careful if you have more
+   than one :class:`Formatter` subclass which customizes the formatting of exception
+   information. In this case, you will have to clear the cached value after a
+   formatter has done its formatting, so that the next formatter to handle the event
+   doesn't use the cached value but recalculates it afresh.
 
 
 .. method:: Formatter.formatTime(record[, datefmt])
diff --git a/Doc/tutorial/stdlib2.rst b/Doc/tutorial/stdlib2.rst
index 4e8d37e..bab0114 100644
--- a/Doc/tutorial/stdlib2.rst
+++ b/Doc/tutorial/stdlib2.rst
@@ -134,8 +134,10 @@
 
 The :mod:`struct` module provides :func:`pack` and :func:`unpack` functions for
 working with variable length binary record formats.  The following example shows
-how to loop through header information in a ZIP file (with pack codes ``"H"``
-and ``"L"`` representing two and four byte unsigned numbers respectively)::
+how to loop through header information in a ZIP file without using the
+:mod:`zipfile` module.  Pack codes ``"H"`` and ``"I"`` represent two and four
+byte unsigned numbers respectively.  The ``"<"`` indicates that they are
+standard size and in little-endian byte order::
 
    import struct
 
@@ -143,7 +145,7 @@
    start = 0
    for i in range(3):                      # show the first 3 file headers
        start += 14
-       fields = struct.unpack('LLLHH', data[start:start+16])
+       fields = struct.unpack('<IIIHH', data[start:start+16])
        crc32, comp_size, uncomp_size, filenamesize, extra_size = fields
 
        start += 16
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index 68fd10c..762ea43 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -38,8 +38,8 @@
 
 __author__  = "Vinay Sajip <vinay_sajip@red-dove.com>"
 __status__  = "production"
-__version__ = "0.5.0.4"
-__date__    = "18 January 2008"
+__version__ = "0.5.0.5"
+__date__    = "24 January 2008"
 
 #---------------------------------------------------------------------------
 #   Miscellaneous module data
@@ -760,7 +760,7 @@
     """
     A handler class which writes formatted logging records to disk files.
     """
-    def __init__(self, filename, mode='a', encoding=None):
+    def __init__(self, filename, mode='a', encoding=None, delay=0):
         """
         Open the specified file and use it as the stream for logging.
         """
@@ -771,8 +771,11 @@
         self.baseFilename = os.path.abspath(filename)
         self.mode = mode
         self.encoding = encoding
-        stream = self._open()
-        StreamHandler.__init__(self, stream)
+        if delay:
+            self.stream = None
+        else:
+            stream = self._open()
+            StreamHandler.__init__(self, stream)
 
     def close(self):
         """
@@ -795,6 +798,18 @@
             stream = codecs.open(self.baseFilename, self.mode, self.encoding)
         return stream
 
+    def emit(self, record):
+        """
+        Emit a record.
+
+        If the stream was not opened because 'delay' was specified in the
+        constructor, open it before calling the superclass's emit.
+        """
+        if self.stream is None:
+            stream = self._open()
+            StreamHandler.__init__(self, stream)
+        StreamHandler.emit(self, record)
+
 #---------------------------------------------------------------------------
 #   Manager classes and functions
 #---------------------------------------------------------------------------
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
index 08bebbd..850e3bd 100644
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -51,13 +51,13 @@
     Not meant to be instantiated directly.  Instead, use RotatingFileHandler
     or TimedRotatingFileHandler.
     """
-    def __init__(self, filename, mode, encoding=None):
+    def __init__(self, filename, mode, encoding=None, delay=0):
         """
         Use the specified filename for streamed logging
         """
         if codecs is None:
             encoding = None
-        logging.FileHandler.__init__(self, filename, mode, encoding)
+        logging.FileHandler.__init__(self, filename, mode, encoding, delay)
         self.mode = mode
         self.encoding = encoding
 
@@ -82,7 +82,7 @@
     Handler for logging to a set of files, which switches from one file
     to the next when the current file reaches a certain size.
     """
-    def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None):
+    def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0):
         """
         Open the specified file and use it as the stream for logging.
 
@@ -105,7 +105,7 @@
         """
         if maxBytes > 0:
             mode = 'a' # doesn't make sense otherwise!
-        BaseRotatingHandler.__init__(self, filename, mode, encoding)
+        BaseRotatingHandler.__init__(self, filename, mode, encoding, delay)
         self.maxBytes = maxBytes
         self.backupCount = backupCount
 
@@ -154,8 +154,8 @@
     If backupCount is > 0, when rollover is done, no more than backupCount
     files are kept - the oldest ones are deleted.
     """
-    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None):
-        BaseRotatingHandler.__init__(self, filename, 'a', encoding)
+    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0):
+        BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay)
         self.when = when.upper()
         self.backupCount = backupCount
         # Calculate the real rollover interval, which is just the number of
@@ -300,10 +300,13 @@
     This handler is based on a suggestion and patch by Chad J.
     Schroeder.
     """
-    def __init__(self, filename, mode='a', encoding=None):
-        logging.FileHandler.__init__(self, filename, mode, encoding)
-        stat = os.stat(self.baseFilename)
-        self.dev, self.ino = stat[ST_DEV], stat[ST_INO]
+    def __init__(self, filename, mode='a', encoding=None, delay=0):
+        logging.FileHandler.__init__(self, filename, mode, encoding, delay)
+        if not os.path.exists(self.baseFilename):
+            self.dev, self.ino = -1, -1
+        else:
+            stat = os.stat(self.baseFilename)
+            self.dev, self.ino = stat[ST_DEV], stat[ST_INO]
 
     def emit(self, record):
         """
@@ -319,7 +322,7 @@
         else:
             stat = os.stat(self.baseFilename)
             changed = (stat[ST_DEV] != self.dev) or (stat[ST_INO] != self.ino)
-        if changed:
+        if changed and self.stream is not None:
             self.stream.flush()
             self.stream.close()
             self.stream = self._open()
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 7ef702b..028be3d 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -4249,7 +4249,7 @@
         builtins.__import__ = orig_import
 
 def test_main():
-    #XXXweakref_segfault() # Must be first, somehow
+    weakref_segfault() # Must be first, somehow
     wrapper_segfault() # NB This one is slow
     do_this_first()
     class_docstrings()
diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py
index a54a833..6d2e27d 100644
--- a/Lib/test/test_largefile.py
+++ b/Lib/test/test_largefile.py
@@ -6,7 +6,7 @@
 #----------------------------------------------------------------------
 
 from test import test_support
-import os, struct, stat, sys
+import os, stat, sys
 
 try:
     import signal