diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index a50a124bb33..2c32d535c81 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -687,157 +687,6 @@ consideration when updating code for Python 3.3, and thus should be read about 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 -is the :class:`~email.policy.Compat32` policy, which provides backward -compatibility with the email package in Python 3.2. A ``policy`` can be -specified when an email message is parsed by a :mod:`~email.parser`, or when a -:class:`~email.message.Message` object is created, or when an email is -serialized using a :mod:`~email.generator`. Unless overridden, a policy passed -to a ``parser`` is inherited by all the ``Message`` object and sub-objects -created by the ``parser``. By default a ``generator`` will use the policy of -the ``Message`` object it is serializing. The default policy is -:data:`~email.policy.compat32`. - -The minimum set of controls implemented by all ``policy`` objects are: - - =============== ======================================================= - max_line_length The maximum length, excluding the linesep character(s), - individual lines may have when a ``Message`` is - serialized. Defaults to 78. - - linesep The character used to separate individual lines when a - ``Message`` is serialized. Defaults to ``\n``. - - cte_type ``7bit`` or ``8bit``. ``8bit`` applies only to a - ``Bytes`` ``generator``, and means that non-ASCII may - be used where allowed by the protocol (or where it - exists in the original input). - - raise_on_defect Causes a ``parser`` to raise error when defects are - encountered instead of adding them to the ``Message`` - object's ``defects`` list. - =============== ======================================================= - -A new policy instance, with new settings, is created using the -:meth:`~email.policy.Policy.clone` method of policy objects. ``clone`` takes -any of the above controls as keyword arguments. Any control not specified in -the call retains its default value. Thus you can create a policy that uses -``\r\n`` linesep characters like this:: - - mypolicy = compat32.clone(linesep='\r\n') - -Policies can be used to make the generation of messages in the format needed by -your application simpler. Instead of having to remember to specify -``linesep='\r\n'`` in all the places you call a ``generator``, you can specify -it once, when you set the policy used by the ``parser`` or the ``Message``, -whichever your program uses to create ``Message`` objects. On the other hand, -if you need to generate messages in multiple forms, you can still specify the -parameters in the appropriate ``generator`` call. Or you can have custom -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 ====================== @@ -1226,6 +1075,157 @@ API changes is deprecated. +email +----- + +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 +is the :class:`~email.policy.Compat32` policy, which provides backward +compatibility with the email package in Python 3.2. A ``policy`` can be +specified when an email message is parsed by a :mod:`~email.parser`, or when a +:class:`~email.message.Message` object is created, or when an email is +serialized using a :mod:`~email.generator`. Unless overridden, a policy passed +to a ``parser`` is inherited by all the ``Message`` object and sub-objects +created by the ``parser``. By default a ``generator`` will use the policy of +the ``Message`` object it is serializing. The default policy is +:data:`~email.policy.compat32`. + +The minimum set of controls implemented by all ``policy`` objects are: + + =============== ======================================================= + max_line_length The maximum length, excluding the linesep character(s), + individual lines may have when a ``Message`` is + serialized. Defaults to 78. + + linesep The character used to separate individual lines when a + ``Message`` is serialized. Defaults to ``\n``. + + cte_type ``7bit`` or ``8bit``. ``8bit`` applies only to a + ``Bytes`` ``generator``, and means that non-ASCII may + be used where allowed by the protocol (or where it + exists in the original input). + + raise_on_defect Causes a ``parser`` to raise error when defects are + encountered instead of adding them to the ``Message`` + object's ``defects`` list. + =============== ======================================================= + +A new policy instance, with new settings, is created using the +:meth:`~email.policy.Policy.clone` method of policy objects. ``clone`` takes +any of the above controls as keyword arguments. Any control not specified in +the call retains its default value. Thus you can create a policy that uses +``\r\n`` linesep characters like this:: + + mypolicy = compat32.clone(linesep='\r\n') + +Policies can be used to make the generation of messages in the format needed by +your application simpler. Instead of having to remember to specify +``linesep='\r\n'`` in all the places you call a ``generator``, you can specify +it once, when you set the policy used by the ``parser`` or the ``Message``, +whichever your program uses to create ``Message`` objects. On the other hand, +if you need to generate messages in multiple forms, you can still specify the +parameters in the appropriate ``generator`` call. Or you can have custom +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. + + ftplib ------