#18584: make doctest examples in email documentation pass.

With the exception of the 'as_string' call in the policy docs.
That one is a separate issue.

Note that when building the docs sphinx is complaining about
.. testcleanup:: being an invalid directive.  I don't know
why this is, as I'm following the sphinx docs...but fortunately
the action is to omit the text in the body, so the generated
documentation is correct.
This commit is contained in:
R David Murray 2013-07-29 15:49:58 -04:00
parent c06c0aed58
commit fdfb0050bb
3 changed files with 66 additions and 22 deletions

View File

@ -33,14 +33,22 @@ useful higher level iterations over message object trees.
Thus, by default :func:`typed_subpart_iterator` returns each subpart that has a
MIME type of :mimetype:`text/\*`.
The following function has been added as a useful debugging tool. It should
*not* be considered part of the supported public interface for the package.
.. function:: _structure(msg, fp=None, level=0, include_default=False)
Prints an indented representation of the content types of the message object
structure. For example::
structure. For example:
.. testsetup::
>>> import email
>>> from email.iterators import _structure
>>> somefile = open('Lib/test/test_email/data/msg_02.txt')
.. doctest::
>>> msg = email.message_from_file(somefile)
>>> _structure(msg)
@ -60,6 +68,10 @@ The following function has been added as a useful debugging tool. It should
text/plain
text/plain
.. testcleanup::
>>> somefile.close()
Optional *fp* is a file-like object to print the output to. It must be
suitable for Python's :func:`print` function. *level* is used internally.
*include_default*, if true, prints the default type as well.

View File

@ -513,16 +513,25 @@ Here are the methods of the :class:`Message` class:
iterator in a ``for`` loop; each iteration returns the next subpart.
Here's an example that prints the MIME type of every part of a multipart
message structure::
message structure:
>>> for part in msg.walk():
... print(part.get_content_type())
multipart/report
text/plain
message/delivery-status
text/plain
text/plain
message/rfc822
.. testsetup::
>>> from email import message_from_binary_file
>>> with open('Lib/test/test_email/data/msg_16.txt', 'rb') as f:
... msg = message_from_binary_file(f)
.. doctest::
>>> for part in msg.walk():
... print(part.get_content_type())
multipart/report
text/plain
message/delivery-status
text/plain
text/plain
message/rfc822
text/plain
:class:`Message` objects can also optionally contain two instance attributes,
which can be used when generating the plain text of a MIME message.

View File

@ -56,19 +56,42 @@ same keyword arguments as the class constructor and returning a new
attributes values changed.
As an example, the following code could be used to read an email message from a
file on disk and pass it to the system ``sendmail`` program on a Unix system::
file on disk and pass it to the system ``sendmail`` program on a Unix system:
>>> from email import msg_from_binary_file
.. testsetup::
>>> from unittest import mock
>>> mocker = mock.patch('subprocess.Popen')
>>> m = mocker.start()
>>> proc = mock.MagicMock()
>>> m.return_value = proc
>>> proc.stdin.close.return_value = None
>>> mymsg = open('mymsg.txt', 'w')
>>> mymsg.write('To: abc@xyz.com\n\n')
17
>>> mymsg.flush()
.. doctest::
>>> from email import message_from_binary_file
>>> from email.generator import BytesGenerator
>>> from email import policy
>>> from subprocess import Popen, PIPE
>>> with open('mymsg.txt', 'b') as f:
... msg = msg_from_binary_file(f)
>>> p = Popen(['sendmail', msg['To'][0].address], stdin=PIPE)
>>> with open('mymsg.txt', 'rb') as f:
... msg = message_from_binary_file(f, policy=policy.default)
>>> p = Popen(['sendmail', msg['To'].addresses[0]], stdin=PIPE)
>>> g = BytesGenerator(p.stdin, policy=msg.policy.clone(linesep='\r\n'))
>>> g.flatten(msg)
>>> p.stdin.close()
>>> rc = p.wait()
.. testcleanup::
>>> mymsg.close()
>>> mocker.stop()
>>> import os
>>> os.remove('mymsg.txt')
Here we are telling :class:`~email.generator.BytesGenerator` to use the RFC
correct line separator characters when creating the binary string to feed into
``sendmail's`` ``stdin``, where the default policy would use ``\n`` line
@ -82,22 +105,22 @@ separators for the platform on which it is running::
>>> import os
>>> with open('converted.txt', 'wb') as f:
... f.write(msg.as_string(policy=msg.policy.clone(linesep=os.linesep))
... f.write(msg.as_string(policy=msg.policy.clone(linesep=os.linesep)))
Policy objects can also be combined using the addition operator, producing a
policy object whose settings are a combination of the non-default values of the
summed objects::
>>> compat_SMTP = email.policy.clone(linesep='\r\n')
>>> compat_strict = email.policy.clone(raise_on_defect=True)
>>> compat_SMTP = policy.compat32.clone(linesep='\r\n')
>>> compat_strict = policy.compat32.clone(raise_on_defect=True)
>>> compat_strict_SMTP = compat_SMTP + compat_strict
This operation is not commutative; that is, the order in which the objects are
added matters. To illustrate::
>>> policy100 = compat32.clone(max_line_length=100)
>>> policy80 = compat32.clone(max_line_length=80)
>>> apolicy = policy100 + Policy80
>>> policy100 = policy.compat32.clone(max_line_length=100)
>>> policy80 = policy.compat32.clone(max_line_length=80)
>>> apolicy = policy100 + policy80
>>> apolicy.max_line_length
80
>>> apolicy = policy80 + policy100