diff -r ffa851df0825 -r 2fb8b9db1c86 symbian-qemu-0.9.1-12/python-2.6.1/Doc/whatsnew/2.0.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symbian-qemu-0.9.1-12/python-2.6.1/Doc/whatsnew/2.0.rst Fri Jul 31 15:01:17 2009 +0100 @@ -0,0 +1,1207 @@ +**************************** + What's New in Python 2.0 +**************************** + +:Author: A.M. Kuchling and Moshe Zadka + +.. |release| replace:: 1.02 + +.. $Id: whatsnew20.tex 50964 2006-07-30 03:03:43Z fred.drake $ + + +Introduction +============ + +A new release of Python, version 2.0, was released on October 16, 2000. This +article covers the exciting new features in 2.0, highlights some other useful +changes, and points out a few incompatible changes that may require rewriting +code. + +Python's development never completely stops between releases, and a steady flow +of bug fixes and improvements are always being submitted. A host of minor fixes, +a few optimizations, additional docstrings, and better error messages went into +2.0; to list them all would be impossible, but they're certainly significant. +Consult the publicly-available CVS logs if you want to see the full list. This +progress is due to the five developers working for PythonLabs are now getting +paid to spend their days fixing bugs, and also due to the improved communication +resulting from moving to SourceForge. + +.. ====================================================================== + + +What About Python 1.6? +====================== + +Python 1.6 can be thought of as the Contractual Obligations Python release. +After the core development team left CNRI in May 2000, CNRI requested that a 1.6 +release be created, containing all the work on Python that had been performed at +CNRI. Python 1.6 therefore represents the state of the CVS tree as of May 2000, +with the most significant new feature being Unicode support. Development +continued after May, of course, so the 1.6 tree received a few fixes to ensure +that it's forward-compatible with Python 2.0. 1.6 is therefore part of Python's +evolution, and not a side branch. + +So, should you take much interest in Python 1.6? Probably not. The 1.6final +and 2.0beta1 releases were made on the same day (September 5, 2000), the plan +being to finalize Python 2.0 within a month or so. If you have applications to +maintain, there seems little point in breaking things by moving to 1.6, fixing +them, and then having another round of breakage within a month by moving to 2.0; +you're better off just going straight to 2.0. Most of the really interesting +features described in this document are only in 2.0, because a lot of work was +done between May and September. + +.. ====================================================================== + + +New Development Process +======================= + +The most important change in Python 2.0 may not be to the code at all, but to +how Python is developed: in May 2000 the Python developers began using the tools +made available by SourceForge for storing source code, tracking bug reports, +and managing the queue of patch submissions. To report bugs or submit patches +for Python 2.0, use the bug tracking and patch manager tools available from +Python's project page, located at http://sourceforge.net/projects/python/. + +The most important of the services now hosted at SourceForge is the Python CVS +tree, the version-controlled repository containing the source code for Python. +Previously, there were roughly 7 or so people who had write access to the CVS +tree, and all patches had to be inspected and checked in by one of the people on +this short list. Obviously, this wasn't very scalable. By moving the CVS tree +to SourceForge, it became possible to grant write access to more people; as of +September 2000 there were 27 people able to check in changes, a fourfold +increase. This makes possible large-scale changes that wouldn't be attempted if +they'd have to be filtered through the small group of core developers. For +example, one day Peter Schneider-Kamp took it into his head to drop K&R C +compatibility and convert the C source for Python to ANSI C. After getting +approval on the python-dev mailing list, he launched into a flurry of checkins +that lasted about a week, other developers joined in to help, and the job was +done. If there were only 5 people with write access, probably that task would +have been viewed as "nice, but not worth the time and effort needed" and it +would never have gotten done. + +The shift to using SourceForge's services has resulted in a remarkable increase +in the speed of development. Patches now get submitted, commented on, revised +by people other than the original submitter, and bounced back and forth between +people until the patch is deemed worth checking in. Bugs are tracked in one +central location and can be assigned to a specific person for fixing, and we can +count the number of open bugs to measure progress. This didn't come without a +cost: developers now have more e-mail to deal with, more mailing lists to +follow, and special tools had to be written for the new environment. For +example, SourceForge sends default patch and bug notification e-mail messages +that are completely unhelpful, so Ka-Ping Yee wrote an HTML screen-scraper that +sends more useful messages. + +The ease of adding code caused a few initial growing pains, such as code was +checked in before it was ready or without getting clear agreement from the +developer group. The approval process that has emerged is somewhat similar to +that used by the Apache group. Developers can vote +1, +0, -0, or -1 on a patch; ++1 and -1 denote acceptance or rejection, while +0 and -0 mean the developer is +mostly indifferent to the change, though with a slight positive or negative +slant. The most significant change from the Apache model is that the voting is +essentially advisory, letting Guido van Rossum, who has Benevolent Dictator For +Life status, know what the general opinion is. He can still ignore the result of +a vote, and approve or reject a change even if the community disagrees with him. + +Producing an actual patch is the last step in adding a new feature, and is +usually easy compared to the earlier task of coming up with a good design. +Discussions of new features can often explode into lengthy mailing list threads, +making the discussion hard to follow, and no one can read every posting to +python-dev. Therefore, a relatively formal process has been set up to write +Python Enhancement Proposals (PEPs), modelled on the Internet RFC process. PEPs +are draft documents that describe a proposed new feature, and are continually +revised until the community reaches a consensus, either accepting or rejecting +the proposal. Quoting from the introduction to PEP 1, "PEP Purpose and +Guidelines": + + +.. epigraph:: + + PEP stands for Python Enhancement Proposal. A PEP is a design document + providing information to the Python community, or describing a new feature for + Python. The PEP should provide a concise technical specification of the feature + and a rationale for the feature. + + We intend PEPs to be the primary mechanisms for proposing new features, for + collecting community input on an issue, and for documenting the design decisions + that have gone into Python. The PEP author is responsible for building + consensus within the community and documenting dissenting opinions. + +Read the rest of PEP 1 for the details of the PEP editorial process, style, and +format. PEPs are kept in the Python CVS tree on SourceForge, though they're not +part of the Python 2.0 distribution, and are also available in HTML form from +http://www.python.org/peps/. As of September 2000, there are 25 PEPS, ranging +from PEP 201, "Lockstep Iteration", to PEP 225, "Elementwise/Objectwise +Operators". + +.. ====================================================================== + + +Unicode +======= + +The largest new feature in Python 2.0 is a new fundamental data type: Unicode +strings. Unicode uses 16-bit numbers to represent characters instead of the +8-bit number used by ASCII, meaning that 65,536 distinct characters can be +supported. + +The final interface for Unicode support was arrived at through countless often- +stormy discussions on the python-dev mailing list, and mostly implemented by +Marc-André Lemburg, based on a Unicode string type implementation by Fredrik +Lundh. A detailed explanation of the interface was written up as :pep:`100`, +"Python Unicode Integration". This article will simply cover the most +significant points about the Unicode interfaces. + +In Python source code, Unicode strings are written as ``u"string"``. Arbitrary +Unicode characters can be written using a new escape sequence, ``\uHHHH``, where +*HHHH* is a 4-digit hexadecimal number from 0000 to FFFF. The existing +``\xHHHH`` escape sequence can also be used, and octal escapes can be used for +characters up to U+01FF, which is represented by ``\777``. + +Unicode strings, just like regular strings, are an immutable sequence type. +They can be indexed and sliced, but not modified in place. Unicode strings have +an ``encode( [encoding] )`` method that returns an 8-bit string in the desired +encoding. Encodings are named by strings, such as ``'ascii'``, ``'utf-8'``, +``'iso-8859-1'``, or whatever. A codec API is defined for implementing and +registering new encodings that are then available throughout a Python program. +If an encoding isn't specified, the default encoding is usually 7-bit ASCII, +though it can be changed for your Python installation by calling the +:func:`sys.setdefaultencoding(encoding)` function in a customised version of +:file:`site.py`. + +Combining 8-bit and Unicode strings always coerces to Unicode, using the default +ASCII encoding; the result of ``'a' + u'bc'`` is ``u'abc'``. + +New built-in functions have been added, and existing built-ins modified to +support Unicode: + +* ``unichr(ch)`` returns a Unicode string 1 character long, containing the + character *ch*. + +* ``ord(u)``, where *u* is a 1-character regular or Unicode string, returns the + number of the character as an integer. + +* ``unicode(string [, encoding] [, errors] )`` creates a Unicode string + from an 8-bit string. ``encoding`` is a string naming the encoding to use. The + ``errors`` parameter specifies the treatment of characters that are invalid for + the current encoding; passing ``'strict'`` as the value causes an exception to + be raised on any encoding error, while ``'ignore'`` causes errors to be silently + ignored and ``'replace'`` uses U+FFFD, the official replacement character, in + case of any problems. + +* The :keyword:`exec` statement, and various built-ins such as ``eval()``, + ``getattr()``, and ``setattr()`` will also accept Unicode strings as well as + regular strings. (It's possible that the process of fixing this missed some + built-ins; if you find a built-in function that accepts strings but doesn't + accept Unicode strings at all, please report it as a bug.) + +A new module, :mod:`unicodedata`, provides an interface to Unicode character +properties. For example, ``unicodedata.category(u'A')`` returns the 2-character +string 'Lu', the 'L' denoting it's a letter, and 'u' meaning that it's +uppercase. ``unicodedata.bidirectional(u'\u0660')`` returns 'AN', meaning that +U+0660 is an Arabic number. + +The :mod:`codecs` module contains functions to look up existing encodings and +register new ones. Unless you want to implement a new encoding, you'll most +often use the :func:`codecs.lookup(encoding)` function, which returns a +4-element tuple: ``(encode_func, decode_func, stream_reader, stream_writer)``. + +* *encode_func* is a function that takes a Unicode string, and returns a 2-tuple + ``(string, length)``. *string* is an 8-bit string containing a portion (perhaps + all) of the Unicode string converted into the given encoding, and *length* tells + you how much of the Unicode string was converted. + +* *decode_func* is the opposite of *encode_func*, taking an 8-bit string and + returning a 2-tuple ``(ustring, length)``, consisting of the resulting Unicode + string *ustring* and the integer *length* telling how much of the 8-bit string + was consumed. + +* *stream_reader* is a class that supports decoding input from a stream. + *stream_reader(file_obj)* returns an object that supports the :meth:`read`, + :meth:`readline`, and :meth:`readlines` methods. These methods will all + translate from the given encoding and return Unicode strings. + +* *stream_writer*, similarly, is a class that supports encoding output to a + stream. *stream_writer(file_obj)* returns an object that supports the + :meth:`write` and :meth:`writelines` methods. These methods expect Unicode + strings, translating them to the given encoding on output. + +For example, the following code writes a Unicode string into a file, encoding +it as UTF-8:: + + import codecs + + unistr = u'\u0660\u2000ab ...' + + (UTF8_encode, UTF8_decode, + UTF8_streamreader, UTF8_streamwriter) = codecs.lookup('UTF-8') + + output = UTF8_streamwriter( open( '/tmp/output', 'wb') ) + output.write( unistr ) + output.close() + +The following code would then read UTF-8 input from the file:: + + input = UTF8_streamreader( open( '/tmp/output', 'rb') ) + print repr(input.read()) + input.close() + +Unicode-aware regular expressions are available through the :mod:`re` module, +which has a new underlying implementation called SRE written by Fredrik Lundh of +Secret Labs AB. + +A ``-U`` command line option was added which causes the Python compiler to +interpret all string literals as Unicode string literals. This is intended to be +used in testing and future-proofing your Python code, since some future version +of Python may drop support for 8-bit strings and provide only Unicode strings. + +.. ====================================================================== + + +List Comprehensions +=================== + +Lists are a workhorse data type in Python, and many programs manipulate a list +at some point. Two common operations on lists are to loop over them, and either +pick out the elements that meet a certain criterion, or apply some function to +each element. For example, given a list of strings, you might want to pull out +all the strings containing a given substring, or strip off trailing whitespace +from each line. + +The existing :func:`map` and :func:`filter` functions can be used for this +purpose, but they require a function as one of their arguments. This is fine if +there's an existing built-in function that can be passed directly, but if there +isn't, you have to create a little function to do the required work, and +Python's scoping rules make the result ugly if the little function needs +additional information. Take the first example in the previous paragraph, +finding all the strings in the list containing a given substring. You could +write the following to do it:: + + # Given the list L, make a list of all strings + # containing the substring S. + sublist = filter( lambda s, substring=S: + string.find(s, substring) != -1, + L) + +Because of Python's scoping rules, a default argument is used so that the +anonymous function created by the :keyword:`lambda` statement knows what +substring is being searched for. List comprehensions make this cleaner:: + + sublist = [ s for s in L if string.find(s, S) != -1 ] + +List comprehensions have the form:: + + [ expression for expr in sequence1 + for expr2 in sequence2 ... + for exprN in sequenceN + if condition ] + +The :keyword:`for`...\ :keyword:`in` clauses contain the sequences to be +iterated over. The sequences do not have to be the same length, because they +are *not* iterated over in parallel, but from left to right; this is explained +more clearly in the following paragraphs. The elements of the generated list +will be the successive values of *expression*. The final :keyword:`if` clause +is optional; if present, *expression* is only evaluated and added to the result +if *condition* is true. + +To make the semantics very clear, a list comprehension is equivalent to the +following Python code:: + + for expr1 in sequence1: + for expr2 in sequence2: + ... + for exprN in sequenceN: + if (condition): + # Append the value of + # the expression to the + # resulting list. + +This means that when there are multiple :keyword:`for`...\ :keyword:`in` +clauses, the resulting list will be equal to the product of the lengths of all +the sequences. If you have two lists of length 3, the output list is 9 elements +long:: + + seq1 = 'abc' + seq2 = (1,2,3) + >>> [ (x,y) for x in seq1 for y in seq2] + [('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('b', 3), ('c', 1), + ('c', 2), ('c', 3)] + +To avoid introducing an ambiguity into Python's grammar, if *expression* is +creating a tuple, it must be surrounded with parentheses. The first list +comprehension below is a syntax error, while the second one is correct:: + + # Syntax error + [ x,y for x in seq1 for y in seq2] + # Correct + [ (x,y) for x in seq1 for y in seq2] + +The idea of list comprehensions originally comes from the functional programming +language Haskell (http://www.haskell.org). Greg Ewing argued most effectively +for adding them to Python and wrote the initial list comprehension patch, which +was then discussed for a seemingly endless time on the python-dev mailing list +and kept up-to-date by Skip Montanaro. + +.. ====================================================================== + + +Augmented Assignment +==================== + +Augmented assignment operators, another long-requested feature, have been added +to Python 2.0. Augmented assignment operators include ``+=``, ``-=``, ``*=``, +and so forth. For example, the statement ``a += 2`` increments the value of the +variable ``a`` by 2, equivalent to the slightly lengthier ``a = a + 2``. + +The full list of supported assignment operators is ``+=``, ``-=``, ``*=``, +``/=``, ``%=``, ``**=``, ``&=``, ``|=``, ``^=``, ``>>=``, and ``<<=``. Python +classes can override the augmented assignment operators by defining methods +named :meth:`__iadd__`, :meth:`__isub__`, etc. For example, the following +:class:`Number` class stores a number and supports using += to create a new +instance with an incremented value. + +.. The empty groups below prevent conversion to guillemets. + +:: + + class Number: + def __init__(self, value): + self.value = value + def __iadd__(self, increment): + return Number( self.value + increment) + + n = Number(5) + n += 3 + print n.value + +The :meth:`__iadd__` special method is called with the value of the increment, +and should return a new instance with an appropriately modified value; this +return value is bound as the new value of the variable on the left-hand side. + +Augmented assignment operators were first introduced in the C programming +language, and most C-derived languages, such as :program:`awk`, C++, Java, Perl, +and PHP also support them. The augmented assignment patch was implemented by +Thomas Wouters. + +.. ====================================================================== + + +String Methods +============== + +Until now string-manipulation functionality was in the :mod:`string` module, +which was usually a front-end for the :mod:`strop` module written in C. The +addition of Unicode posed a difficulty for the :mod:`strop` module, because the +functions would all need to be rewritten in order to accept either 8-bit or +Unicode strings. For functions such as :func:`string.replace`, which takes 3 +string arguments, that means eight possible permutations, and correspondingly +complicated code. + +Instead, Python 2.0 pushes the problem onto the string type, making string +manipulation functionality available through methods on both 8-bit strings and +Unicode strings. :: + + >>> 'andrew'.capitalize() + 'Andrew' + >>> 'hostname'.replace('os', 'linux') + 'hlinuxtname' + >>> 'moshe'.find('sh') + 2 + +One thing that hasn't changed, a noteworthy April Fools' joke notwithstanding, +is that Python strings are immutable. Thus, the string methods return new +strings, and do not modify the string on which they operate. + +The old :mod:`string` module is still around for backwards compatibility, but it +mostly acts as a front-end to the new string methods. + +Two methods which have no parallel in pre-2.0 versions, although they did exist +in JPython for quite some time, are :meth:`startswith` and :meth:`endswith`. +``s.startswith(t)`` is equivalent to ``s[:len(t)] == t``, while +``s.endswith(t)`` is equivalent to ``s[-len(t):] == t``. + +One other method which deserves special mention is :meth:`join`. The +:meth:`join` method of a string receives one parameter, a sequence of strings, +and is equivalent to the :func:`string.join` function from the old :mod:`string` +module, with the arguments reversed. In other words, ``s.join(seq)`` is +equivalent to the old ``string.join(seq, s)``. + +.. ====================================================================== + + +Garbage Collection of Cycles +============================ + +The C implementation of Python uses reference counting to implement garbage +collection. Every Python object maintains a count of the number of references +pointing to itself, and adjusts the count as references are created or +destroyed. Once the reference count reaches zero, the object is no longer +accessible, since you need to have a reference to an object to access it, and if +the count is zero, no references exist any longer. + +Reference counting has some pleasant properties: it's easy to understand and +implement, and the resulting implementation is portable, fairly fast, and reacts +well with other libraries that implement their own memory handling schemes. The +major problem with reference counting is that it sometimes doesn't realise that +objects are no longer accessible, resulting in a memory leak. This happens when +there are cycles of references. + +Consider the simplest possible cycle, a class instance which has a reference to +itself:: + + instance = SomeClass() + instance.myself = instance + +After the above two lines of code have been executed, the reference count of +``instance`` is 2; one reference is from the variable named ``'instance'``, and +the other is from the ``myself`` attribute of the instance. + +If the next line of code is ``del instance``, what happens? The reference count +of ``instance`` is decreased by 1, so it has a reference count of 1; the +reference in the ``myself`` attribute still exists. Yet the instance is no +longer accessible through Python code, and it could be deleted. Several objects +can participate in a cycle if they have references to each other, causing all of +the objects to be leaked. + +Python 2.0 fixes this problem by periodically executing a cycle detection +algorithm which looks for inaccessible cycles and deletes the objects involved. +A new :mod:`gc` module provides functions to perform a garbage collection, +obtain debugging statistics, and tuning the collector's parameters. + +Running the cycle detection algorithm takes some time, and therefore will result +in some additional overhead. It is hoped that after we've gotten experience +with the cycle collection from using 2.0, Python 2.1 will be able to minimize +the overhead with careful tuning. It's not yet obvious how much performance is +lost, because benchmarking this is tricky and depends crucially on how often the +program creates and destroys objects. The detection of cycles can be disabled +when Python is compiled, if you can't afford even a tiny speed penalty or +suspect that the cycle collection is buggy, by specifying the +:option:`--without-cycle-gc` switch when running the :program:`configure` +script. + +Several people tackled this problem and contributed to a solution. An early +implementation of the cycle detection approach was written by Toby Kelsey. The +current algorithm was suggested by Eric Tiedemann during a visit to CNRI, and +Guido van Rossum and Neil Schemenauer wrote two different implementations, which +were later integrated by Neil. Lots of other people offered suggestions along +the way; the March 2000 archives of the python-dev mailing list contain most of +the relevant discussion, especially in the threads titled "Reference cycle +collection for Python" and "Finalization again". + +.. ====================================================================== + + +Other Core Changes +================== + +Various minor changes have been made to Python's syntax and built-in functions. +None of the changes are very far-reaching, but they're handy conveniences. + + +Minor Language Changes +---------------------- + +A new syntax makes it more convenient to call a given function with a tuple of +arguments and/or a dictionary of keyword arguments. In Python 1.5 and earlier, +you'd use the :func:`apply` built-in function: ``apply(f, args, kw)`` calls the +function :func:`f` with the argument tuple *args* and the keyword arguments in +the dictionary *kw*. :func:`apply` is the same in 2.0, but thanks to a patch +from Greg Ewing, ``f(*args, **kw)`` as a shorter and clearer way to achieve the +same effect. This syntax is symmetrical with the syntax for defining +functions:: + + def f(*args, **kw): + # args is a tuple of positional args, + # kw is a dictionary of keyword args + ... + +The :keyword:`print` statement can now have its output directed to a file-like +object by following the :keyword:`print` with ``>> file``, similar to the +redirection operator in Unix shells. Previously you'd either have to use the +:meth:`write` method of the file-like object, which lacks the convenience and +simplicity of :keyword:`print`, or you could assign a new value to +``sys.stdout`` and then restore the old value. For sending output to standard +error, it's much easier to write this:: + + print >> sys.stderr, "Warning: action field not supplied" + +Modules can now be renamed on importing them, using the syntax ``import module +as name`` or ``from module import name as othername``. The patch was submitted +by Thomas Wouters. + +A new format style is available when using the ``%`` operator; '%r' will insert +the :func:`repr` of its argument. This was also added from symmetry +considerations, this time for symmetry with the existing '%s' format style, +which inserts the :func:`str` of its argument. For example, ``'%r %s' % ('abc', +'abc')`` returns a string containing ``'abc' abc``. + +Previously there was no way to implement a class that overrode Python's built-in +:keyword:`in` operator and implemented a custom version. ``obj in seq`` returns +true if *obj* is present in the sequence *seq*; Python computes this by simply +trying every index of the sequence until either *obj* is found or an +:exc:`IndexError` is encountered. Moshe Zadka contributed a patch which adds a +:meth:`__contains__` magic method for providing a custom implementation for +:keyword:`in`. Additionally, new built-in objects written in C can define what +:keyword:`in` means for them via a new slot in the sequence protocol. + +Earlier versions of Python used a recursive algorithm for deleting objects. +Deeply nested data structures could cause the interpreter to fill up the C stack +and crash; Christian Tismer rewrote the deletion logic to fix this problem. On +a related note, comparing recursive objects recursed infinitely and crashed; +Jeremy Hylton rewrote the code to no longer crash, producing a useful result +instead. For example, after this code:: + + a = [] + b = [] + a.append(a) + b.append(b) + +The comparison ``a==b`` returns true, because the two recursive data structures +are isomorphic. See the thread "trashcan and PR#7" in the April 2000 archives of +the python-dev mailing list for the discussion leading up to this +implementation, and some useful relevant links. Note that comparisons can now +also raise exceptions. In earlier versions of Python, a comparison operation +such as ``cmp(a,b)`` would always produce an answer, even if a user-defined +:meth:`__cmp__` method encountered an error, since the resulting exception would +simply be silently swallowed. + +.. Starting URL: +.. http://www.python.org/pipermail/python-dev/2000-April/004834.html + +Work has been done on porting Python to 64-bit Windows on the Itanium processor, +mostly by Trent Mick of ActiveState. (Confusingly, ``sys.platform`` is still +``'win32'`` on Win64 because it seems that for ease of porting, MS Visual C++ +treats code as 32 bit on Itanium.) PythonWin also supports Windows CE; see the +Python CE page at http://starship.python.net/crew/mhammond/ce/ for more +information. + +Another new platform is Darwin/MacOS X; initial support for it is in Python 2.0. +Dynamic loading works, if you specify "configure --with-dyld --with-suffix=.x". +Consult the README in the Python source distribution for more instructions. + +An attempt has been made to alleviate one of Python's warts, the often-confusing +:exc:`NameError` exception when code refers to a local variable before the +variable has been assigned a value. For example, the following code raises an +exception on the :keyword:`print` statement in both 1.5.2 and 2.0; in 1.5.2 a +:exc:`NameError` exception is raised, while 2.0 raises a new +:exc:`UnboundLocalError` exception. :exc:`UnboundLocalError` is a subclass of +:exc:`NameError`, so any existing code that expects :exc:`NameError` to be +raised should still work. :: + + def f(): + print "i=",i + i = i + 1 + f() + +Two new exceptions, :exc:`TabError` and :exc:`IndentationError`, have been +introduced. They're both subclasses of :exc:`SyntaxError`, and are raised when +Python code is found to be improperly indented. + + +Changes to Built-in Functions +----------------------------- + +A new built-in, :func:`zip(seq1, seq2, ...)`, has been added. :func:`zip` +returns a list of tuples where each tuple contains the i-th element from each of +the argument sequences. The difference between :func:`zip` and ``map(None, +seq1, seq2)`` is that :func:`map` pads the sequences with ``None`` if the +sequences aren't all of the same length, while :func:`zip` truncates the +returned list to the length of the shortest argument sequence. + +The :func:`int` and :func:`long` functions now accept an optional "base" +parameter when the first argument is a string. ``int('123', 10)`` returns 123, +while ``int('123', 16)`` returns 291. ``int(123, 16)`` raises a +:exc:`TypeError` exception with the message "can't convert non-string with +explicit base". + +A new variable holding more detailed version information has been added to the +:mod:`sys` module. ``sys.version_info`` is a tuple ``(major, minor, micro, +level, serial)`` For example, in a hypothetical 2.0.1beta1, ``sys.version_info`` +would be ``(2, 0, 1, 'beta', 1)``. *level* is a string such as ``"alpha"``, +``"beta"``, or ``"final"`` for a final release. + +Dictionaries have an odd new method, :meth:`setdefault(key, default)`, which +behaves similarly to the existing :meth:`get` method. However, if the key is +missing, :meth:`setdefault` both returns the value of *default* as :meth:`get` +would do, and also inserts it into the dictionary as the value for *key*. Thus, +the following lines of code:: + + if dict.has_key( key ): return dict[key] + else: + dict[key] = [] + return dict[key] + +can be reduced to a single ``return dict.setdefault(key, [])`` statement. + +The interpreter sets a maximum recursion depth in order to catch runaway +recursion before filling the C stack and causing a core dump or GPF.. +Previously this limit was fixed when you compiled Python, but in 2.0 the maximum +recursion depth can be read and modified using :func:`sys.getrecursionlimit` and +:func:`sys.setrecursionlimit`. The default value is 1000, and a rough maximum +value for a given platform can be found by running a new script, +:file:`Misc/find_recursionlimit.py`. + +.. ====================================================================== + + +Porting to 2.0 +============== + +New Python releases try hard to be compatible with previous releases, and the +record has been pretty good. However, some changes are considered useful +enough, usually because they fix initial design decisions that turned out to be +actively mistaken, that breaking backward compatibility can't always be avoided. +This section lists the changes in Python 2.0 that may cause old Python code to +break. + +The change which will probably break the most code is tightening up the +arguments accepted by some methods. Some methods would take multiple arguments +and treat them as a tuple, particularly various list methods such as +:meth:`.append` and :meth:`.insert`. In earlier versions of Python, if ``L`` is +a list, ``L.append( 1,2 )`` appends the tuple ``(1,2)`` to the list. In Python +2.0 this causes a :exc:`TypeError` exception to be raised, with the message: +'append requires exactly 1 argument; 2 given'. The fix is to simply add an +extra set of parentheses to pass both values as a tuple: ``L.append( (1,2) )``. + +The earlier versions of these methods were more forgiving because they used an +old function in Python's C interface to parse their arguments; 2.0 modernizes +them to use :func:`PyArg_ParseTuple`, the current argument parsing function, +which provides more helpful error messages and treats multi-argument calls as +errors. If you absolutely must use 2.0 but can't fix your code, you can edit +:file:`Objects/listobject.c` and define the preprocessor symbol +``NO_STRICT_LIST_APPEND`` to preserve the old behaviour; this isn't recommended. + +Some of the functions in the :mod:`socket` module are still forgiving in this +way. For example, :func:`socket.connect( ('hostname', 25) )` is the correct +form, passing a tuple representing an IP address, but :func:`socket.connect( +'hostname', 25 )` also works. :func:`socket.connect_ex` and :func:`socket.bind` +are similarly easy-going. 2.0alpha1 tightened these functions up, but because +the documentation actually used the erroneous multiple argument form, many +people wrote code which would break with the stricter checking. GvR backed out +the changes in the face of public reaction, so for the :mod:`socket` module, the +documentation was fixed and the multiple argument form is simply marked as +deprecated; it *will* be tightened up again in a future Python version. + +The ``\x`` escape in string literals now takes exactly 2 hex digits. Previously +it would consume all the hex digits following the 'x' and take the lowest 8 bits +of the result, so ``\x123456`` was equivalent to ``\x56``. + +The :exc:`AttributeError` and :exc:`NameError` exceptions have a more friendly +error message, whose text will be something like ``'Spam' instance has no +attribute 'eggs'`` or ``name 'eggs' is not defined``. Previously the error +message was just the missing attribute name ``eggs``, and code written to take +advantage of this fact will break in 2.0. + +Some work has been done to make integers and long integers a bit more +interchangeable. In 1.5.2, large-file support was added for Solaris, to allow +reading files larger than 2 GiB; this made the :meth:`tell` method of file +objects return a long integer instead of a regular integer. Some code would +subtract two file offsets and attempt to use the result to multiply a sequence +or slice a string, but this raised a :exc:`TypeError`. In 2.0, long integers +can be used to multiply or slice a sequence, and it'll behave as you'd +intuitively expect it to; ``3L * 'abc'`` produces 'abcabcabc', and +``(0,1,2,3)[2L:4L]`` produces (2,3). Long integers can also be used in various +contexts where previously only integers were accepted, such as in the +:meth:`seek` method of file objects, and in the formats supported by the ``%`` +operator (``%d``, ``%i``, ``%x``, etc.). For example, ``"%d" % 2L**64`` will +produce the string ``18446744073709551616``. + +The subtlest long integer change of all is that the :func:`str` of a long +integer no longer has a trailing 'L' character, though :func:`repr` still +includes it. The 'L' annoyed many people who wanted to print long integers that +looked just like regular integers, since they had to go out of their way to chop +off the character. This is no longer a problem in 2.0, but code which does +``str(longval)[:-1]`` and assumes the 'L' is there, will now lose the final +digit. + +Taking the :func:`repr` of a float now uses a different formatting precision +than :func:`str`. :func:`repr` uses ``%.17g`` format string for C's +:func:`sprintf`, while :func:`str` uses ``%.12g`` as before. The effect is that +:func:`repr` may occasionally show more decimal places than :func:`str`, for +certain numbers. For example, the number 8.1 can't be represented exactly in +binary, so ``repr(8.1)`` is ``'8.0999999999999996'``, while str(8.1) is +``'8.1'``. + +The ``-X`` command-line option, which turned all standard exceptions into +strings instead of classes, has been removed; the standard exceptions will now +always be classes. The :mod:`exceptions` module containing the standard +exceptions was translated from Python to a built-in C module, written by Barry +Warsaw and Fredrik Lundh. + +.. Commented out for now -- I don't think anyone will care. + The pattern and match objects provided by SRE are C types, not Python + class instances as in 1.5. This means you can no longer inherit from + \class{RegexObject} or \class{MatchObject}, but that shouldn't be much + of a problem since no one should have been doing that in the first + place. +.. ====================================================================== + + +Extending/Embedding Changes +=========================== + +Some of the changes are under the covers, and will only be apparent to people +writing C extension modules or embedding a Python interpreter in a larger +application. If you aren't dealing with Python's C API, you can safely skip +this section. + +The version number of the Python C API was incremented, so C extensions compiled +for 1.5.2 must be recompiled in order to work with 2.0. On Windows, it's not +possible for Python 2.0 to import a third party extension built for Python 1.5.x +due to how Windows DLLs work, so Python will raise an exception and the import +will fail. + +Users of Jim Fulton's ExtensionClass module will be pleased to find out that +hooks have been added so that ExtensionClasses are now supported by +:func:`isinstance` and :func:`issubclass`. This means you no longer have to +remember to write code such as ``if type(obj) == myExtensionClass``, but can use +the more natural ``if isinstance(obj, myExtensionClass)``. + +The :file:`Python/importdl.c` file, which was a mass of #ifdefs to support +dynamic loading on many different platforms, was cleaned up and reorganised by +Greg Stein. :file:`importdl.c` is now quite small, and platform-specific code +has been moved into a bunch of :file:`Python/dynload_\*.c` files. Another +cleanup: there were also a number of :file:`my\*.h` files in the Include/ +directory that held various portability hacks; they've been merged into a single +file, :file:`Include/pyport.h`. + +Vladimir Marangozov's long-awaited malloc restructuring was completed, to make +it easy to have the Python interpreter use a custom allocator instead of C's +standard :func:`malloc`. For documentation, read the comments in +:file:`Include/pymem.h` and :file:`Include/objimpl.h`. For the lengthy +discussions during which the interface was hammered out, see the Web archives of +the 'patches' and 'python-dev' lists at python.org. + +Recent versions of the GUSI development environment for MacOS support POSIX +threads. Therefore, Python's POSIX threading support now works on the +Macintosh. Threading support using the user-space GNU ``pth`` library was also +contributed. + +Threading support on Windows was enhanced, too. Windows supports thread locks +that use kernel objects only in case of contention; in the common case when +there's no contention, they use simpler functions which are an order of +magnitude faster. A threaded version of Python 1.5.2 on NT is twice as slow as +an unthreaded version; with the 2.0 changes, the difference is only 10%. These +improvements were contributed by Yakov Markovitch. + +Python 2.0's source now uses only ANSI C prototypes, so compiling Python now +requires an ANSI C compiler, and can no longer be done using a compiler that +only supports K&R C. + +Previously the Python virtual machine used 16-bit numbers in its bytecode, +limiting the size of source files. In particular, this affected the maximum +size of literal lists and dictionaries in Python source; occasionally people who +are generating Python code would run into this limit. A patch by Charles G. +Waldman raises the limit from ``2^16`` to ``2^{32}``. + +Three new convenience functions intended for adding constants to a module's +dictionary at module initialization time were added: :func:`PyModule_AddObject`, +:func:`PyModule_AddIntConstant`, and :func:`PyModule_AddStringConstant`. Each +of these functions takes a module object, a null-terminated C string containing +the name to be added, and a third argument for the value to be assigned to the +name. This third argument is, respectively, a Python object, a C long, or a C +string. + +A wrapper API was added for Unix-style signal handlers. :func:`PyOS_getsig` gets +a signal handler and :func:`PyOS_setsig` will set a new handler. + +.. ====================================================================== + + +Distutils: Making Modules Easy to Install +========================================= + +Before Python 2.0, installing modules was a tedious affair -- there was no way +to figure out automatically where Python is installed, or what compiler options +to use for extension modules. Software authors had to go through an arduous +ritual of editing Makefiles and configuration files, which only really work on +Unix and leave Windows and MacOS unsupported. Python users faced wildly +differing installation instructions which varied between different extension +packages, which made administering a Python installation something of a chore. + +The SIG for distribution utilities, shepherded by Greg Ward, has created the +Distutils, a system to make package installation much easier. They form the +:mod:`distutils` package, a new part of Python's standard library. In the best +case, installing a Python module from source will require the same steps: first +you simply mean unpack the tarball or zip archive, and the run "``python +setup.py install``". The platform will be automatically detected, the compiler +will be recognized, C extension modules will be compiled, and the distribution +installed into the proper directory. Optional command-line arguments provide +more control over the installation process, the distutils package offers many +places to override defaults -- separating the build from the install, building +or installing in non-default directories, and more. + +In order to use the Distutils, you need to write a :file:`setup.py` script. For +the simple case, when the software contains only .py files, a minimal +:file:`setup.py` can be just a few lines long:: + + from distutils.core import setup + setup (name = "foo", version = "1.0", + py_modules = ["module1", "module2"]) + +The :file:`setup.py` file isn't much more complicated if the software consists +of a few packages:: + + from distutils.core import setup + setup (name = "foo", version = "1.0", + packages = ["package", "package.subpackage"]) + +A C extension can be the most complicated case; here's an example taken from +the PyXML package:: + + from distutils.core import setup, Extension + + expat_extension = Extension('xml.parsers.pyexpat', + define_macros = [('XML_NS', None)], + include_dirs = [ 'extensions/expat/xmltok', + 'extensions/expat/xmlparse' ], + sources = [ 'extensions/pyexpat.c', + 'extensions/expat/xmltok/xmltok.c', + 'extensions/expat/xmltok/xmlrole.c', + ] + ) + setup (name = "PyXML", version = "0.5.4", + ext_modules =[ expat_extension ] ) + +The Distutils can also take care of creating source and binary distributions. +The "sdist" command, run by "``python setup.py sdist``', builds a source +distribution such as :file:`foo-1.0.tar.gz`. Adding new commands isn't +difficult, "bdist_rpm" and "bdist_wininst" commands have already been +contributed to create an RPM distribution and a Windows installer for the +software, respectively. Commands to create other distribution formats such as +Debian packages and Solaris :file:`.pkg` files are in various stages of +development. + +All this is documented in a new manual, *Distributing Python Modules*, that +joins the basic set of Python documentation. + +.. ====================================================================== + + +XML Modules +=========== + +Python 1.5.2 included a simple XML parser in the form of the :mod:`xmllib` +module, contributed by Sjoerd Mullender. Since 1.5.2's release, two different +interfaces for processing XML have become common: SAX2 (version 2 of the Simple +API for XML) provides an event-driven interface with some similarities to +:mod:`xmllib`, and the DOM (Document Object Model) provides a tree-based +interface, transforming an XML document into a tree of nodes that can be +traversed and modified. Python 2.0 includes a SAX2 interface and a stripped- +down DOM interface as part of the :mod:`xml` package. Here we will give a brief +overview of these new interfaces; consult the Python documentation or the source +code for complete details. The Python XML SIG is also working on improved +documentation. + + +SAX2 Support +------------ + +SAX defines an event-driven interface for parsing XML. To use SAX, you must +write a SAX handler class. Handler classes inherit from various classes +provided by SAX, and override various methods that will then be called by the +XML parser. For example, the :meth:`startElement` and :meth:`endElement` +methods are called for every starting and end tag encountered by the parser, the +:meth:`characters` method is called for every chunk of character data, and so +forth. + +The advantage of the event-driven approach is that the whole document doesn't +have to be resident in memory at any one time, which matters if you are +processing really huge documents. However, writing the SAX handler class can +get very complicated if you're trying to modify the document structure in some +elaborate way. + +For example, this little example program defines a handler that prints a message +for every starting and ending tag, and then parses the file :file:`hamlet.xml` +using it:: + + from xml import sax + + class SimpleHandler(sax.ContentHandler): + def startElement(self, name, attrs): + print 'Start of element:', name, attrs.keys() + + def endElement(self, name): + print 'End of element:', name + + # Create a parser object + parser = sax.make_parser() + + # Tell it what handler to use + handler = SimpleHandler() + parser.setContentHandler( handler ) + + # Parse a file! + parser.parse( 'hamlet.xml' ) + +For more information, consult the Python documentation, or the XML HOWTO at +http://pyxml.sourceforge.net/topics/howto/xml-howto.html. + + +DOM Support +----------- + +The Document Object Model is a tree-based representation for an XML document. A +top-level :class:`Document` instance is the root of the tree, and has a single +child which is the top-level :class:`Element` instance. This :class:`Element` +has children nodes representing character data and any sub-elements, which may +have further children of their own, and so forth. Using the DOM you can +traverse the resulting tree any way you like, access element and attribute +values, insert and delete nodes, and convert the tree back into XML. + +The DOM is useful for modifying XML documents, because you can create a DOM +tree, modify it by adding new nodes or rearranging subtrees, and then produce a +new XML document as output. You can also construct a DOM tree manually and +convert it to XML, which can be a more flexible way of producing XML output than +simply writing ````...\ ```` to a file. + +The DOM implementation included with Python lives in the :mod:`xml.dom.minidom` +module. It's a lightweight implementation of the Level 1 DOM with support for +XML namespaces. The :func:`parse` and :func:`parseString` convenience +functions are provided for generating a DOM tree:: + + from xml.dom import minidom + doc = minidom.parse('hamlet.xml') + +``doc`` is a :class:`Document` instance. :class:`Document`, like all the other +DOM classes such as :class:`Element` and :class:`Text`, is a subclass of the +:class:`Node` base class. All the nodes in a DOM tree therefore support certain +common methods, such as :meth:`toxml` which returns a string containing the XML +representation of the node and its children. Each class also has special +methods of its own; for example, :class:`Element` and :class:`Document` +instances have a method to find all child elements with a given tag name. +Continuing from the previous 2-line example:: + + perslist = doc.getElementsByTagName( 'PERSONA' ) + print perslist[0].toxml() + print perslist[1].toxml() + +For the *Hamlet* XML file, the above few lines output:: + + CLAUDIUS, king of Denmark. + HAMLET, son to the late, and nephew to the present king. + +The root element of the document is available as ``doc.documentElement``, and +its children can be easily modified by deleting, adding, or removing nodes:: + + root = doc.documentElement + + # Remove the first child + root.removeChild( root.childNodes[0] ) + + # Move the new first child to the end + root.appendChild( root.childNodes[0] ) + + # Insert the new first child (originally, + # the third child) before the 20th child. + root.insertBefore( root.childNodes[0], root.childNodes[20] ) + +Again, I will refer you to the Python documentation for a complete listing of +the different :class:`Node` classes and their various methods. + + +Relationship to PyXML +--------------------- + +The XML Special Interest Group has been working on XML-related Python code for a +while. Its code distribution, called PyXML, is available from the SIG's Web +pages at http://www.python.org/sigs/xml-sig/. The PyXML distribution also used +the package name ``xml``. If you've written programs that used PyXML, you're +probably wondering about its compatibility with the 2.0 :mod:`xml` package. + +The answer is that Python 2.0's :mod:`xml` package isn't compatible with PyXML, +but can be made compatible by installing a recent version PyXML. Many +applications can get by with the XML support that is included with Python 2.0, +but more complicated applications will require that the full PyXML package will +be installed. When installed, PyXML versions 0.6.0 or greater will replace the +:mod:`xml` package shipped with Python, and will be a strict superset of the +standard package, adding a bunch of additional features. Some of the additional +features in PyXML include: + +* 4DOM, a full DOM implementation from FourThought, Inc. + +* The xmlproc validating parser, written by Lars Marius Garshol. + +* The :mod:`sgmlop` parser accelerator module, written by Fredrik Lundh. + +.. ====================================================================== + + +Module changes +============== + +Lots of improvements and bugfixes were made to Python's extensive standard +library; some of the affected modules include :mod:`readline`, +:mod:`ConfigParser`, :mod:`cgi`, :mod:`calendar`, :mod:`posix`, :mod:`readline`, +:mod:`xmllib`, :mod:`aifc`, :mod:`chunk, wave`, :mod:`random`, :mod:`shelve`, +and :mod:`nntplib`. Consult the CVS logs for the exact patch-by-patch details. + +Brian Gallew contributed OpenSSL support for the :mod:`socket` module. OpenSSL +is an implementation of the Secure Socket Layer, which encrypts the data being +sent over a socket. When compiling Python, you can edit :file:`Modules/Setup` +to include SSL support, which adds an additional function to the :mod:`socket` +module: :func:`socket.ssl(socket, keyfile, certfile)`, which takes a socket +object and returns an SSL socket. The :mod:`httplib` and :mod:`urllib` modules +were also changed to support "https://" URLs, though no one has implemented FTP +or SMTP over SSL. + +The :mod:`httplib` module has been rewritten by Greg Stein to support HTTP/1.1. +Backward compatibility with the 1.5 version of :mod:`httplib` is provided, +though using HTTP/1.1 features such as pipelining will require rewriting code to +use a different set of interfaces. + +The :mod:`Tkinter` module now supports Tcl/Tk version 8.1, 8.2, or 8.3, and +support for the older 7.x versions has been dropped. The Tkinter module now +supports displaying Unicode strings in Tk widgets. Also, Fredrik Lundh +contributed an optimization which makes operations like ``create_line`` and +``create_polygon`` much faster, especially when using lots of coordinates. + +The :mod:`curses` module has been greatly extended, starting from Oliver +Andrich's enhanced version, to provide many additional functions from ncurses +and SYSV curses, such as colour, alternative character set support, pads, and +mouse support. This means the module is no longer compatible with operating +systems that only have BSD curses, but there don't seem to be any currently +maintained OSes that fall into this category. + +As mentioned in the earlier discussion of 2.0's Unicode support, the underlying +implementation of the regular expressions provided by the :mod:`re` module has +been changed. SRE, a new regular expression engine written by Fredrik Lundh and +partially funded by Hewlett Packard, supports matching against both 8-bit +strings and Unicode strings. + +.. ====================================================================== + + +New modules +=========== + +A number of new modules were added. We'll simply list them with brief +descriptions; consult the 2.0 documentation for the details of a particular +module. + +* :mod:`atexit`: For registering functions to be called before the Python + interpreter exits. Code that currently sets ``sys.exitfunc`` directly should be + changed to use the :mod:`atexit` module instead, importing :mod:`atexit` and + calling :func:`atexit.register` with the function to be called on exit. + (Contributed by Skip Montanaro.) + +* :mod:`codecs`, :mod:`encodings`, :mod:`unicodedata`: Added as part of the new + Unicode support. + +* :mod:`filecmp`: Supersedes the old :mod:`cmp`, :mod:`cmpcache` and + :mod:`dircmp` modules, which have now become deprecated. (Contributed by Gordon + MacMillan and Moshe Zadka.) + +* :mod:`gettext`: This module provides internationalization (I18N) and + localization (L10N) support for Python programs by providing an interface to the + GNU gettext message catalog library. (Integrated by Barry Warsaw, from separate + contributions by Martin von Löwis, Peter Funk, and James Henstridge.) + +* :mod:`linuxaudiodev`: Support for the :file:`/dev/audio` device on Linux, a + twin to the existing :mod:`sunaudiodev` module. (Contributed by Peter Bosch, + with fixes by Jeremy Hylton.) + +* :mod:`mmap`: An interface to memory-mapped files on both Windows and Unix. A + file's contents can be mapped directly into memory, at which point it behaves + like a mutable string, so its contents can be read and modified. They can even + be passed to functions that expect ordinary strings, such as the :mod:`re` + module. (Contributed by Sam Rushing, with some extensions by A.M. Kuchling.) + +* :mod:`pyexpat`: An interface to the Expat XML parser. (Contributed by Paul + Prescod.) + +* :mod:`robotparser`: Parse a :file:`robots.txt` file, which is used for writing + Web spiders that politely avoid certain areas of a Web site. The parser accepts + the contents of a :file:`robots.txt` file, builds a set of rules from it, and + can then answer questions about the fetchability of a given URL. (Contributed + by Skip Montanaro.) + +* :mod:`tabnanny`: A module/script to check Python source code for ambiguous + indentation. (Contributed by Tim Peters.) + +* :mod:`UserString`: A base class useful for deriving objects that behave like + strings. + +* :mod:`webbrowser`: A module that provides a platform independent way to launch + a web browser on a specific URL. For each platform, various browsers are tried + in a specific order. The user can alter which browser is launched by setting the + *BROWSER* environment variable. (Originally inspired by Eric S. Raymond's patch + to :mod:`urllib` which added similar functionality, but the final module comes + from code originally implemented by Fred Drake as + :file:`Tools/idle/BrowserControl.py`, and adapted for the standard library by + Fred.) + +* :mod:`_winreg`: An interface to the Windows registry. :mod:`_winreg` is an + adaptation of functions that have been part of PythonWin since 1995, but has now + been added to the core distribution, and enhanced to support Unicode. + :mod:`_winreg` was written by Bill Tutt and Mark Hammond. + +* :mod:`zipfile`: A module for reading and writing ZIP-format archives. These + are archives produced by :program:`PKZIP` on DOS/Windows or :program:`zip` on + Unix, not to be confused with :program:`gzip`\ -format files (which are + supported by the :mod:`gzip` module) (Contributed by James C. Ahlstrom.) + +* :mod:`imputil`: A module that provides a simpler way for writing customised + import hooks, in comparison to the existing :mod:`ihooks` module. (Implemented + by Greg Stein, with much discussion on python-dev along the way.) + +.. ====================================================================== + + +IDLE Improvements +================= + +IDLE is the official Python cross-platform IDE, written using Tkinter. Python +2.0 includes IDLE 0.6, which adds a number of new features and improvements. A +partial list: + +* UI improvements and optimizations, especially in the area of syntax + highlighting and auto-indentation. + +* The class browser now shows more information, such as the top level functions + in a module. + +* Tab width is now a user settable option. When opening an existing Python file, + IDLE automatically detects the indentation conventions, and adapts. + +* There is now support for calling browsers on various platforms, used to open + the Python documentation in a browser. + +* IDLE now has a command line, which is largely similar to the vanilla Python + interpreter. + +* Call tips were added in many places. + +* IDLE can now be installed as a package. + +* In the editor window, there is now a line/column bar at the bottom. + +* Three new keystroke commands: Check module (Alt-F5), Import module (F5) and + Run script (Ctrl-F5). + +.. ====================================================================== + + +Deleted and Deprecated Modules +============================== + +A few modules have been dropped because they're obsolete, or because there are +now better ways to do the same thing. The :mod:`stdwin` module is gone; it was +for a platform-independent windowing toolkit that's no longer developed. + +A number of modules have been moved to the :file:`lib-old` subdirectory: +:mod:`cmp`, :mod:`cmpcache`, :mod:`dircmp`, :mod:`dump`, :mod:`find`, +:mod:`grep`, :mod:`packmail`, :mod:`poly`, :mod:`util`, :mod:`whatsound`, +:mod:`zmod`. If you have code which relies on a module that's been moved to +:file:`lib-old`, you can simply add that directory to ``sys.path`` to get them +back, but you're encouraged to update any code that uses these modules. + + +Acknowledgements +================ + +The authors would like to thank the following people for offering suggestions on +various drafts of this article: David Bolen, Mark Hammond, Gregg Hauser, Jeremy +Hylton, Fredrik Lundh, Detlef Lannert, Aahz Maruch, Skip Montanaro, Vladimir +Marangozov, Tobias Polzin, Guido van Rossum, Neil Schemenauer, and Russ Schmidt. +