From f10878b74c8b08463407ef7feffe7f647489797c Mon Sep 17 00:00:00 2001 From: "Andrew M. Kuchling" Date: Thu, 13 Sep 2007 22:49:34 +0000 Subject: Add various items --- Doc/whatsnew/2.6.rst | 428 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 428 insertions(+) diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst index 6c799fd..0216589 100644 --- a/Doc/whatsnew/2.6.rst +++ b/Doc/whatsnew/2.6.rst @@ -2,6 +2,9 @@ What's New in Python 2.6 **************************** +.. % XXX mention switch to reST for documentation +.. % XXX mention switch to Roundup for bug tracking + :Author: A.M. Kuchling :Release: |release| :Date: |today| @@ -67,12 +70,367 @@ new feature. .. % sets module deprecated .. % ====================================================================== +Python 3.0 +================ + +.. % XXX add general comment about Python 3.0 features in 2.6 + +.. % XXX mention -3 switch + +A new command-line switch, :option:`-3`, enables warnings +about features that will be removed in Python 3.0. You can run code +with this switch to see how much work will be necessary to port +code to 3.0. + +.. seealso:: + + The 3xxx series of PEPs, which describes the development process for + Python 3.0 and various features that have been accepted, rejected, + or are still under consideration. + +PEP 343: The 'with' statement +============================= + +The previous version, Python 2.5, added the ':keyword:`with`' +statement an optional feature, to be enabled by a ``from __future__ +import generators`` directive. In 2.6 the statement no longer need to +be specially enabled; this means that :keyword:`with` is now always a +keyword. The rest of this section is a copy of the corresponding +section from "What's New in Python 2.5" document; if you read +it back when Python 2.5 came out, you can skip the rest of this +section. + +The ':keyword:`with`' statement clarifies code that previously would use +``try...finally`` blocks to ensure that clean-up code is executed. In this +section, I'll discuss the statement as it will commonly be used. In the next +section, I'll examine the implementation details and show how to write objects +for use with this statement. + +The ':keyword:`with`' statement is a new control-flow structure whose basic +structure is:: + + with expression [as variable]: + with-block + +The expression is evaluated, and it should result in an object that supports the +context management protocol (that is, has :meth:`__enter__` and :meth:`__exit__` +methods. + +The object's :meth:`__enter__` is called before *with-block* is executed and +therefore can run set-up code. It also may return a value that is bound to the +name *variable*, if given. (Note carefully that *variable* is *not* assigned +the result of *expression*.) + +After execution of the *with-block* is finished, the object's :meth:`__exit__` +method is called, even if the block raised an exception, and can therefore run +clean-up code. + +Some standard Python objects now support the context management protocol and can +be used with the ':keyword:`with`' statement. File objects are one example:: + + with open('/etc/passwd', 'r') as f: + for line in f: + print line + ... more processing code ... + +After this statement has executed, the file object in *f* will have been +automatically closed, even if the :keyword:`for` loop raised an exception part- +way through the block. + +.. note:: + + In this case, *f* is the same object created by :func:`open`, because + :meth:`file.__enter__` returns *self*. + +The :mod:`threading` module's locks and condition variables also support the +':keyword:`with`' statement:: + + lock = threading.Lock() + with lock: + # Critical section of code + ... + +The lock is acquired before the block is executed and always released once the +block is complete. + +The new :func:`localcontext` function in the :mod:`decimal` module makes it easy +to save and restore the current decimal context, which encapsulates the desired +precision and rounding characteristics for computations:: + + from decimal import Decimal, Context, localcontext + + # Displays with default precision of 28 digits + v = Decimal('578') + print v.sqrt() + + with localcontext(Context(prec=16)): + # All code in this block uses a precision of 16 digits. + # The original context is restored on exiting the block. + print v.sqrt() + + +.. _new-26-context-managers: + +Writing Context Managers +------------------------ + +Under the hood, the ':keyword:`with`' statement is fairly complicated. Most +people will only use ':keyword:`with`' in company with existing objects and +don't need to know these details, so you can skip the rest of this section if +you like. Authors of new objects will need to understand the details of the +underlying implementation and should keep reading. + +A high-level explanation of the context management protocol is: + +* The expression is evaluated and should result in an object called a "context + manager". The context manager must have :meth:`__enter__` and :meth:`__exit__` + methods. + +* The context manager's :meth:`__enter__` method is called. The value returned + is assigned to *VAR*. If no ``'as VAR'`` clause is present, the value is simply + discarded. + +* The code in *BLOCK* is executed. + +* If *BLOCK* raises an exception, the :meth:`__exit__(type, value, traceback)` + is called with the exception details, the same values returned by + :func:`sys.exc_info`. The method's return value controls whether the exception + is re-raised: any false value re-raises the exception, and ``True`` will result + in suppressing it. You'll only rarely want to suppress the exception, because + if you do the author of the code containing the ':keyword:`with`' statement will + never realize anything went wrong. + +* If *BLOCK* didn't raise an exception, the :meth:`__exit__` method is still + called, but *type*, *value*, and *traceback* are all ``None``. + +Let's think through an example. I won't present detailed code but will only +sketch the methods necessary for a database that supports transactions. + +(For people unfamiliar with database terminology: a set of changes to the +database are grouped into a transaction. Transactions can be either committed, +meaning that all the changes are written into the database, or rolled back, +meaning that the changes are all discarded and the database is unchanged. See +any database textbook for more information.) + +Let's assume there's an object representing a database connection. Our goal will +be to let the user write code like this:: + + db_connection = DatabaseConnection() + with db_connection as cursor: + cursor.execute('insert into ...') + cursor.execute('delete from ...') + # ... more operations ... + +The transaction should be committed if the code in the block runs flawlessly or +rolled back if there's an exception. Here's the basic interface for +:class:`DatabaseConnection` that I'll assume:: + + class DatabaseConnection: + # Database interface + def cursor (self): + "Returns a cursor object and starts a new transaction" + def commit (self): + "Commits current transaction" + def rollback (self): + "Rolls back current transaction" + +The :meth:`__enter__` method is pretty easy, having only to start a new +transaction. For this application the resulting cursor object would be a useful +result, so the method will return it. The user can then add ``as cursor`` to +their ':keyword:`with`' statement to bind the cursor to a variable name. :: + + class DatabaseConnection: + ... + def __enter__ (self): + # Code to start a new transaction + cursor = self.cursor() + return cursor + +The :meth:`__exit__` method is the most complicated because it's where most of +the work has to be done. The method has to check if an exception occurred. If +there was no exception, the transaction is committed. The transaction is rolled +back if there was an exception. + +In the code below, execution will just fall off the end of the function, +returning the default value of ``None``. ``None`` is false, so the exception +will be re-raised automatically. If you wished, you could be more explicit and +add a :keyword:`return` statement at the marked location. :: + + class DatabaseConnection: + ... + def __exit__ (self, type, value, tb): + if tb is None: + # No exception, so commit + self.commit() + else: + # Exception occurred, so rollback. + self.rollback() + # return False + + +.. _module-contextlib: + +The contextlib module +--------------------- + +The new :mod:`contextlib` module provides some functions and a decorator that +are useful for writing objects for use with the ':keyword:`with`' statement. + +The decorator is called :func:`contextmanager`, and lets you write a single +generator function instead of defining a new class. The generator should yield +exactly one value. The code up to the :keyword:`yield` will be executed as the +:meth:`__enter__` method, and the value yielded will be the method's return +value that will get bound to the variable in the ':keyword:`with`' statement's +:keyword:`as` clause, if any. The code after the :keyword:`yield` will be +executed in the :meth:`__exit__` method. Any exception raised in the block will +be raised by the :keyword:`yield` statement. + +Our database example from the previous section could be written using this +decorator as:: + + from contextlib import contextmanager + + @contextmanager + def db_transaction (connection): + cursor = connection.cursor() + try: + yield cursor + except: + connection.rollback() + raise + else: + connection.commit() + + db = DatabaseConnection() + with db_transaction(db) as cursor: + ... + +The :mod:`contextlib` module also has a :func:`nested(mgr1, mgr2, ...)` function +that combines a number of context managers so you don't need to write nested +':keyword:`with`' statements. In this example, the single ':keyword:`with`' +statement both starts a database transaction and acquires a thread lock:: + + lock = threading.Lock() + with nested (db_transaction(db), lock) as (cursor, locked): + ... + +Finally, the :func:`closing(object)` function returns *object* so that it can be +bound to a variable, and calls ``object.close`` at the end of the block. :: + + import urllib, sys + from contextlib import closing + + with closing(urllib.urlopen('http://www.yahoo.com')) as f: + for line in f: + sys.stdout.write(line) + + +.. seealso:: + + :pep:`343` - The "with" statement + PEP written by Guido van Rossum and Nick Coghlan; implemented by Mike Bland, + Guido van Rossum, and Neal Norwitz. The PEP shows the code generated for a + ':keyword:`with`' statement, which can be helpful in learning how the statement + works. + + The documentation for the :mod:`contextlib` module. + +.. % ====================================================================== + +.. _pep-3110: + +PEP 3110: Exception-Handling Changes +===================================================== + +One error that Python programmers occasionally make +is the following:: + + try: + ... + except TypeError, ValueError: + ... + +The author is probably trying to catch both +:exc:`TypeError` and :exc:`ValueError` exceptions, but this code +actually does something different: it will catch +:exc:`TypeError` and bind the resulting exception object +to the local name ``"ValueError"``. The correct code +would have specified a tuple:: + + try: + ... + except (TypeError, ValueError): + ... + +This error is possible because the use of the comma here is ambiguous: +does it indicate two different nodes in the parse tree, or a single +node that's a tuple. + +Python 3.0 changes the syntax to make this unambiguous by replacing +the comma with the word "as". To catch an exception and store the +exception object in the variable ``exc``, you must write:: + + try: + ... + except TypeError as exc: + ... + +Python 3.0 will only support the use of "as", and therefore interprets +the first example as catching two different exceptions. Python 2.6 +supports both the comma and "as", so existing code will continue to +work. + +.. seealso:: + + :pep:`3110` - Catching Exceptions in Python 3000 + PEP written and implemented by Collin Winter. + +.. % ====================================================================== + +.. _pep-3119: + +PEP 3119: Abstract Base Classes +===================================================== + +XXX + +.. seealso:: + + :pep:`3119` - Introducing Abstract Base Classes + PEP written by Guido van Rossum and Talin. + Implemented by XXX. + Backported to 2.6 by Benjamin Aranguren (with Alex Martelli). Other Language Changes ====================== Here are all of the changes that Python 2.6 makes to the core Python language. +* Changes to the :class:`Exception` interface + as dictated by :pep:`352` continue to be made. For 2.6, + the :attr:`message` attribute is being deprecated in favor of the + :attr:`args` attribute. + +* When calling a function using the ``**`` syntax to provide keyword + arguments, you are no longer required to use a Python dictionary; + any mapping will now work:: + + >>> def f(**kw): + ... print sorted(kw) + ... + >>> ud=UserDict.UserDict() + >>> ud['a'] = 1 + >>> ud['b'] = 'string' + >>> f(**ud) + ['a', 'b'] + + .. % Patch 1686487 + +* The :func:`compile` built-in function now accepts keyword arguments + as well as positional parameters. (Contributed by XXX.) + + .. % Patch 1444529 + * The :func:`complex` constructor now accepts strings containing parenthesized complex numbers, letting ``complex(repr(cmplx))`` will now round-trip values. For example, ``complex('(3+4j)')`` @@ -87,6 +445,15 @@ Here are all of the changes that Python 2.6 makes to the core Python language. .. % Patch 1193128 +* The built-in :func:`dir` function now checks for a :meth:`__dir__` + method on the objects it receives. This method must return a list + of strings containing the names of valid attributes for the object, + and lets the object control the value that :func:`dir` produces. + Objects that have :meth:`__getattr__` or :meth:`__getattribute__` + methods. + + .. % Patch 1591665 + * An obscure change: when you use the the :func:`locals` function inside a :keyword:`class` statement, the resulting dictionary no longer returns free variables. (Free variables, in this case, are variables referred to in the @@ -160,6 +527,11 @@ complete list of changes, or look through the CVS logs for all the details. (Contributed by Raymond Hettinger.) +* An optional ``timeout`` parameter was added to the + :class:`httplib.HTTPConnection` and :class:`HTTPSConnection` + class constructors, specifying a timeout measured in seconds. + (Added by Facundo Batista.) + * A new function in the :mod:`itertools` module: ``izip_longest(iter1, iter2, ...[, fillvalue])`` makes tuples from each of the elements; if some of the iterables are shorter than others, the missing values are set to *fillvalue*. @@ -176,6 +548,15 @@ complete list of changes, or look through the CVS logs for all the details. .. % Patch #1490190 +* The :func:`os.walk` function now has a "followlinks" parameter. If + set to True, it will follow symlinks pointing to directories and + visit the directory's contents. For backward compatibility, the + parameter's default value is false. Note that the function can fall + into an infinite recursion if there's a symlink that points to a + parent directory. + + .. % Patch 1273829 + * In the :mod:`os.path` module, the :func:`splitext` function has been changed to not split on leading period characters. This produces better results when operating on Unix's dot-files. @@ -191,6 +572,12 @@ complete list of changes, or look through the CVS logs for all the details. .. % Patch 1339796 + On Windows, :func:`os.path.expandvars` will now expand environment variables + in the form "%var%", and "~user" will be expanded into the + user's home directory path. (Contributed by XXX.) + + .. % Patch 957650 + * New functions in the :mod:`posix` module: :func:`chflags` and :func:`lchflags` are wrappers for the corresponding system calls (where they're available). Constants for the flag values are defined in the :mod:`stat` module; some @@ -217,10 +604,37 @@ complete list of changes, or look through the CVS logs for all the details. .. % Patch #957003 +* The :mod:`textwrap` module can now preserve existing whitespace + at the beginnings and ends of the newly-created lines + by specifying ``drop_whitespace=False`` + as an argument:: + + >>> S = """This sentence has a bunch of extra whitespace.""" + >>> print textwrap.fill(S, width=15) + This sentence + has a bunch + of extra + whitespace. + >>> print textwrap.fill(S, drop_whitespace=False, width=15) + This sentence + has a bunch + of extra + whitespace. + >>> + + .. % Patch #1581073 + * An optional ``timeout`` parameter was added to the :class:`telnetlib.Telnet` class constructor, specifying a timeout measured in seconds. (Added by Facundo Batista.) +* The :class:`tempfile.NamedTemporaryFile` class usually deletes + the temporary file it created when the file is closed. This + behaviour can now be changed by passing ``delete=False`` to the + constructor. (Contributed by Damien Miller.) + + .. % Patch #1537850 + * The :mod:`test.test_support` module now contains a :func:`EnvironmentVarGuard` context manager that supports temporarily changing environment variables and automatically restores them to their old values. (Contributed by Brett Cannon.) @@ -235,6 +649,20 @@ complete list of changes, or look through the CVS logs for all the details. .. % Patch #1533909 +* An optional ``timeout`` parameter was added to the + :func:`urllib.urlopen` function and the + :class:`urllib.ftpwrapper` class constructor, as well as the + :func:`urllib2.urlopen` function. The parameter specifies a timeout + measured in seconds. For example:: + + >>> u = urllib2.urlopen("http://slow.example.com", timeout=3) + Traceback (most recent call last): + ... + urllib2.URLError: + >>> + + (Added by Facundo Batista.) + .. % ====================================================================== .. % whole new modules get described in \subsections here -- cgit v0.12