diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index ad4d5e5d92c..fe134228e94 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -558,6 +558,9 @@ in the `Porting Python code`_ section of this document. New Email Package Features ========================== +Policy Framework +---------------- + The email package now has a :mod:`~email.policy` framework. A :class:`~email.policy.Policy` is an object with several methods and properties that control how the email package behaves. The primary policy for Python 3.3 @@ -610,6 +613,99 @@ policy instances for your different cases, and pass those in when you create the ``generator``. +Provisional Policy with New Header API +-------------------------------------- + +While the policy framework is worthwhile all by itself, the main motivation for +introducing it is to allow the creation of new policies that implement new +features for the email package in a way that maintains backward compatibility +for those who do not use the new policies. Because the new policies introduce a +new API, we are releasing them in Python 3.3 as a :term:`provisional policy +`. Backwards incompatible changes (up to and including +removal of the code) may occur if deemed necessary by the core developers. + +The new policies are instances of :class:`~email.policy.EmailPolicy`, +and add the following additional controls: + + =============== ======================================================= + refold_source Controls whether or not headers parsed by a + :mod:`~email.parser` are refolded by the + :mod:`~email.generator`. It can be ``none``, ``long``, + or ``all``. The default is ``long``, which means that + source headers with a line longer than + ``max_line_length`` get refolded. ``none`` means no + line get refolded, and ``all`` means that all lines + get refolded. + + header_factory A callable that take a ``name`` and ``value`` and + produces a custom header object. + =============== ======================================================= + +The ``header_factory`` is the key to the new features provided by the new +policies. When one of the new policies is used, any header retrieved from +a ``Message`` object is an object produced by the ``header_factory``, and any +time you set a header on a ``Message`` it becomes an object produced by +``header_factory``. All such header objects have a ``name`` attribute equal +to the header name. Address and Date headers have additional attributes +that give you access to the parsed data of the header. This means you can now +do things like this:: + + >>> m = Message(policy=SMTP) + >>> m['To'] = 'Éric ' + >>> m['to'] + 'Éric ' + >>> m['to'].addresses + (Address(display_name='Éric', username='foo', domain='example.com'),) + >>> m['to'].addresses[0].username + 'foo' + >>> m['to'].addresses[0].display_name + 'Éric' + >>> m['Date'] = email.utils.localtime() + >>> m['Date'].datetime + datetime.datetime(2012, 5, 25, 21, 39, 24, 465484, tzinfo=datetime.timezone(datetime.timedelta(-1, 72000), 'EDT')) + >>> m['Date'] + 'Fri, 25 May 2012 21:44:27 -0400' + >>> print(m) + To: =?utf-8?q?=C3=89ric?= + Date: Fri, 25 May 2012 21:44:27 -0400 + +You will note that the unicode display name is automatically encoded as +``utf-8`` when the message is serialized, but that when the header is accessed +directly, you get the unicode version. This eliminates any need to deal with +the :mod:`email.header` :meth:`~email.header.decode_header` or +:meth:`~email.header.make_header` functions. + +You can also create addresses from parts:: + + >>> m['cc'] = [Group('pals', [Address('Bob', 'bob', 'example.com'), + ... Address('Sally', 'sally', 'example.com')]), + ... Address('Bonzo', addr_spec='bonz@laugh.com')] + >>> print(m) + To: =?utf-8?q?=C3=89ric?= + Date: Fri, 25 May 2012 21:44:27 -0400 + cc: pals: Bob , Sally ;, Bonzo + +Decoding to unicode is done automatically:: + + >>> m2 = message_from_string(str(m)) + >>> m2['to'] + 'Éric ' + +When you parse a message, you can use the ``addresses`` and ``groups`` +attributes of the header objects to access the groups and individual +addresses:: + + >>> m2['cc'].addresses + (Address(display_name='Bob', username='bob', domain='example.com'), Address(display_name='Sally', username='sally', domain='example.com'), Address(display_name='Bonzo', username='bonz', domain='laugh.com')) + >>> m2['cc'].groups + (Group(display_name='pals', addresses=(Address(display_name='Bob', username='bob', domain='example.com'), Address(display_name='Sally', username='sally', domain='example.com')), Group(display_name=None, addresses=(Address(display_name='Bonzo', username='bonz', domain='laugh.com'),)) + +In summary, if you use one of the new policies, header manipulation works the +way it ought to: your application works with unicode strings, and the email +package transparently encodes and decodes the unicode to and from the RFC +standard Content Transfer Encodings. + + Other Language Changes ====================== diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index 528c0a7aafb..c0995dc010e 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -707,7 +707,7 @@ def quote_plus(string, safe='', encoding=None, errors=None): def quote_from_bytes(bs, safe='/'): """Like quote(), but accepts a bytes object rather than a str, and does not perform string-to-bytes encoding. It always returns an ASCII string. - quote_from_bytes(b'abc def\xab') -> 'abc%20def%AB' + quote_from_bytes(b'abc def\x3f') -> 'abc%20def%3f' """ if not isinstance(bs, (bytes, bytearray)): raise TypeError("quote_from_bytes() expected bytes") diff --git a/Misc/NEWS b/Misc/NEWS index 23ad604486e..369b1a51b25 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ What's New in Python 3.3.0 Alpha 4? Core and Builtins ----------------- +- Issue #14712 (PEP 405): Virtual environments. Implemented by Vinay Sajip. + - Issue #14660 (PEP 420): Namespace packages. Implemented by Eric Smith. - Issue #14494: Fix __future__.py and its documentation to note that @@ -44,6 +46,17 @@ Core and Builtins Library ------- +- Issue #12586: Added new provisional policies that implement convenient + unicode support for email headers. See What's New for details. + +- Issue #14731: Refactored email Policy framework to support full backward + compatibility with Python 3.2 by default yet allow for the introduction of + new features through new policies. Note that Policy.must_be_7bit is renamed + to cte_type. + +- Issue #14920: Fix the help(urllib.parse) failure on locale C on terminals. + Have ascii characters in help. + - Issue #14548: Make multiprocessing finalizers check pid before running to cope with possibility of gc running just after fork.