From barry@users.sourceforge.net Tue Oct 1 00:07:42 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 30 Sep 2002 16:07:42 -0700 Subject: [Python-checkins] python/dist/src/Lib/email Header.py,1.12,1.13 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv6887 Modified Files: Header.py Log Message: Docstring consistency with the updated .tex files. Index: Header.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Header.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** Header.py 30 Sep 2002 15:51:31 -0000 1.12 --- Header.py 30 Sep 2002 23:07:35 -0000 1.13 *************** *** 206,214 **** (i.e. isinstance(s, StringType) is true), then charset is the encoding of that byte string, and a UnicodeError will be raised if the string ! cannot be decoded with that charset. If `s' is a Unicode string, then charset is a hint specifying the character set of the characters in the string. In this case, when producing an RFC 2822 compliant header using RFC 2047 rules, the Unicode string will be encoded using the ! following charsets in order: us-ascii, the charset hint, utf-8. """ if charset is None: --- 206,215 ---- (i.e. isinstance(s, StringType) is true), then charset is the encoding of that byte string, and a UnicodeError will be raised if the string ! cannot be decoded with that charset. If s is a Unicode string, then charset is a hint specifying the character set of the characters in the string. In this case, when producing an RFC 2822 compliant header using RFC 2047 rules, the Unicode string will be encoded using the ! following charsets in order: us-ascii, the charset hint, utf-8. The ! first character set not to provoke a UnicodeError is used. """ if charset is None: *************** *** 377,381 **** def encode(self): ! """Encode a message header, possibly converting charset and encoding. There are many issues involved in converting a given string for use in --- 378,382 ---- def encode(self): ! """Encode a message header into an RFC-compliant format. There are many issues involved in converting a given string for use in From barry@users.sourceforge.net Tue Oct 1 01:02:36 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 30 Sep 2002 17:02:36 -0700 Subject: [Python-checkins] python/dist/src/Lib/email Charset.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv28660 Modified Files: Charset.py Log Message: Docstring consistency with the updated .tex files. Index: Charset.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Charset.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Charset.py 28 Sep 2002 17:47:56 -0000 1.6 --- Charset.py 1 Oct 2002 00:02:33 -0000 1.7 *************** *** 86,90 **** # Convenience functions for extending the above mappings def add_charset(charset, header_enc=None, body_enc=None, output_charset=None): ! """Add charset properties to the global map. charset is the input character set, and must be the canonical name of a --- 86,90 ---- # Convenience functions for extending the above mappings def add_charset(charset, header_enc=None, body_enc=None, output_charset=None): ! """Add character set properties to the global registry. charset is the input character set, and must be the canonical name of a *************** *** 105,109 **** Both input_charset and output_charset must have Unicode codec entries in the module's charset-to-codec mapping; use add_codec(charset, codecname) ! to add codecs the module does not know about. See the codec module's documentation for more information. """ --- 105,109 ---- Both input_charset and output_charset must have Unicode codec entries in the module's charset-to-codec mapping; use add_codec(charset, codecname) ! to add codecs the module does not know about. See the codecs module's documentation for more information. """ *************** *** 127,131 **** charset is the canonical name of a character set. codecname is the name of a Python codec, as appropriate for the second argument to the unicode() ! built-in, or to the .encode() method of a Unicode string. """ CODEC_MAP[charset] = codecname --- 127,131 ---- charset is the canonical name of a character set. codecname is the name of a Python codec, as appropriate for the second argument to the unicode() ! built-in, or to the encode() method of a Unicode string. """ CODEC_MAP[charset] = codecname *************** *** 139,144 **** for a specific character set. It also provides convenience routines for converting between character sets, given the availability of the ! applicable codecs. Given an character set, it will do its best to provide ! information on how to use that character set in an email. Certain character sets must be encoded with quoted-printable or base64 --- 139,145 ---- for a specific character set. It also provides convenience routines for converting between character sets, given the availability of the ! applicable codecs. Given a character set, it will do its best to provide ! information on how to use that character set in an email in an ! RFC-compliant way. Certain character sets must be encoded with quoted-printable or base64 *************** *** 210,214 **** the encoding used, or it is a function in which case you should call the function with a single argument, the Message object being ! encoded. The function should then set the Content-Transfer-Encoding: header itself to whatever is appropriate. --- 211,215 ---- the encoding used, or it is a function in which case you should call the function with a single argument, the Message object being ! encoded. The function should then set the Content-Transfer-Encoding header itself to whatever is appropriate. *************** *** 236,243 **** Uses the input_codec to try and convert the string to Unicode, so it ! can be safely split on character boundaries (even for double-byte characters). ! Returns the string untouched if we don't know how to convert it to Unicode with the input_charset. --- 237,244 ---- Uses the input_codec to try and convert the string to Unicode, so it ! can be safely split on character boundaries (even for multibyte characters). ! Returns the string as-is if it isn't known how to convert it to Unicode with the input_charset. *************** *** 257,264 **** """Convert a splittable string back into an encoded string. ! Uses the proper codec to try and convert the string from ! Unicode back into an encoded format. Return the string as-is ! if it is not Unicode, or if it could not be encoded from ! Unicode. Characters that could not be converted from Unicode will be replaced --- 258,264 ---- """Convert a splittable string back into an encoded string. ! Uses the proper codec to try and convert the string from Unicode back ! into an encoded format. Return the string as-is if it is not Unicode, ! or if it could not be converted from Unicode. Characters that could not be converted from Unicode will be replaced *************** *** 283,287 **** """Return the output character set. ! This is self.output_charset if that is set, otherwise it is self.input_charset. """ --- 283,287 ---- """Return the output character set. ! This is self.output_charset if that is not None, otherwise it is self.input_charset. """ From barry@users.sourceforge.net Tue Oct 1 01:05:26 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 30 Sep 2002 17:05:26 -0700 Subject: [Python-checkins] python/dist/src/Lib/email Encoders.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv29955 Modified Files: Encoders.py Log Message: Docstring consistency with the updated .tex files. Index: Encoders.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Encoders.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Encoders.py 19 May 2002 23:44:19 -0000 1.6 --- Encoders.py 1 Oct 2002 00:05:24 -0000 1.7 *************** *** 52,56 **** """Encode the message's payload in Base64. ! Also, add an appropriate Content-Transfer-Encoding: header. """ orig = msg.get_payload() --- 52,56 ---- """Encode the message's payload in Base64. ! Also, add an appropriate Content-Transfer-Encoding header. """ orig = msg.get_payload() *************** *** 62,68 **** def encode_quopri(msg): ! """Encode the message's payload in Quoted-Printable. ! Also, add an appropriate Content-Transfer-Encoding: header. """ orig = msg.get_payload() --- 62,68 ---- def encode_quopri(msg): ! """Encode the message's payload in quoted-printable. ! Also, add an appropriate Content-Transfer-Encoding header. """ orig = msg.get_payload() *************** *** 74,78 **** def encode_7or8bit(msg): ! """Set the Content-Transfer-Encoding: header to 7bit or 8bit.""" orig = msg.get_payload() if orig is None: --- 74,78 ---- def encode_7or8bit(msg): ! """Set the Content-Transfer-Encoding header to 7bit or 8bit.""" orig = msg.get_payload() if orig is None: From barry@users.sourceforge.net Tue Oct 1 01:44:16 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 30 Sep 2002 17:44:16 -0700 Subject: [Python-checkins] python/dist/src/Lib/email Utils.py,1.19,1.20 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv11254 Modified Files: Utils.py Log Message: Docstring consistency with the updated .tex files. Index: Utils.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Utils.py,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** Utils.py 28 Sep 2002 20:49:57 -0000 1.19 --- Utils.py 1 Oct 2002 00:44:13 -0000 1.20 *************** *** 222,231 **** def make_msgid(idstring=None): ! """Returns a string suitable for RFC 2822 compliant Message-ID:, e.g: <20020201195627.33539.96671@nightshade.la.mastaler.com> Optional idstring if given is a string used to strengthen the ! uniqueness of the Message-ID, otherwise an empty string is used. """ timeval = time.time() --- 222,231 ---- def make_msgid(idstring=None): ! """Returns a string suitable for RFC 2822 compliant Message-ID, e.g: <20020201195627.33539.96671@nightshade.la.mastaler.com> Optional idstring if given is a string used to strengthen the ! uniqueness of the message id. """ timeval = time.time() *************** *** 287,297 **** def encode_rfc2231(s, charset=None, language=None): ! """Encode string according to RFC 2231""" import urllib s = urllib.quote(s, safe='') if charset is None and language is None: return s ! else: ! return "%s'%s'%s" % (charset, language, s) --- 287,303 ---- def encode_rfc2231(s, charset=None, language=None): ! """Encode string according to RFC 2231. ! ! If neither charset nor language is given, then s is returned as-is. If ! charset is given but not language, the string is encoded using the empty ! string for language. ! """ import urllib s = urllib.quote(s, safe='') if charset is None and language is None: return s ! if language is None: ! language = '' ! return "%s'%s'%s" % (charset, language, s) *************** *** 299,303 **** def decode_params(params): ! """Decode parameters list according to RFC 2231""" new_params = [] # maps parameter's name to a list of continuations --- 305,312 ---- def decode_params(params): ! """Decode parameters list according to RFC 2231. ! ! params is a sequence of 2-tuples containing (content type, string value). ! """ new_params = [] # maps parameter's name to a list of continuations From barry@users.sourceforge.net Tue Oct 1 01:51:50 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 30 Sep 2002 17:51:50 -0700 Subject: [Python-checkins] python/dist/src/Lib/email Iterators.py,1.11,1.12 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv13470 Modified Files: Iterators.py Log Message: _structure(): Swap fp and level arguments. Index: Iterators.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Iterators.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** Iterators.py 1 Sep 2002 21:04:43 -0000 1.11 --- Iterators.py 1 Oct 2002 00:51:47 -0000 1.12 *************** *** 15,19 **** ! def _structure(msg, level=0, fp=None): """A handy debugging aid""" if fp is None: --- 15,19 ---- ! def _structure(msg, fp=None, level=0): """A handy debugging aid""" if fp is None: *************** *** 23,25 **** if msg.is_multipart(): for subpart in msg.get_payload(): ! _structure(subpart, level+1, fp) --- 23,25 ---- if msg.is_multipart(): for subpart in msg.get_payload(): ! _structure(subpart, fp, level+1) From barry@users.sourceforge.net Tue Oct 1 01:52:30 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 30 Sep 2002 17:52:30 -0700 Subject: [Python-checkins] python/dist/src/Lib/email MIMEText.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv13717 Modified Files: MIMEText.py Log Message: Docstring consistency with the updated .tex files. Index: MIMEText.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/MIMEText.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** MIMEText.py 28 Sep 2002 20:27:28 -0000 1.6 --- MIMEText.py 1 Oct 2002 00:52:27 -0000 1.7 *************** *** 23,29 **** _subtype is the MIME sub content type, defaulting to "plain". ! _charset is the character set parameter added to the Content-Type: header. This defaults to "us-ascii". Note that as a side-effect, the ! Content-Transfer-Encoding: header will also be set. The use of the _encoder is deprecated. The encoding of the payload, --- 23,29 ---- _subtype is the MIME sub content type, defaulting to "plain". ! _charset is the character set parameter added to the Content-Type header. This defaults to "us-ascii". Note that as a side-effect, the ! Content-Transfer-Encoding header will also be set. The use of the _encoder is deprecated. The encoding of the payload, *************** *** 43,47 **** DeprecationWarning, 2) # Because set_payload() with a _charset will set its own ! # Content-Transfer-Encoding: header, we need to delete the # existing one or will end up with two of them. :( del self['content-transfer-encoding'] --- 43,47 ---- DeprecationWarning, 2) # Because set_payload() with a _charset will set its own ! # Content-Transfer-Encoding header, we need to delete the # existing one or will end up with two of them. :( del self['content-transfer-encoding'] From barry@users.sourceforge.net Tue Oct 1 02:05:54 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 30 Sep 2002 18:05:54 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib emailheaders.tex,NONE,1.1 emailmimebase.tex,NONE,1.1 email.tex,1.11,1.12 emailencoders.tex,1.2,1.3 emailexc.tex,1.2,1.3 emailgenerator.tex,1.3,1.4 emailiter.tex,1.2,1.3 emailmessage.tex,1.5,1.6 emailparser.tex,1.5,1.6 emailutil.tex,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv18003 Modified Files: email.tex emailencoders.tex emailexc.tex emailgenerator.tex emailiter.tex emailmessage.tex emailparser.tex emailutil.tex Added Files: emailheaders.tex emailmimebase.tex Log Message: Vast update to email version 2. This could surely use proofreading. --- NEW FILE: emailheaders.tex --- \declaremodule{standard}{email.Header} \modulesynopsis{Representing non-ASCII headers} \rfc{2822} is the base standard that describes the format of email messages. It derives from the older \rfc{822} standard which came into widespread at a time when most email was composed of \ASCII{} characters only. \rfc{2822} is a specification written assuming email contains only 7-bit \ASCII{} characters. Of course, as email has been deployed worldwide, it has become internationalized, such that language specific character sets can now be used in email messages. The base standard still requires email messages to be transfered using only 7-bit \ASCII{} characters, so a slew of RFCs have been written describing how to encode email containing non-\ASCII{} characters into \rfc{2822}-compliant format. These RFCs include \rfc{2045}, \rfc{2046}, \rfc{2047}, and \rfc{2231}. The \module{email} package supports these standards in its \module{email.Header} and \module{email.Charset} modules. If you want to include non-\ASCII{} characters in your email headers, say in the \mailheader{Subject} or \mailheader{To} fields, you should use the \class{Header} class (in module \module{email.Header} and assign the field in the \class{Message} object to an instance of \class{Header} instead of using a string for the header value. For example: \begin{verbatim} >>> from email.Message import Message >>> from email.Header import Header >>> msg = Message() >>> h = Header('p\xf6stal', 'iso-8859-1') >>> msg['Subject'] = h >>> print msg.as_string() Subject: =?iso-8859-1?q?p=F6stal?= \end{verbatim} Notice here how we wanted the \mailheader{Subject} field to contain a non-\ASCII{} character? We did this by creating a \class{Header} instance and passing in the character set that the byte string was encoded in. When the subsequent \class{Message} instance was flattened, the \mailheader{Subject} field was properly \rfc{2047} encoded. MIME-aware mail readers would show this header using the embedded ISO-8859-1 character. \versionadded{2.2.2} Here is the \class{Header} class description: \begin{classdesc}{Header}{\optional{s\optional{, charset\optional{, maxlinelen\optional{, header_name\optional{, continuation_ws}}}}}} Create a MIME-compliant header that can contain many character sets. Optional \var{s} is the initial header value. If \code{None} (the default), the initial header value is not set. You can later append to the header with \method{append()} method calls. \var{s} may be a byte string or a Unicode string, but see the \method{append()} documentation for semantics. Optional \var{charset} serves two purposes: it has the same meaning as the \var{charset} argument to the \method{append()} method. It also sets the default character set for all subsequent \method{append()} calls that omit the \var{charset} argument. If \var{charset} is not provided in the constructor (the default), the \code{us-ascii} character set is used both as \var{s}'s initial charset and as the default for subsequent \method{append()} calls. The maximum line length can be specified explicit via \var{maxlinelen}. For splitting the first line to a shorter value (to account for the field header which isn't included in \var{s}, e.g. \mailheader{Subject}) pass in the name of the field in \var{header_name}. The default \var{maxlinelen} is 76, and the default value for \var{header_name} is \code{None}, meaning it is not taken into account for the first line of a long, split header. Optional \var{continuation_ws} must be RFC 2822 compliant folding whitespace, and is usually either a space or a hard tab character. This character will be prepended to continuation lines. \end{classdesc} \begin{methoddesc}[Header]{append}{s\optional{, charset}} Append the string \var{s} to the MIME header. Optional \var{charset}, if given, should be a \class{Charset} instance (see \refmodule{email.Charset}) or the name of a character set, which will be converted to a \class{Charset} instance. A value of \code{None} (the default) means that the \var{charset} given in the constructor is used. \var{s} may be a byte string or a Unicode string. If it is a byte string (i.e. \code{isinstance(s, StringType)} is true), then \var{charset} is the encoding of that byte string, and a \exception{UnicodeError} will be raised if the string cannot be decoded with that character set. If \var{s} is a Unicode string, then \var{charset} is a hint specifying the character set of the characters in the string. In this case, when producing an \rfc{2822}-compliant header using \rfc{2047} rules, the Unicode string will be encoded using the following charsets in order: \code{us-ascii}, the \var{charset} hint, \code{utf-8}. The first character set to not provoke a \exception{UnicodeError} is used. \end{methoddesc} \begin{methoddesc}[Header]{encode}{} Encode a message header into an RFC-compliant format, possibly wrapping long lines and encapsulating non-\ASCII{} parts in base64 or quoted-printable encodings. \end{methoddesc} The \class{Header} class also provides a number of methods to support standard operators and built-in functions. \begin{methoddesc}[Header]{__str__}{} A synonym for \method{Header.encode()}. Useful for \code{str(aHeader)} calls. \end{methoddesc} \begin{methoddesc}[Header]{__unicode__}{} A helper for the built-in \function{unicode()} function. Returns the header as a Unicode string. \end{methoddesc} \begin{methoddesc}[Header]{__eq__}{other} This method allows you to compare two \class{Header} instances for equality. \end{methoddesc} \begin{methoddesc}[Header]{__ne__}{other} This method allows you to compare two \class{Header} instances for inequality. \end{methoddesc} The \module{email.Header} module also provides the following convenient functions. \begin{funcdesc}{decode_header}{header} Decode a message header value without converting the character set. The header value is in \var{header}. This function returns a list of \code{(decoded_string, charset)} pairs containing each of the decoded parts of the header. \var{charset} is \code{None} for non-encoded parts of the header, otherwise a lower case string containing the name of the character set specified in the encoded string. Here's an example: \begin{verbatim} >>> from email.Header import decode_header >>> decode_header('=?iso-8859-1?q?p=F6stal?=') [('p\\xf6stal', 'iso-8859-1')] \end{verbatim} \end{funcdesc} \begin{funcdesc}{make_header}{decoded_seq\optional{, maxlinelen\optional{, header_name\optional{, continuation_ws}}}} Create a \class{Header} instance from a sequence of pairs as returned by \function{decode_header()}. \function{decode_header()} takes a header value string and returns a sequence of pairs of the format \code{(decoded_string, charset)} where \var{charset} is the name of the character set. This function takes one of those sequence of pairs and returns a \class{Header} instance. Optional \var{maxlinelen}, \var{header_name}, and \var{continuation_ws} are as in the \class{Header} constructor. \end{funcdesc} \declaremodule{standard}{email.Charset} \modulesynopsis{Character Sets} This module provides a class \class{Charset} for representing character sets and character set conversions in email messages, as well as a character set registry and several convenience methods for manipulating this registry. Instances of \class{Charset} are used in several other modules within the \module{email} package. \versionadded{2.2.2} \begin{classdesc}{Charset}{\optional{input_charset}} Map character sets to their email properties. This class provides information about the requirements imposed on email for a specific character set. It also provides convenience routines for converting between character sets, given the availability of the applicable codecs. Given a character set, it will do its best to provide information on how to use that character set in an email message in an RFC-compliant way. Certain character sets must be encoded with quoted-printable or base64 when used in email headers or bodies. Certain character sets must be converted outright, and are not allowed in email. Optional \var{input_charset} is as described below. After being alias normalized it is also used as a lookup into the registry of character sets to find out the header encoding, body encoding, and output conversion codec to be used for the character set. For example, if \var{input_charset} is \code{iso-8859-1}, then headers and bodies will be encoded using quoted-printable and no output conversion codec is necessary. If \var{input_charset} is \code{euc-jp}, then headers will be encoded with base64, bodies will not be encoded, but output text will be converted from the \code{euc-jp} character set to the \code{iso-2022-jp} character set. \end{classdesc} \class{Charset} instances have the following data attributes: \begin{datadesc}{input_charset} The initial character set specified. Common aliases are converted to their \emph{official} email names (e.g. \code{latin_1} is converted to \code{iso-8859-1}). Defaults to 7-bit \code{us-ascii}. \end{datadesc} \begin{datadesc}{header_encoding} If the character set must be encoded before it can be used in an email header, this attribute will be set to \code{Charset.QP} (for quoted-printable), \code{Charset.BASE64} (for base64 encoding), or \code{Charset.SHORTEST} for the shortest of QP or BASE64 encoding. Otherwise, it will be \code{None}. \end{datadesc} \begin{datadesc}{body_encoding} Same as \var{header_encoding}, but describes the encoding for the mail message's body, which indeed may be different than the header encoding. \code{Charset.SHORTEST} is not allowed for \var{body_encoding}. \end{datadesc} \begin{datadesc}{output_charset} Some character sets must be converted before the can be used in email headers or bodies. If the \var{input_charset} is one of them, this attribute will contain the name of the character set output will be converted to. Otherwise, it will be \code{None}. \end{datadesc} \begin{datadesc}{input_codec} The name of the Python codec used to convert the \var{input_charset} to Unicode. If no conversion codec is necessary, this attribute will be \code{None}. \end{datadesc} \begin{datadesc}{output_codec} The name of the Python codec used to convert Unicode to the \var{output_charset}. If no conversion codec is necessary, this attribute will have the same value as the \var{input_codec}. \end{datadesc} \class{Charset} instances also have the following methods: \begin{methoddesc}[Charset]{get_body_encoding}{} Return the content transfer encoding used for body encoding. This is either the string \samp{quoted-printable} or \samp{base64} depending on the encoding used, or it is a function, in which case you should call the function with a single argument, the Message object being encoded. The function should then set the \mailheader{Content-Transfer-Encoding} header itself to whatever is appropriate. Returns the string \samp{quoted-printable} if \var{body_encoding} is \code{QP}, returns the string \samp{base64} if \var{body_encoding} is \code{BASE64}, and returns the string \samp{7bit} otherwise. \end{methoddesc} \begin{methoddesc}{convert}{s} Convert the string \var{s} from the \var{input_codec} to the \var{output_codec}. \end{methoddesc} \begin{methoddesc}{to_splittable}{s} Convert a possibly multibyte string to a safely splittable format. \var{s} is the string to split. Uses the \var{input_codec} to try and convert the string to Unicode, so it can be safely split on character boundaries (even for multibyte characters). Returns the string as-is if it isn't known how to convert \var{s} to Unicode with the \var{input_charset}. Characters that could not be converted to Unicode will be replaced with the Unicode replacement character \character{U+FFFD}. \end{methoddesc} \begin{methoddesc}{from_splittable}{ustr\optional{, to_output}} Convert a splittable string back into an encoded string. \var{ustr} is a Unicode string to ``unsplit''. This method uses the proper codec to try and convert the string from Unicode back into an encoded format. Return the string as-is if it is not Unicode, or if it could not be converted from Unicode. Characters that could not be converted from Unicode will be replaced with an appropriate character (usually \character{?}). If \var{to_output} is \code{True} (the default), uses \var{output_codec} to convert to an encoded format. If \var{to_output} is \code{False}, it uses \var{input_codec}. \end{methoddesc} \begin{methoddesc}{get_output_charset}{} Return the output character set. This is the \var{output_charset} attribute if that is not \code{None}, otherwise it is \var{input_charset}. \end{methoddesc} \begin{methoddesc}{encoded_header_len}{} Return the length of the encoded header string, properly calculating for quoted-printable or base64 encoding. \end{methoddesc} \begin{methoddesc}{header_encode}{s\optional{, convert}} Header-encode the string \var{s}. If \var{convert} is \code{True}, the string will be converted from the input charset to the output charset automatically. This is not useful for multibyte character sets, which have line length issues (multibyte characters must be split on a character, not a byte boundary); use the higher-level \class{Header} class to deal with these issues (see \refmodule{email.Header}). \var{convert} defaults to \code{False}. The type of encoding (base64 or quoted-printable) will be based on the \var{header_encoding} attribute. \end{methoddesc} \begin{methoddesc}{body_encode}{s\optional{, convert}} Body-encode the string \var{s}. If \var{convert} is \code{True} (the default), the string will be converted from the input charset to output charset automatically. Unlike \method{header_encode()}, there are no issues with byte boundaries and multibyte charsets in email bodies, so this is usually pretty safe. The type of encoding (base64 or quoted-printable) will be based on the \var{body_encoding} attribute. \end{methoddesc} The \class{Charset} class also provides a number of methods to support standard operations and built-in functions. \begin{methoddesc}[Charset]{__str__}{} Returns \var{input_charset} as a string coerced to lower case. \end{methoddesc} \begin{methoddesc}[Charset]{__eq__}{other} This method allows you to compare two \class{Charset} instances for equality. \end{methoddesc} \begin{methoddesc}[Header]{__ne__}{other} This method allows you to compare two \class{Charset} instances for inequality. \end{methoddesc} The \module{email.Charset} module also provides the following functions for adding new entries to the global character set, alias, and codec registries: \begin{funcdesc}{add_charset}{charset\optional{, header_enc\optional{, body_enc\optional{, output_charset}}}} Add character properties to the global registry. \var{charset} is the input character set, and must be the canonical name of a character set. Optional \var{header_enc} and \var{body_enc} is either \code{Charset.QP} for quoted-printable, \code{Charset.BASE64} for base64 encoding, \code{Charset.SHORTEST} for the shortest of qp or base64 encoding, or \code{None} for no encoding. \code{SHORTEST} is only valid for \var{header_enc}. It describes how message headers and message bodies in the input charset are to be encoded. Default is no encoding. Optional \var{output_charset} is the character set that the output should be in. Conversions will proceed from input charset, to Unicode, to the output charset when the method \method{Charset.convert()} is called. The default is to output in the same character set as the input. Both \var{input_charset} and \var{output_charset} must have Unicode codec entries in the module's character set-to-codec mapping; use \function{add_codec(charset, codecname)} to add codecs the module does not know about. See the \refmodule{codecs} module's documentation for more information. The global character set registry is kept in the module global dictionary \code{CHARSETS}. \end{funcdesc} \begin{funcdesc}{add_alias}{alias, canonical} Add a character set alias. \var{alias} is the alias name, e.g. \code{latin-1}. \var{canonical} is the character set's canonical name, e.g. \code{iso-8859-1}. The global charset alias registry is kept in the module global dictionary \code{ALIASES}. \end{funcdesc} \begin{funcdesc}{add_codec}{charset, codecname} Add a codec that map characters in the given character set to and from Unicode. \var{charset} is the canonical name of a character set. \var{codecname} is the name of a Python codec, as appropriate for the second argument to the \function{unicode()} built-in, or to the \method{encode()} method of a Unicode string. \end{funcdesc} --- NEW FILE: emailmimebase.tex --- Ordinarily, you get a message object structure by passing a file or some text to a parser, which parses the text and returns the root of the message object structure. However you can also build a complete object structure from scratch, or even individual \class{Message} objects by hand. In fact, you can also take an existing structure and add new \class{Message} objects, move them around, etc. This makes a very convenient interface for slicing-and-dicing MIME messages. You can create a new object structure by creating \class{Message} instances, adding attachments and all the appropriate headers manually. For MIME messages though, the \module{email} package provides some convenient subclasses to make things easier. Each of these classes should be imported from a module with the same name as the class, from within the \module{email} package. E.g.: \begin{verbatim} import email.MIMEImage.MIMEImage \end{verbatim} or \begin{verbatim} from email.MIMEText import MIMEText \end{verbatim} Here are the classes: \begin{classdesc}{MIMEBase}{_maintype, _subtype, **_params} This is the base class for all the MIME-specific subclasses of \class{Message}. Ordinarily you won't create instances specifically of \class{MIMEBase}, although you could. \class{MIMEBase} is provided primarily as a convenient base class for more specific MIME-aware subclasses. \var{_maintype} is the \mailheader{Content-Type} major type (e.g. \mimetype{text} or \mimetype{image}), and \var{_subtype} is the \mailheader{Content-Type} minor type (e.g. \mimetype{plain} or \mimetype{gif}). \var{_params} is a parameter key/value dictionary and is passed directly to \method{Message.add_header()}. The \class{MIMEBase} class always adds a \mailheader{Content-Type} header (based on \var{_maintype}, \var{_subtype}, and \var{_params}), and a \mailheader{MIME-Version} header (always set to \code{1.0}). \end{classdesc} \begin{classdesc}{MIMENonMultipart}{} A subclass of \class{MIMEBase}, this is an intermediate base class for MIME messages that are not \mimetype{multipart}. The primary purpose of this class is to prevent the use of the \method{attach()} method, which only makes sense for \mimetype{multipart} messages. If \method{attach()} is called, a \exception{MultipartConversionError} exception is raised. \versionadded{2.2.2} \end{classdesc} \begin{classdesc}{MIMEMultipart}{\optional{subtype\optional{, boundary\optional{, _subparts\optional{, _params}}}}} A subclass of \class{MIMEBase}, this is an intermediate base class for MIME messages that are \mimetype{multipart}. Optional \var{_subtype} defaults to \mimetype{mixed}, but can be used to specify the subtype of the message. A \mailheader{Content-Type} header of \mimetype{multipart/}\var{_subtype} will be added to the message object. A \mailheader{MIME-Version} header will also be added. Optional \var{boundary} is the multipart boundary string. When \code{None} (the default), the boundary is calculated when needed. \var{_subparts} is a sequence of initial subparts for the payload. It must be possible to convert this sequence to a list. You can always attach new subparts to the message by using the \method{Message.attach()} method. Additional parameters for the \mailheader{Content-Type} header are taken from the keyword arguments, or passed into the \var{_params} argument, which is a keyword dictionary. \versionadded{2.2.2} \end{classdesc} \begin{classdesc}{MIMEAudio}{_audiodata\optional{, _subtype\optional{, _encoder\optional{, **_params}}}} A subclass of \class{MIMENonMultipart}, the \class{MIMEAudio} class is used to create MIME message objects of major type \mimetype{audio}. \var{_audiodata} is a string containing the raw audio data. If this data can be decoded by the standard Python module \refmodule{sndhdr}, then the subtype will be automatically included in the \mailheader{Content-Type} header. Otherwise you can explicitly specify the audio subtype via the \var{_subtype} parameter. If the minor type could not be guessed and \var{_subtype} was not given, then \exception{TypeError} is raised. Optional \var{_encoder} is a callable (i.e. function) which will perform the actual encoding of the audio data for transport. This callable takes one argument, which is the \class{MIMEAudio} instance. It should use \method{get_payload()} and \method{set_payload()} to change the payload to encoded form. It should also add any \mailheader{Content-Transfer-Encoding} or other headers to the message object as necessary. The default encoding is \emph{Base64}. See the \refmodule{email.Encoders} module for a list of the built-in encoders. \var{_params} are passed straight through to the base class constructor. \end{classdesc} \begin{classdesc}{MIMEImage}{_imagedata\optional{, _subtype\optional{, _encoder\optional{, **_params}}}} A subclass of \class{MIMENonMultipart}, the \class{MIMEImage} class is used to create MIME message objects of major type \mimetype{image}. \var{_imagedata} is a string containing the raw image data. If this data can be decoded by the standard Python module \refmodule{imghdr}, then the subtype will be automatically included in the \mailheader{Content-Type} header. Otherwise you can explicitly specify the image subtype via the \var{_subtype} parameter. If the minor type could not be guessed and \var{_subtype} was not given, then \exception{TypeError} is raised. Optional \var{_encoder} is a callable (i.e. function) which will perform the actual encoding of the image data for transport. This callable takes one argument, which is the \class{MIMEImage} instance. It should use \method{get_payload()} and \method{set_payload()} to change the payload to encoded form. It should also add any \mailheader{Content-Transfer-Encoding} or other headers to the message object as necessary. The default encoding is \emph{Base64}. See the \refmodule{email.Encoders} module for a list of the built-in encoders. \var{_params} are passed straight through to the \class{MIMEBase} constructor. \end{classdesc} \begin{classdesc}{MIMEMessage}{_msg\optional{, _subtype}} A subclass of \class{MIMENonMultipart}, the \class{MIMEMessage} class is used to create MIME objects of main type \mimetype{message}. \var{_msg} is used as the payload, and must be an instance of class \class{Message} (or a subclass thereof), otherwise a \exception{TypeError} is raised. Optional \var{_subtype} sets the subtype of the message; it defaults to \mimetype{rfc822}. \end{classdesc} \begin{classdesc}{MIMEText}{_text\optional{, _subtype\optional{, _charset\optional{, _encoder}}}} A subclass of \class{MIMENonMultipart}, the \class{MIMEText} class is used to create MIME objects of major type \mimetype{text}. \var{_text} is the string for the payload. \var{_subtype} is the minor type and defaults to \mimetype{plain}. \var{_charset} is the character set of the text and is passed as a parameter to the \class{MIMENonMultipart} constructor; it defaults to \code{us-ascii}. No guessing or encoding is performed on the text data, but a newline is appended to \var{_text} if it doesn't already end with a newline. \deprecated{2.2.2}{The \var{_encoding} argument has been deprecated. Encoding now happens implicitly based on the \var{_charset} argument.} \end{classdesc} Index: email.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/email.tex,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** email.tex 26 Jun 2002 07:51:32 -0000 1.11 --- email.tex 1 Oct 2002 01:05:51 -0000 1.12 *************** *** 1,3 **** ! % Copyright (C) 2001 Python Software Foundation % Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! % Copyright (C) 2001,2002 Python Software Foundation % Author: barry@zope.com (Barry Warsaw) *************** *** 20,30 **** \module{mimecntl}. It is specifically \emph{not} designed to do any sending of email messages to SMTP (\rfc{2821}) servers; that is the ! function of the \refmodule{smtplib} module\footnote{For this reason, ! line endings in the \module{email} package are always native line ! endings. The \module{smtplib} module is responsible for converting ! from native line endings to \rfc{2821} line endings, just as your mail ! server would be responsible for converting from \rfc{2821} line ! endings to native line endings when it stores messages in a local ! mailbox.}. The primary distinguishing feature of the \module{email} package is --- 20,27 ---- \module{mimecntl}. It is specifically \emph{not} designed to do any sending of email messages to SMTP (\rfc{2821}) servers; that is the ! function of the \refmodule{smtplib} module. The \module{email} ! package attempts to be as RFC-compliant as possible, supporting in ! addition to \rfc{2822}, such MIME-related RFCs as ! \rfc{2045}-\rfc{2047}, and \rfc{2231}. The primary distinguishing feature of the \module{email} package is *************** *** 56,61 **** classes you might encounter while using the \module{email} package, some auxiliary utilities, and a few examples. For users of the older ! \module{mimelib} package, from which the \module{email} package is ! descended, a section on differences and porting is provided. \begin{seealso} --- 53,58 ---- classes you might encounter while using the \module{email} package, some auxiliary utilities, and a few examples. For users of the older ! \module{mimelib} package, or previous versions of the \module{email} ! package, a section on differences and porting is provided. \begin{seealso} *************** *** 73,203 **** \subsection{Creating email and MIME objects from scratch} ! Ordinarily, you get a message object tree by passing some text to a ! parser, which parses the text and returns the root of the message ! object tree. However you can also build a complete object tree from ! scratch, or even individual \class{Message} objects by hand. In fact, ! you can also take an existing tree and add new \class{Message} ! objects, move them around, etc. This makes a very convenient ! interface for slicing-and-dicing MIME messages. ! ! You can create a new object tree by creating \class{Message} ! instances, adding payloads and all the appropriate headers manually. ! For MIME messages though, the \module{email} package provides some ! convenient classes to make things easier. Each of these classes ! should be imported from a module with the same name as the class, from ! within the \module{email} package. E.g.: ! ! \begin{verbatim} ! import email.MIMEImage.MIMEImage ! \end{verbatim} ! ! or ! ! \begin{verbatim} ! from email.MIMEText import MIMEText ! \end{verbatim} ! ! Here are the classes: ! ! \begin{classdesc}{MIMEBase}{_maintype, _subtype, **_params} ! This is the base class for all the MIME-specific subclasses of ! \class{Message}. Ordinarily you won't create instances specifically ! of \class{MIMEBase}, although you could. \class{MIMEBase} is provided ! primarily as a convenient base class for more specific MIME-aware ! subclasses. ! ! \var{_maintype} is the \mailheader{Content-Type} major type ! (e.g. \mimetype{text} or \mimetype{image}), and \var{_subtype} is the ! \mailheader{Content-Type} minor type ! (e.g. \mimetype{plain} or \mimetype{gif}). \var{_params} is a parameter ! key/value dictionary and is passed directly to ! \method{Message.add_header()}. ! ! The \class{MIMEBase} class always adds a \mailheader{Content-Type} header ! (based on \var{_maintype}, \var{_subtype}, and \var{_params}), and a ! \mailheader{MIME-Version} header (always set to \code{1.0}). ! \end{classdesc} ! ! \begin{classdesc}{MIMEAudio}{_audiodata\optional{, _subtype\optional{, ! _encoder\optional{, **_params}}}} ! ! A subclass of \class{MIMEBase}, the \class{MIMEAudio} class is used to ! create MIME message objects of major type \mimetype{audio}. ! \var{_audiodata} is a string containing the raw audio data. If this ! data can be decoded by the standard Python module \refmodule{sndhdr}, ! then the subtype will be automatically included in the ! \mailheader{Content-Type} header. Otherwise you can explicitly specify the ! audio subtype via the \var{_subtype} parameter. If the minor type could ! not be guessed and \var{_subtype} was not given, then \exception{TypeError} ! is raised. ! ! Optional \var{_encoder} is a callable (i.e. function) which will ! perform the actual encoding of the audio data for transport. This ! callable takes one argument, which is the \class{MIMEAudio} instance. ! It should use \method{get_payload()} and \method{set_payload()} to ! change the payload to encoded form. It should also add any ! \mailheader{Content-Transfer-Encoding} or other headers to the message ! object as necessary. The default encoding is \emph{Base64}. See the ! \refmodule{email.Encoders} module for a list of the built-in encoders. ! ! \var{_params} are passed straight through to the \class{MIMEBase} ! constructor. ! \end{classdesc} ! ! \begin{classdesc}{MIMEImage}{_imagedata\optional{, _subtype\optional{, ! _encoder\optional{, **_params}}}} ! ! A subclass of \class{MIMEBase}, the \class{MIMEImage} class is used to ! create MIME message objects of major type \mimetype{image}. ! \var{_imagedata} is a string containing the raw image data. If this ! data can be decoded by the standard Python module \refmodule{imghdr}, ! then the subtype will be automatically included in the ! \mailheader{Content-Type} header. Otherwise you can explicitly specify the ! image subtype via the \var{_subtype} parameter. If the minor type could ! not be guessed and \var{_subtype} was not given, then \exception{TypeError} ! is raised. ! ! Optional \var{_encoder} is a callable (i.e. function) which will ! perform the actual encoding of the image data for transport. This ! callable takes one argument, which is the \class{MIMEImage} instance. ! It should use \method{get_payload()} and \method{set_payload()} to ! change the payload to encoded form. It should also add any ! \mailheader{Content-Transfer-Encoding} or other headers to the message ! object as necessary. The default encoding is \emph{Base64}. See the ! \refmodule{email.Encoders} module for a list of the built-in encoders. ! ! \var{_params} are passed straight through to the \class{MIMEBase} ! constructor. ! \end{classdesc} ! ! \begin{classdesc}{MIMEText}{_text\optional{, _subtype\optional{, ! _charset\optional{, _encoder}}}} ! ! A subclass of \class{MIMEBase}, the \class{MIMEText} class is used to ! create MIME objects of major type \mimetype{text}. \var{_text} is the ! string for the payload. \var{_subtype} is the minor type and defaults ! to \mimetype{plain}. \var{_charset} is the character set of the text and is ! passed as a parameter to the \class{MIMEBase} constructor; it defaults ! to \code{us-ascii}. No guessing or encoding is performed on the text ! data, but a newline is appended to \var{_text} if it doesn't already ! end with a newline. ! ! The \var{_encoding} argument is as with the \class{MIMEImage} class ! constructor, except that the default encoding for \class{MIMEText} ! objects is one that doesn't actually modify the payload, but does set ! the \mailheader{Content-Transfer-Encoding} header to \code{7bit} or ! \code{8bit} as appropriate. ! \end{classdesc} ! ! \begin{classdesc}{MIMEMessage}{_msg\optional{, _subtype}} ! A subclass of \class{MIMEBase}, the \class{MIMEMessage} class is used to ! create MIME objects of main type \mimetype{message}. \var{_msg} is used as ! the payload, and must be an instance of class \class{Message} (or a ! subclass thereof), otherwise a \exception{TypeError} is raised. ! ! Optional \var{_subtype} sets the subtype of the message; it defaults ! to \mimetype{rfc822}. ! \end{classdesc} \subsection{Encoders} --- 70,77 ---- \subsection{Creating email and MIME objects from scratch} + \input{emailmimebase} ! \subsection{Headers, Character sets, and Internationalization} ! \input{emailheaders} \subsection{Encoders} *************** *** 212,215 **** --- 86,160 ---- \subsection{Iterators} \input{emailiter} + + \subsection{Differences from \module{email} v1 (up to Python 2.2.1)} + + Version 1 of the \module{email} package was bundled with Python + releases up to Python 2.2.1. Version 2 was developed for the Python + 2.3 release, and backported to Python 2.2.2. It was also available as + a separate distutils based package. \module{email} version 2 is + almost entirely backwards compatible with version 1, with the + following differences: + + \begin{itemize} + \item The \module{email.Header} and \module{email.Charset} modules + have been added. + \item The pickle format for \class{Message} instances has changed. + Since this was never (and still isn't) formally defined, this + isn't considered a backwards incompatibility. However if your + application pickles and unpickles \class{Message} instances, be + aware that in \module{email} version 2, \class{Message} + instances now have private variables \var{_charset} and + \var{_default_type}. + \item Several methods in the \class{Message} class have been + deprecated, or their signatures changes. Also, many new methods + have been added. See the documentation for the \class{Message} + class for deatils. The changes should be completely backwards + compatible. + \item The object structure has changed in the face of + \mimetype{message/rfc822} content types. In \module{email} + version 1, such a type would be represented by a scalar payload, + i.e. the container message's \method{is_multipart()} returned + false, \method{get_payload()} was not a list object, and was + actually a \class{Message} instance. + + This structure was inconsistent with the rest of the package, so + the object representation for \mimetype{message/rfc822} content + types was changed. In module{email} version 2, the container + \emph{does} return \code{True} from \method{is_multipart()}, and + \method{get_payload()} returns a list containing a single + \class{Message} item. + + Note that this is one place that backwards compatibility could + not be completely maintained. However, if you're already + testing the return type of \method{get_payload()}, you should be + fine. You just need to make sure your code doesn't do a + \method{set_payload()} with a \class{Message} instance on a + container with a content type of \mimetype{message/rfc822}. + \item The \class{Parser} constructor's \var{strict} argument was + added, and its \method{parse()} and \method{parsestr()} methods + grew a \var{headersonly} argument. The \var{strict} flag was + also added to functions \function{email.message_from_file()} + and \function{email.message_from_string()}. + \item \method{Generator.__call__()} is deprecated; use + \method{Generator.flatten()} instead. The \class{Generator} + class has also grown the \method{clone()} method. + \item The \class{DecodedGenerator} class in the + \module{email.Generator} module was added. + \item The intermediate base classes \class{MIMENonMultipart} and + \class{MIMEMultipart} have been added, and interposed in the + class heirarchy for most of the other MIME-related derived + classes. + \item The \var{_encoder} argument to the \class{MIMEText} constructor + has been deprecated. Encoding now happens implicitly based + on the \var{_charset} argument. + \item The following functions in the \module{email.Utils} module have + been deprecated: \function{dump_address_pairs()}, + \function{decode()}, and \function{encode()}. The following + functions have been added to the module: + \function{make_msgid()}, \function{decode_rfc2231()}, + \function{encode_rfc2231()}, and \function{decode_params()}. + \item The non-public function \function{email.Iterators._structure()} + was added. + \end{itemize} \subsection{Differences from \module{mimelib}} Index: emailencoders.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailencoders.tex,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** emailencoders.tex 26 Sep 2001 22:21:52 -0000 1.2 --- emailencoders.tex 1 Oct 2002 01:05:52 -0000 1.3 *************** *** 18,23 **** \begin{funcdesc}{encode_quopri}{msg} ! Encodes the payload into \emph{Quoted-Printable} form and sets the ! \code{Content-Transfer-Encoding:} header to \code{quoted-printable}\footnote{Note that encoding with \method{encode_quopri()} also encodes all tabs and space characters in --- 18,23 ---- \begin{funcdesc}{encode_quopri}{msg} ! Encodes the payload into quoted-Printable form and sets the ! \mailheader{Content-Transfer-Encoding} header to \code{quoted-printable}\footnote{Note that encoding with \method{encode_quopri()} also encodes all tabs and space characters in *************** *** 28,36 **** \begin{funcdesc}{encode_base64}{msg} ! Encodes the payload into \emph{Base64} form and sets the \mailheader{Content-Transfer-Encoding} header to \code{base64}. This is a good encoding to use when most of your payload is unprintable data since it is a more compact form than ! Quoted-Printable. The drawback of Base64 encoding is that it renders the text non-human readable. \end{funcdesc} --- 28,36 ---- \begin{funcdesc}{encode_base64}{msg} ! Encodes the payload into base64 form and sets the \mailheader{Content-Transfer-Encoding} header to \code{base64}. This is a good encoding to use when most of your payload is unprintable data since it is a more compact form than ! quoted-printable. The drawback of base64 encoding is that it renders the text non-human readable. \end{funcdesc} Index: emailexc.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailexc.tex,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** emailexc.tex 26 Sep 2001 22:21:52 -0000 1.2 --- emailexc.tex 1 Oct 2002 01:05:52 -0000 1.3 *************** *** 22,26 **** \method{Parser.parsestr()} methods. ! Situations where it can be raised include finding a \emph{Unix-From} header after the first \rfc{2822} header of the message, finding a continuation line before the first \rfc{2822} header is found, or finding --- 22,26 ---- \method{Parser.parsestr()} methods. ! Situations where it can be raised include finding an envelope header after the first \rfc{2822} header of the message, finding a continuation line before the first \rfc{2822} header is found, or finding *************** *** 36,40 **** Situations where it can be raised include not being able to find the ! starting or terminating boundary in a \mimetype{multipart/*} message. \end{excclassdesc} --- 36,41 ---- Situations where it can be raised include not being able to find the ! starting or terminating boundary in a \mimetype{multipart/*} message ! when strict parsing is used. \end{excclassdesc} *************** *** 46,48 **** --- 47,54 ---- multiply inherits from \exception{MessageError} and the built-in \exception{TypeError}. + + Since \method{Message.add_payload()} is deprecated, this exception is + rarely raised in practice. However the exception may also be raised + if the \method{attach()} method is called on an instance of a class + derived from \class{MIMENonMultipart} (e.g. \class{MIMEImage}). \end{excclassdesc} Index: emailgenerator.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailgenerator.tex,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** emailgenerator.tex 5 Nov 2001 01:55:03 -0000 1.3 --- emailgenerator.tex 1 Oct 2002 01:05:52 -0000 1.4 *************** *** 1,10 **** \declaremodule{standard}{email.Generator} ! \modulesynopsis{Generate flat text email messages from a message object tree.} One of the most common tasks is to generate the flat text of the email ! message represented by a message object tree. You will need to do this if you want to send your message via the \refmodule{smtplib} module or the \refmodule{nntplib} module, or print the message on the ! console. Taking a message object tree and producing a flat text document is the job of the \class{Generator} class. --- 1,10 ---- \declaremodule{standard}{email.Generator} ! \modulesynopsis{Generate flat text email messages from a message structure.} One of the most common tasks is to generate the flat text of the email ! message represented by a message object structure. You will need to do this if you want to send your message via the \refmodule{smtplib} module or the \refmodule{nntplib} module, or print the message on the ! console. Taking a message object structure and producing a flat text document is the job of the \class{Generator} class. *************** *** 14,21 **** generate most email in a standards-compliant way, should handle MIME and non-MIME email messages just fine, and is designed so that the ! transformation from flat text, to an object tree via the ! \class{Parser} class, ! and back to flat text, is idempotent (the input is identical to the ! output). Here are the public methods of the \class{Generator} class: --- 14,20 ---- generate most email in a standards-compliant way, should handle MIME and non-MIME email messages just fine, and is designed so that the ! transformation from flat text, to a message structure via the ! \class{Parser} class, and back to flat text, is idempotent (the input ! is identical to the output). Here are the public methods of the \class{Generator} class: *************** *** 28,39 **** Python 2.0 extended print statement. ! Optional \var{mangle_from_} is a flag that, when true, puts a \samp{>} ! character in front of any line in the body that starts exactly as \samp{From } (i.e. \code{From} followed by a space at the front of the line). This is the only guaranteed portable way to avoid having such ! lines be mistaken for \emph{Unix-From} headers (see \ulink{WHY THE CONTENT-LENGTH FORMAT IS BAD} {http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html} ! for details). Optional \var{maxheaderlen} specifies the longest length for a --- 27,40 ---- Python 2.0 extended print statement. ! Optional \var{mangle_from_} is a flag that, when \code{True}, puts a ! \samp{>} character in front of any line in the body that starts exactly as \samp{From } (i.e. \code{From} followed by a space at the front of the line). This is the only guaranteed portable way to avoid having such ! lines be mistaken for a Unix mailbox format envelope header separator (see \ulink{WHY THE CONTENT-LENGTH FORMAT IS BAD} {http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html} ! for details). \var{mangle_from_} defaults to \code{True}, but you ! might want to set this to \code{False} if you are not writing Unix ! mailbox format files. Optional \var{maxheaderlen} specifies the longest length for a *************** *** 48,53 **** The other public \class{Generator} methods are: ! \begin{methoddesc}[Generator]{__call__}{msg\optional{, unixfrom}} ! Print the textual representation of the message object tree rooted at \var{msg} to the output file specified when the \class{Generator} instance was created. Sub-objects are visited depth-first and the --- 49,54 ---- The other public \class{Generator} methods are: ! \begin{methoddesc}[Generator]{flatten()}{msg\optional{, unixfrom}} ! Print the textual representation of the message object structure rooted at \var{msg} to the output file specified when the \class{Generator} instance was created. Sub-objects are visited depth-first and the *************** *** 55,65 **** Optional \var{unixfrom} is a flag that forces the printing of the ! \emph{Unix-From} (a.k.a. envelope header or \code{From_} header) ! delimiter before the first \rfc{2822} header of the root message ! object. If the root object has no \emph{Unix-From} header, a standard ! one is crafted. By default, this is set to 0 to inhibit the printing ! of the \emph{Unix-From} delimiter. ! Note that for sub-objects, no \emph{Unix-From} header is ever printed. \end{methoddesc} --- 56,74 ---- Optional \var{unixfrom} is a flag that forces the printing of the ! envelope header delimiter before the first \rfc{2822} header of the ! root message object. If the root object has no envelope header, a ! standard one is crafted. By default, this is set to \code{False} to ! inhibit the printing of the envelope delimiter. ! Note that for sub-objects, no envelope header is ever printed. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Generator]{clone}{fp} ! Return an independent clone of this \class{Generator} instance with ! the exact same options. ! ! \versionadded{2.2.2} \end{methoddesc} *************** *** 75,76 **** --- 84,131 ---- simplify the generation of a formatted string representation of a message object. For more detail, see \refmodule{email.Message}. + + The \module{email.Generator} module also provides a derived class, + called \class{DecodedGenerator} which is like the \class{Generator} + base class, except that non-\mimetype{text} parts are substituted with + a format string representing the part. + + \begin{classdesc}{DecodedGenerator}{outfp\optional{, mangle_from_\optional{, + maxheaderlen\optional{, fmt}}}} + + This class, derived from \class{Generator} walks through all the + subparts of a message. If the subpart is of main type + \mimetype{text}, then it prints the decoded payload of the subpart. + Optional \var{_mangle_from_} and \var{maxheaderlen} are as with the + \class{Generator} base class. + + If the subpart is not of main type \mimetype{text}, optional \var{fmt} + is a format string that is used instead of the message + payload. \var{fmt} is expanded with the following keywords (in + \samp{\%(keyword)s} format): + + type : Full MIME type of the non-\mimetype{text} part + maintype : Main MIME type of the non-\mimetype{text} part + subtype : Sub-MIME type of the non-\mimetype{text} part + filename : Filename of the non-\mimetype{text} part + description: Description associated with the non-\mimetype{text} part + encoding : Content transfer encoding of the non-\mimetype{text} part + + The default value for \var{fmt} is \code{None}, meaning + + \begin{verbatim} + [Non-text (%(type)s) part of message omitted, filename %(filename)s] + \end{verbatim} + + \versionadded{2.2.2} + \end{classdesc} + + \subsubsection{Deprecated methods} + + The following methods are deprecated in \module{email} version 2. + They are documented here for completeness. + + \begin{methoddesc}[Generator]{__call__}{msg\optional{, unixfrom}} + This method is identical to the \method{flatten()} method. + + \deprecated{2.2.2}{Use the \method{flatten()} method instead.} + \end{methoddesc} Index: emailiter.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailiter.tex,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** emailiter.tex 26 Sep 2001 22:21:52 -0000 1.2 --- emailiter.tex 1 Oct 2002 01:05:52 -0000 1.3 *************** *** 30,31 **** --- 30,63 ---- \end{funcdesc} + The following function has been added as a useful debugging tool. It + should \emph{not} be considered part of the supported public interface + for the package. + + \begin{funcdesc}{_structure}{msg\optional{, fp\optional{, level}}} + Prints an indented representation of the content types of the + message object structure. For example: + + \begin{verbatim} + >>> msg = email.message_from_file(somefile) + >>> _structure(msg) + multipart/mixed + text/plain + text/plain + multipart/digest + message/rfc822 + text/plain + message/rfc822 + text/plain + message/rfc822 + text/plain + message/rfc822 + text/plain + message/rfc822 + text/plain + text/plain + \end{verbatim} + + Optional \var{fp} is a file-like object to print the output to. It + must be suitable for Python's extended print statement. \var{level} + is used internally. + \end{funcdesc} Index: emailmessage.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailmessage.tex,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** emailmessage.tex 22 May 2002 20:44:03 -0000 1.5 --- emailmessage.tex 1 Oct 2002 01:05:52 -0000 1.6 *************** *** 13,22 **** Headers are stored and returned in case-preserving form but are ! matched case-insensitively. There may also be a single ! \emph{Unix-From} header, also known as the envelope header or the \code{From_} header. The payload is either a string in the case of ! simple message objects, a list of \class{Message} objects for ! multipart MIME documents, or a single \class{Message} instance for ! \mimetype{message/rfc822} type objects. \class{Message} objects provide a mapping style interface for --- 13,22 ---- Headers are stored and returned in case-preserving form but are ! matched case-insensitively. There may also be a single envelope ! header, also known as the \emph{Unix-From} header or the \code{From_} header. The payload is either a string in the case of ! simple message objects or a list of \class{Message} objects for ! MIME container documents (e.g. \mimetype{multipart/*} and ! \mimetype{message/rfc822}). \class{Message} objects provide a mapping style interface for *************** *** 36,115 **** Return the entire formatted message as a string. Optional \var{unixfrom}, when true, specifies to include the \emph{Unix-From} ! envelope header; it defaults to 0. \end{methoddesc} \begin{methoddesc}[Message]{__str__}{} ! Equivalent to \method{aMessage.as_string(unixfrom=1)}. \end{methoddesc} \begin{methoddesc}[Message]{is_multipart}{} ! Return 1 if the message's payload is a list of sub-\class{Message} ! objects, otherwise return 0. When \method{is_multipart()} returns 0, ! the payload should either be a string object, or a single ! \class{Message} instance. \end{methoddesc} \begin{methoddesc}[Message]{set_unixfrom}{unixfrom} ! Set the \emph{Unix-From} (a.k.a envelope header or \code{From_} ! header) to \var{unixfrom}, which should be a string. \end{methoddesc} \begin{methoddesc}[Message]{get_unixfrom}{} ! Return the \emph{Unix-From} header. Defaults to \code{None} if the ! \emph{Unix-From} header was never set. ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{add_payload}{payload} ! Add \var{payload} to the message object's existing payload. If, prior ! to calling this method, the object's payload was \code{None} ! (i.e. never before set), then after this method is called, the payload ! will be the argument \var{payload}. ! ! If the object's payload was already a list ! (i.e. \method{is_multipart()} returns 1), then \var{payload} is ! appended to the end of the existing payload list. ! ! For any other type of existing payload, \method{add_payload()} will ! transform the new payload into a list consisting of the old payload ! and \var{payload}, but only if the document is already a MIME ! multipart document. This condition is satisfied if the message's ! \mailheader{Content-Type} header's main type is either ! \mimetype{multipart}, or there is no \mailheader{Content-Type} ! header. In any other situation, ! \exception{MultipartConversionError} is raised. \end{methoddesc} \begin{methoddesc}[Message]{attach}{payload} ! Synonymous with \method{add_payload()}. \end{methoddesc} \begin{methoddesc}[Message]{get_payload}{\optional{i\optional{, decode}}} ! Return the current payload, which will be a list of \class{Message} ! objects when \method{is_multipart()} returns 1, or a scalar (either a ! string or a single \class{Message} instance) when ! \method{is_multipart()} returns 0. ! With optional \var{i}, \method{get_payload()} will return the \var{i}-th element of the payload, counting from zero, if ! \method{is_multipart()} returns 1. An \exception{IndexError} will be raised ! if \var{i} is less than 0 or greater than or equal to the number of ! items in the payload. If the payload is scalar ! (i.e. \method{is_multipart()} returns 0) and \var{i} is given, a \exception{TypeError} is raised. Optional \var{decode} is a flag indicating whether the payload should be decoded or not, according to the \mailheader{Content-Transfer-Encoding} header. ! When true and the message is not a multipart, the payload will be decoded if this header's value is \samp{quoted-printable} or \samp{base64}. If some other encoding is used, or \mailheader{Content-Transfer-Encoding} header is missing, the payload is returned as-is (undecoded). If the message is ! a multipart and the \var{decode} flag is true, then \code{None} is ! returned. \end{methoddesc} ! \begin{methoddesc}[Message]{set_payload}{payload} Set the entire message object's payload to \var{payload}. It is the ! client's responsibility to ensure the payload invariants. \end{methoddesc} --- 36,129 ---- Return the entire formatted message as a string. Optional \var{unixfrom}, when true, specifies to include the \emph{Unix-From} ! envelope header; it defaults to \code{False}. \end{methoddesc} \begin{methoddesc}[Message]{__str__}{} ! Equivalent to \method{aMessage.as_string(unixfrom=True)}. \end{methoddesc} \begin{methoddesc}[Message]{is_multipart}{} ! Return \code{True} if the message's payload is a list of ! sub-\class{Message} objects, otherwise return \code{False}. When ! \method{is_multipart()} returns False, the payload should be a string ! object. \end{methoddesc} \begin{methoddesc}[Message]{set_unixfrom}{unixfrom} ! Set the message's envelope header to \var{unixfrom}, which should be a string. \end{methoddesc} \begin{methoddesc}[Message]{get_unixfrom}{} ! Return the message's envelope header. Defaults to \code{None} if the ! envelope header was never set. \end{methoddesc} \begin{methoddesc}[Message]{attach}{payload} ! Add the given payload to the current payload, which must be ! \code{None} or a list of \class{Message} objects before the call. ! After the call, the payload will always be a list of \class{Message} ! objects. If you want to set the payload to a scalar object (e.g. a ! string), use \method{set_payload()} instead. \end{methoddesc} \begin{methoddesc}[Message]{get_payload}{\optional{i\optional{, decode}}} ! Return a reference the current payload, which will be a list of ! \class{Message} objects when \method{is_multipart()} is \code{True}, or a ! string when \method{is_multipart()} is \code{False}. If the ! payload is a list and you mutate the list object, you modify the ! message's payload in place. ! With optional argument \var{i}, \method{get_payload()} will return the \var{i}-th element of the payload, counting from zero, if ! \method{is_multipart()} is \code{True}. An \exception{IndexError} ! will be raised if \var{i} is less than 0 or greater than or equal to ! the number of items in the payload. If the payload is a string ! (i.e. \method{is_multipart()} is \code{False}) and \var{i} is given, a \exception{TypeError} is raised. Optional \var{decode} is a flag indicating whether the payload should be decoded or not, according to the \mailheader{Content-Transfer-Encoding} header. ! When \code{True} and the message is not a multipart, the payload will be decoded if this header's value is \samp{quoted-printable} or \samp{base64}. If some other encoding is used, or \mailheader{Content-Transfer-Encoding} header is missing, the payload is returned as-is (undecoded). If the message is ! a multipart and the \var{decode} flag is \code{True}, then \code{None} is ! returned. The default for \var{decode} is \code{False}. \end{methoddesc} ! \begin{methoddesc}[Message]{set_payload}{payload\optional{, charset}} Set the entire message object's payload to \var{payload}. It is the ! client's responsibility to ensure the payload invariants. Optional ! \var{charset} sets the message's default character set (see ! \method{set_charset()} for details. ! ! \versionchanged[\var{charset} argument added]{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{set_charset}{charset} ! Set the character set of the payload to \var{charset}, which can ! either be a \class{Charset} instance (see \refmodule{email.Charset}, a ! string naming a character set, ! or \code{None}. If it is a string, it will be converted to a ! \class{Charset} instance. If \var{charset} is \code{None}, the ! \code{charset} parameter will be removed from the ! \mailheader{Content-Type} header. Anything else will generate a ! \exception{TypeError}. ! ! The message will be assumed to be of type \mimetype{text/*} encoded with ! \code{charset.input_charset}. It will be converted to ! \code{charset.output_charset} ! and encoded properly, if needed, when generating the plain text ! representation of the message. MIME headers ! (\mailheader{MIME-Version}, \mailheader{Content-Type}, ! \mailheader{Content-Transfer-Encoding}) will be added as needed. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{get_charset}{} ! Return the \class{Charset} instance associated with the message's payload. ! \versionadded{2.2.2} \end{methoddesc} *************** *** 124,129 **** toward maximal convenience. ! Note that in all cases, any optional \emph{Unix-From} header the message ! may have is not included in the mapping interface. \begin{methoddesc}[Message]{__len__}{} --- 138,143 ---- toward maximal convenience. ! Note that in all cases, any envelope header present in the message is ! not included in the mapping interface. \begin{methoddesc}[Message]{__len__}{} *************** *** 178,207 **** \begin{methoddesc}[Message]{has_key}{name} ! Return 1 if the message contains a header field named \var{name}, ! otherwise return 0. \end{methoddesc} \begin{methoddesc}[Message]{keys}{} Return a list of all the message's header field names. These keys ! will be sorted in the order in which they were added to the message ! via \method{__setitem__()}, and may contain duplicates. Any fields ! deleted and then subsequently re-added are always appended to the end ! of the header list. \end{methoddesc} \begin{methoddesc}[Message]{values}{} Return a list of all the message's field values. These will be sorted ! in the order in which they were added to the message via ! \method{__setitem__()}, and may contain duplicates. Any fields ! deleted and then subsequently re-added are always appended to the end ! of the header list. \end{methoddesc} \begin{methoddesc}[Message]{items}{} ! Return a list of 2-tuples containing all the message's field headers and ! values. These will be sorted in the order in which they were added to ! the message via \method{__setitem__()}, and may contain duplicates. ! Any fields deleted and then subsequently re-added are always appended ! to the end of the header list. \end{methoddesc} --- 192,221 ---- \begin{methoddesc}[Message]{has_key}{name} ! Return true if the message contains a header field named \var{name}, ! otherwise return false. \end{methoddesc} \begin{methoddesc}[Message]{keys}{} Return a list of all the message's header field names. These keys ! will be sorted in the order in which they appeared in the original ! message, or were added to the message and may contain ! duplicates. Any fields deleted and then subsequently re-added are ! always appended to the end of the header list. \end{methoddesc} \begin{methoddesc}[Message]{values}{} Return a list of all the message's field values. These will be sorted ! in the order in which they appeared in the original message, or were ! added to the message, and may contain ! duplicates. Any fields deleted and then subsequently re-added are ! always appended to the end of the header list. \end{methoddesc} \begin{methoddesc}[Message]{items}{} ! Return a list of 2-tuples containing all the message's field headers ! and values. These will be sorted in the order in which they appeared ! in the original message, or were added to the message, and may contain ! duplicates. Any fields deleted and then subsequently re-added are ! always appended to the end of the header list. \end{methoddesc} *************** *** 216,223 **** \begin{methoddesc}[Message]{get_all}{name\optional{, failobj}} Return a list of all the values for the field named \var{name}. These ! will be sorted in the order in which they were added to the message ! via \method{__setitem__()}. Any fields ! deleted and then subsequently re-added are always appended to the end ! of the list. If there are no such named headers in the message, \var{failobj} is --- 230,236 ---- \begin{methoddesc}[Message]{get_all}{name\optional{, failobj}} Return a list of all the values for the field named \var{name}. These ! will be sorted in the order in which they appeared in the original ! message, or were added to the message. Any fields deleted and then ! subsequently re-added are always appended to the end of the list. If there are no such named headers in the message, \var{failobj} is *************** *** 228,233 **** Extended header setting. This method is similar to \method{__setitem__()} except that additional header parameters can be ! provided as keyword arguments. \var{_name} is the header to set and ! \var{_value} is the \emph{primary} value for the header. For each item in the keyword argument dictionary \var{_params}, the --- 241,246 ---- Extended header setting. This method is similar to \method{__setitem__()} except that additional header parameters can be ! provided as keyword arguments. \var{_name} is the header field to add ! and \var{_value} is the \emph{primary} value for the header. For each item in the keyword argument dictionary \var{_params}, the *************** *** 250,276 **** \end{methoddesc} ! \begin{methoddesc}[Message]{get_type}{\optional{failobj}} ! Return the message's content type, as a string of the form ! \mimetype{maintype/subtype} as taken from the ! \mailheader{Content-Type} header. ! The returned string is coerced to lowercase. ! If there is no \mailheader{Content-Type} header in the message, ! \var{failobj} is returned (defaults to \code{None}). \end{methoddesc} ! \begin{methoddesc}[Message]{get_main_type}{\optional{failobj}} ! Return the message's \emph{main} content type. This essentially returns the ! \var{maintype} part of the string returned by \method{get_type()}, with the ! same semantics for \var{failobj}. \end{methoddesc} ! \begin{methoddesc}[Message]{get_subtype}{\optional{failobj}} ! Return the message's sub-content type. This essentially returns the ! \var{subtype} part of the string returned by \method{get_type()}, with the ! same semantics for \var{failobj}. \end{methoddesc} ! \begin{methoddesc}[Message]{get_params}{\optional{failobj\optional{, header}}} Return the message's \mailheader{Content-Type} parameters, as a list. The elements of the returned list are 2-tuples of key/value pairs, as --- 263,327 ---- \end{methoddesc} ! \begin{methoddesc}[Message]{replace_header}{_name, _value} ! Replace a header. Replace the first header found in the message that ! matches \var{_name}, retaining header order and field name case. If ! no matching header was found, a \exception{KeyError} is raised. ! \versionadded{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Message]{get_content_type}{} ! Return the message's content type. The returned string is coerced to ! lower case of the form \mimetype{maintype/subtype}. If there was no ! \mailheader{Content-Type} header in the message the default type as ! given by \method{get_default_type()} will be returned. Since ! according to \rfc{2045}, messages always have a default type, ! \method{get_content_type()} will always return a value. ! ! \rfc{2045} defines a message's default type to be ! \mimetype{text/plain} unless it appears inside a ! \mimetype{multipart/digest} container, in which case it would be ! \mimetype{message/rfc822}. If the \mailheader{Content-Type} header ! has an invalid type specification, \rfc{2045} mandates that the ! default type be \mimetype{text/plain}. ! ! \versionadded{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Message]{get_content_maintype}{} ! Return the message's main content type. This is the ! \mimetype{maintype} part of the string returned by ! \method{get_content_type()}. ! ! \versionadded{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Message]{get_content_subtype}{} ! Return the message's sub-content type. This is the \mimetype{subtype} ! part of the string returned by \method{get_content_type()}. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{get_default_type}{} ! Return the default content type. Most messages have a default content ! type of \mimetype{text/plain}, except for messages that are subparts ! of \mimetype{multipart/digest} containers. Such subparts have a ! default content type of \mimetype{message/rfc822}. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{set_default_type}{ctype} ! Set the default content type. \var{ctype} should either be ! \mimetype{text/plain} or \mimetype{message/rfc822}, although this is ! not enforced. The default content type is not stored in the ! \mailheader{Content-Type} header. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{get_params}{\optional{failobj\optional{, ! header\optional{, unquote}}}} Return the message's \mailheader{Content-Type} parameters, as a list. The elements of the returned list are 2-tuples of key/value pairs, as *************** *** 278,290 **** \character{=} is the key, while the right hand side is the value. If there is no \character{=} sign in the parameter the value is the empty ! string. The value is always unquoted with \method{Utils.unquote()}. Optional \var{failobj} is the object to return if there is no \mailheader{Content-Type} header. Optional \var{header} is the header to search instead of \mailheader{Content-Type}. \end{methoddesc} \begin{methoddesc}[Message]{get_param}{param\optional{, ! failobj\optional{, header}}} Return the value of the \mailheader{Content-Type} header's parameter \var{param} as a string. If the message has no \mailheader{Content-Type} --- 329,344 ---- \character{=} is the key, while the right hand side is the value. If there is no \character{=} sign in the parameter the value is the empty ! string, otherwise the value is as described in \method{get_param()} and is ! unquoted if optional \var{unquote} is \code{True} (the default). Optional \var{failobj} is the object to return if there is no \mailheader{Content-Type} header. Optional \var{header} is the header to search instead of \mailheader{Content-Type}. + + \versionchanged[\var{unquote} argument added]{2.2.2} \end{methoddesc} \begin{methoddesc}[Message]{get_param}{param\optional{, ! failobj\optional{, header\optional{, unquote}}}} Return the value of the \mailheader{Content-Type} header's parameter \var{param} as a string. If the message has no \mailheader{Content-Type} *************** *** 294,311 **** Optional \var{header} if given, specifies the message header to use instead of \mailheader{Content-Type}. \end{methoddesc} ! \begin{methoddesc}[Message]{get_charsets}{\optional{failobj}} ! Return a list containing the character set names in the message. If ! the message is a \mimetype{multipart}, then the list will contain one ! element for each subpart in the payload, otherwise, it will be a list ! of length 1. ! Each item in the list will be a string which is the value of the ! \code{charset} parameter in the \mailheader{Content-Type} header for the ! represented subpart. However, if the subpart has no ! \mailheader{Content-Type} header, no \code{charset} parameter, or is not of ! the \mimetype{text} main MIME type, then that item in the returned list ! will be \var{failobj}. \end{methoddesc} --- 348,425 ---- Optional \var{header} if given, specifies the message header to use instead of \mailheader{Content-Type}. + + Parameter keys are always compared case insensitively. The return + value can either be a string, or a 3-tuple if the parameter was + \rfc{2231} encoded. When it's a 3-tuple, the elements of the value are of + the form \samp{(CHARSET, LANGUAGE, VALUE)}, where \var{LANGUAGE} may + be the empty string. Your application should be prepared to deal with + 3-tuple return values, which it can convert the parameter to a Unicode + string like so: + + \begin{verbatim} + param = msg.get_param('foo') + if isinstance(param, tuple): + param = unicode(param[2], param[0]) + \end{verbatim} + + In any case, the parameter value (either the returned string, or the + \var{VALUE} item in the 3-tuple) is always unquoted, unless + \var{unquote} is set to \code{False}. + + \versionchanged[\var{unquote} argument added, and 3-tuple return value + possible]{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Message]{set_param}{param, value\optional{, ! header\optional{, requote\optional{, charset\optional{, language}}}}} ! Set a parameter in the \mailheader{Content-Type} header. If the ! parameter already exists in the header, its value will be replaced ! with \var{value}. If the \mailheader{Content-Type} header as not yet ! been defined for this message, it will be set to \mimetype{text/plain} ! and the new parameter value will be appended as per \rfc{2045}. ! ! Optional \var{header} specifies an alternative header to ! \mailheader{Content-Type}, and all parameters will be quoted as ! necessary unless optional \var{requote} is \code{False} (the default ! is \code{True}). ! ! If optional \var{charset} is specified, the parameter will be encoded ! according to \rfc{2231}. Optional \var{language} specifies the RFC ! 2231 language, defaulting to the empty string. Both \var{charset} and ! \var{language} should be strings. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{del_param}{param\optional{, header\optional{, ! requote}}} ! Remove the given parameter completely from the ! \mailheader{Content-Type} header. The header will be re-written in ! place without the parameter or its value. All values will be quoted ! as necessary unless \var{requote} is \code{False} (the default is ! \code{True}). Optional \var{header} specifies an alterative to ! \mailheader{Content-Type}. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{set_type}{type\optional{, header}\optional{, ! requote}} ! Set the main type and subtype for the \mailheader{Content-Type} ! header. \var{type} must be a string in the form ! \mimetype{maintype/subtype}, otherwise a \exception{ValueError} is ! raised. ! ! This method replaces the \mailheader{Content-Type} header, keeping all ! the parameters in place. If \var{requote} is \code{False}, this ! leaves the existing header's quoting as is, otherwise the parameters ! will be quoted (the default). ! ! An alternative header can be specified in the \var{header} argument. ! When the \mailheader{Content-Type} header is set, we'll always also ! add a \mailheader{MIME-Version} header. ! ! \versionadded{2.2.2} \end{methoddesc} *************** *** 341,344 **** --- 455,484 ---- \end{methoddesc} + \begin{methoddesc}[Message]{get_content_charset}{\optional{failobj}} + Return the \code{charset} parameter of the \mailheader{Content-Type} + header. If there is no \mailheader{Content-Type} header, or if that + header has no \code{charset} parameter, \var{failobj} is returned. + + Note that this method differs from \method{get_charset} which returns + the \class{Charset} instance for the default encoding of the message + body. + + \versionadded{2.2.2} + \end{methoddesc} + + \begin{methoddesc}[Message]{get_charsets}{\optional{failobj}} + Return a list containing the character set names in the message. If + the message is a \mimetype{multipart}, then the list will contain one + element for each subpart in the payload, otherwise, it will be a list + of length 1. + + Each item in the list will be a string which is the value of the + \code{charset} parameter in the \mailheader{Content-Type} header for the + represented subpart. However, if the subpart has no + \mailheader{Content-Type} header, no \code{charset} parameter, or is not of + the \mimetype{text} main MIME type, then that item in the returned list + will be \var{failobj}. + \end{methoddesc} + \begin{methoddesc}[Message]{walk}{} The \method{walk()} method is an all-purpose generator which can be *************** *** 381,385 **** is writing out the plain text representation of a MIME message, and it finds the message has a \var{preamble} attribute, it will write this ! text in the area between the headers and the first boundary. Note that if the message object has no preamble, the --- 521,526 ---- is writing out the plain text representation of a MIME message, and it finds the message has a \var{preamble} attribute, it will write this ! text in the area between the headers and the first boundary. See ! \refmodule{email.Parser} and \refmodule{email.Generator} for details. Note that if the message object has no preamble, the *************** *** 402,403 **** --- 543,600 ---- set the \var{epilogue} to the empty string. \end{datadesc} + + \subsubsection{Deprecated methods} + + The following methods are deprecated in \module{email} version 2. + They are documented here for completeness. + + \begin{methoddesc}[Message]{add_payload}{payload} + Add \var{payload} to the message object's existing payload. If, prior + to calling this method, the object's payload was \code{None} + (i.e. never before set), then after this method is called, the payload + will be the argument \var{payload}. + + If the object's payload was already a list + (i.e. \method{is_multipart()} returns 1), then \var{payload} is + appended to the end of the existing payload list. + + For any other type of existing payload, \method{add_payload()} will + transform the new payload into a list consisting of the old payload + and \var{payload}, but only if the document is already a MIME + multipart document. This condition is satisfied if the message's + \mailheader{Content-Type} header's main type is either + \mimetype{multipart}, or there is no \mailheader{Content-Type} + header. In any other situation, + \exception{MultipartConversionError} is raised. + + \deprecated{2.2.2}{Use the \method{attach()} method instead.} + \end{methoddesc} + + \begin{methoddesc}[Message]{get_type}{\optional{failobj}} + Return the message's content type, as a string of the form + \mimetype{maintype/subtype} as taken from the + \mailheader{Content-Type} header. + The returned string is coerced to lowercase. + + If there is no \mailheader{Content-Type} header in the message, + \var{failobj} is returned (defaults to \code{None}). + + \deprecated{2.2.2}{Use the \method{get_content_type()} method instead.} + \end{methoddesc} + + \begin{methoddesc}[Message]{get_main_type}{\optional{failobj}} + Return the message's \emph{main} content type. This essentially returns the + \var{maintype} part of the string returned by \method{get_type()}, with the + same semantics for \var{failobj}. + + \deprecated{2.2.2}{Use the \method{get_content_maintype()} method instead.} + \end{methoddesc} + + \begin{methoddesc}[Message]{get_subtype}{\optional{failobj}} + Return the message's sub-content type. This essentially returns the + \var{subtype} part of the string returned by \method{get_type()}, with the + same semantics for \var{failobj}. + + \deprecated{2.2.2}{Use the \method{get_content_subtype()} method instead.} + \end{methoddesc} + Index: emailparser.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailparser.tex,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** emailparser.tex 22 Feb 2002 21:24:32 -0000 1.5 --- emailparser.tex 1 Oct 2002 01:05:52 -0000 1.6 *************** *** 1,9 **** \declaremodule{standard}{email.Parser} \modulesynopsis{Parse flat text email messages to produce a message ! object tree.} ! Message object trees can be created in one of two ways: they can be created from whole cloth by instantiating \class{Message} objects and ! stringing them together via \method{add_payload()} and \method{set_payload()} calls, or they can be created by parsing a flat text representation of the email message. --- 1,9 ---- \declaremodule{standard}{email.Parser} \modulesynopsis{Parse flat text email messages to produce a message ! object structure.} ! Message object structures can be created in one of two ways: they can be created from whole cloth by instantiating \class{Message} objects and ! stringing them together via \method{attach()} and \method{set_payload()} calls, or they can be created by parsing a flat text representation of the email message. *************** *** 12,19 **** most email document structures, including MIME documents. You can pass the parser a string or a file object, and the parser will return ! to you the root \class{Message} instance of the object tree. For simple, non-MIME messages the payload of this root object will likely be a string containing the text of the message. For MIME ! messages, the root object will return true from its \method{is_multipart()} method, and the subparts can be accessed via the \method{get_payload()} and \method{walk()} methods. --- 12,19 ---- most email document structures, including MIME documents. You can pass the parser a string or a file object, and the parser will return ! to you the root \class{Message} instance of the object structure. For simple, non-MIME messages the payload of this root object will likely be a string containing the text of the message. For MIME ! messages, the root object will return \code{True} from its \method{is_multipart()} method, and the subparts can be accessed via the \method{get_payload()} and \method{walk()} methods. *************** *** 28,43 **** headers and the payload of the message. In the case of \mimetype{multipart} messages, it will recursively parse the body of ! the container message. The \module{email.Parser} module also provides ! a second class, called \class{HeaderParser} which can be used if ! you're only interested in the headers of the message. ! \class{HeaderParser} can be much faster in this situations, since it ! does not attempt to parse the message body, instead setting the ! payload to the raw body as a string. \class{HeaderParser} has the ! same API as the \class{Parser} class. \subsubsection{Parser class API} ! \begin{classdesc}{Parser}{\optional{_class}} ! The constructor for the \class{Parser} class takes a single optional argument \var{_class}. This must be a callable factory (such as a function or a class), and it is used whenever a sub-message object --- 28,47 ---- headers and the payload of the message. In the case of \mimetype{multipart} messages, it will recursively parse the body of ! the container message. Two modes of parsing are supported, ! \emph{strict} parsing, which will usually reject any non-RFC compliant ! message, and \emph{lax} parsing, which attempts to adjust for common ! MIME formatting problems. ! ! The \module{email.Parser} module also provides a second class, called ! \class{HeaderParser} which can be used if you're only interested in ! the headers of the message. \class{HeaderParser} can be much faster in ! these situations, since it does not attempt to parse the message body, ! instead setting the payload to the raw body as a string. ! \class{HeaderParser} has the same API as the \class{Parser} class. \subsubsection{Parser class API} ! \begin{classdesc}{Parser}{\optional{_class\optional{, strict}}} ! The constructor for the \class{Parser} class takes an optional argument \var{_class}. This must be a callable factory (such as a function or a class), and it is used whenever a sub-message object *************** *** 45,53 **** \refmodule{email.Message}). The factory will be called without arguments. \end{classdesc} The other public \class{Parser} methods are: ! \begin{methoddesc}[Parser]{parse}{fp} Read all the data from the file-like object \var{fp}, parse the resulting text, and return the root message object. \var{fp} must --- 49,71 ---- \refmodule{email.Message}). The factory will be called without arguments. + + The optional \var{strict} flag specifies whether strict or lax parsing + should be performed. Normally, when things like MIME terminating + boundaries are missing, or when messages contain other formatting + problems, the \class{Parser} will raise a + \exception{MessageParseError}. However, when lax parsing is enabled, + the \class{Parser} will attempt to workaround such broken formatting + to produce a usable message structure (this doesn't mean + \exception{MessageParseError}s are never raised; some ill-formatted + messages just can't be parsed). The \var{strict} flag defaults to + \code{False} since lax parsing usually provides the most convenient + behavior. + + \versionchanged[The \var{strict} flag was added]{2.2.2} \end{classdesc} The other public \class{Parser} methods are: ! \begin{methoddesc}[Parser]{parse}{fp\optional{, headersonly}} Read all the data from the file-like object \var{fp}, parse the resulting text, and return the root message object. \var{fp} must *************** *** 57,86 **** The text contained in \var{fp} must be formatted as a block of \rfc{2822} style headers and header continuation lines, optionally preceeded by a ! \emph{Unix-From} header. The header block is terminated either by the end of the data or by a blank line. Following the header block is the body of the message (which may contain MIME-encoded subparts). \end{methoddesc} ! \begin{methoddesc}[Parser]{parsestr}{text} Similar to the \method{parse()} method, except it takes a string object instead of a file-like object. Calling this method on a string is exactly equivalent to wrapping \var{text} in a \class{StringIO} instance first and calling \method{parse()}. \end{methoddesc} ! Since creating a message object tree from a string or a file object is ! such a common task, two functions are provided as a convenience. They ! are available in the top-level \module{email} package namespace. ! \begin{funcdesc}{message_from_string}{s\optional{, _class}} Return a message object tree from a string. This is exactly ! equivalent to \code{Parser().parsestr(s)}. Optional \var{_class} is ! interpreted as with the \class{Parser} class constructor. \end{funcdesc} ! \begin{funcdesc}{message_from_file}{fp\optional{, _class}} Return a message object tree from an open file object. This is exactly ! equivalent to \code{Parser().parse(fp)}. Optional \var{_class} is ! interpreted as with the \class{Parser} class constructor. \end{funcdesc} --- 75,121 ---- The text contained in \var{fp} must be formatted as a block of \rfc{2822} style headers and header continuation lines, optionally preceeded by a ! envelope header. The header block is terminated either by the end of the data or by a blank line. Following the header block is the body of the message (which may contain MIME-encoded subparts). + + Optional \var{headersonly} is a flag specifying whether to stop + parsing after reading the headers or not. The default is \code{False}, + meaning it parses the entire contents of the file. + + \versionchanged[The \var{headersonly} flag was added]{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Parser]{parsestr}{text\optional{, headersonly}} Similar to the \method{parse()} method, except it takes a string object instead of a file-like object. Calling this method on a string is exactly equivalent to wrapping \var{text} in a \class{StringIO} instance first and calling \method{parse()}. + + Optional \var{headersonly} is a flag specifying whether to stop + parsing after reading the headers or not. The default is \code{False}, + meaning it parses the entire contents of the file. + + \versionchanged[The \var{headersonly} flag was added]{2.2.2} \end{methoddesc} ! Since creating a message object structure from a string or a file ! object is such a common task, two functions are provided as a ! convenience. They are available in the top-level \module{email} ! package namespace. ! \begin{funcdesc}{message_from_string}{s\optional{, _class\optional{, strict}}} Return a message object tree from a string. This is exactly ! equivalent to \code{Parser().parsestr(s)}. Optional \var{_class} and ! \var{strict} are interpreted as with the \class{Parser} class constructor. ! ! \versionchanged[The \var{strict} flag was added]{2.2.2} \end{funcdesc} ! \begin{funcdesc}{message_from_file}{fp\optional{, _class\optional{, strict}}} Return a message object tree from an open file object. This is exactly ! equivalent to \code{Parser().parse(fp)}. Optional \var{_class} and ! \var{strict} are interpreted as with the \class{Parser} class constructor. ! ! \versionchanged[The \var{strict} flag was added]{2.2.2} \end{funcdesc} *************** *** 100,113 **** \item Most non-\mimetype{multipart} type messages are parsed as a single message object with a string payload. These objects will return ! 0 for \method{is_multipart()}. ! \item One exception is for \mimetype{message/delivery-status} type ! messages. Because the body of such messages consist of ! blocks of headers, \class{Parser} will create a non-multipart ! object containing non-multipart subobjects for each header ! block. ! \item Another exception is for \mimetype{message/*} types (more ! general than \mimetype{message/delivery-status}). These are ! typically \mimetype{message/rfc822} messages, represented as a ! non-multipart object containing a singleton payload which is ! another non-multipart \class{Message} instance. \end{itemize} --- 135,150 ---- \item Most non-\mimetype{multipart} type messages are parsed as a single message object with a string payload. These objects will return ! \code{False} for \method{is_multipart()}. Their ! \method{get_payload()} method will return a string object. ! \item All \mimetype{multipart} type messages will be parsed as a ! container message object with a list of sub-message objects for ! their payload. These messages will return \code{True} for ! \method{is_multipart()} and their \method{get_payload()} method ! will return a list of \class{Message} instances. ! \item Most messages with a content type of \mimetype{message/*} ! (e.g. \mimetype{message/deliver-status} and ! \mimetype{message/rfc822}) will also be parsed as container ! object containing a list payload of length 1. Their ! \method{is_multipart()} method will return \code{True}. The ! single element in the list payload will be a sub-message object. \end{itemize} Index: emailutil.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailutil.tex,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** emailutil.tex 22 May 2002 01:22:46 -0000 1.6 --- emailutil.tex 1 Oct 2002 01:05:52 -0000 1.7 *************** *** 22,29 **** \emph{realname} and \emph{email address} parts. Returns a tuple of that information, unless the parse fails, in which case a 2-tuple of ! \code{(None, None)} is returned. \end{funcdesc} ! \begin{funcdesc}{dump_address_pair}{pair} The inverse of \method{parseaddr()}, this takes a 2-tuple of the form \code{(realname, email_address)} and returns the string value suitable --- 22,29 ---- \emph{realname} and \emph{email address} parts. Returns a tuple of that information, unless the parse fails, in which case a 2-tuple of ! \code{('', '')} is returned. \end{funcdesc} ! \begin{funcdesc}{formataddr}{pair} The inverse of \method{parseaddr()}, this takes a 2-tuple of the form \code{(realname, email_address)} and returns the string value suitable *************** *** 49,73 **** \end{funcdesc} - \begin{funcdesc}{decode}{s} - This method decodes a string according to the rules in \rfc{2047}. It - returns the decoded string as a Python unicode string. - \end{funcdesc} - - \begin{funcdesc}{encode}{s\optional{, charset\optional{, encoding}}} - This method encodes a string according to the rules in \rfc{2047}. It - is not actually the inverse of \function{decode()} since it doesn't - handle multiple character sets or multiple string parts needing - encoding. In fact, the input string \var{s} must already be encoded - in the \var{charset} character set (Python can't reliably guess what - character set a string might be encoded in). The default - \var{charset} is \samp{iso-8859-1}. - - \var{encoding} must be either the letter \character{q} for - Quoted-Printable or \character{b} for Base64 encoding. If - neither, a \exception{ValueError} is raised. Both the \var{charset} and - the \var{encoding} strings are case-insensitive, and coerced to lower - case in the returned string. - \end{funcdesc} - \begin{funcdesc}{parsedate}{date} Attempts to parse a date according to the rules in \rfc{2822}. --- 49,52 ---- *************** *** 117,122 **** otherwise the current time is used. ! Optional \var{localtime} is a flag that when true, interprets \var{timeval}, and returns a date relative to the local timezone instead of UTC, properly taking daylight savings time into account. \end{funcdesc} --- 96,142 ---- otherwise the current time is used. ! Optional \var{localtime} is a flag that when \code{True}, interprets \var{timeval}, and returns a date relative to the local timezone instead of UTC, properly taking daylight savings time into account. + The default is \code{False} meaning UTC is used. + \end{funcdesc} + + \begin{funcdesc}{make_msgid}{\optional{idstring}} + Returns a string suitable for an \rfc{2822}-compliant + \mailheader{Message-ID} header. Optional \var{idstring} if given, is + a string used to strengthen the uniqueness of the message id. \end{funcdesc} + + \begin{funcdesc}{decode_rfc2231}{s} + Decode the string \var{s} according to \rfc{2231}. + \end{funcdesc} + + \begin{funcdesc}{encode_rfc2231}{s\optional{, charset\optional{, language}}} + Encode the string \var{s} according to \rfc{2231}. Optional + \var{charset} and \var{language}, if given is the character set name + and language name to use. If neither is given, \var{s} is returned + as-is. If \var{charset} is given but \var{language} is not, the + string is encoded using the empty string for \var{language}. + \end{funcdesc} + + \begin{funcdesc}{decode_params}{params} + Decode parameters list according to \rfc{2231}. \var{params} is a + sequence of 2-tuples containing elements of the form + \code{(content-type, string-value)}. + \end{funcdesc} + + The following functions have been deprecated: + + \begin{funcdesc}{dump_address_pair}{pair} + \deprecated{2.2.2}{Use \function{formataddr()} instead.} + \end{funcdesc} + + \begin{funcdesc}{decode}{s} + \deprecated{2.2.2}{Use \method{Header.decode_header()} instead.} + \end{funcdesc} + + + \begin{funcdesc}{encode}{s\optional{, charset\optional{, encoding}}} + \deprecated{2.2.2}{Use \method{Header.encode()} instead.} + \end{funcdesc} + From gvanrossum@users.sourceforge.net Tue Oct 1 05:14:19 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 30 Sep 2002 21:14:19 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils ccompiler.py,1.47,1.48 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/distutils In directory usw-pr-cvs1:/tmp/cvs-serv13686 Modified Files: ccompiler.py Log Message: Commit fix for SF 603831. Strangely, two out of three patches there seem already committed; but the essential one (get rid of the assert in object_filenames in ccompiler.py) was not yet applied. This makes the build procedure for Twisted work again. This is *not* a backport candidate despite the fact that identical code appears to exist in 2.2.2; Twisted builds fine there, so there must have been a change elsewhere. Index: ccompiler.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/distutils/ccompiler.py,v retrieving revision 1.47 retrieving revision 1.48 diff -C2 -d -r1.47 -r1.48 *** ccompiler.py 11 Sep 2002 16:31:53 -0000 1.47 --- ccompiler.py 1 Oct 2002 04:14:17 -0000 1.48 *************** *** 877,881 **** def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): ! assert output_dir is not None obj_names = [] for src_name in source_filenames: --- 877,882 ---- def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): ! if output_dir is None: ! output_dir = '' obj_names = [] for src_name in source_filenames: From barry@users.sourceforge.net Tue Oct 1 05:33:19 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 30 Sep 2002 21:33:19 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib emailcharsets.tex,NONE,1.1 email.tex,1.12,1.13 emailencoders.tex,1.3,1.4 emailgenerator.tex,1.4,1.5 emailheaders.tex,1.1,1.2 emailmessage.tex,1.6,1.7 emailmimebase.tex,1.1,1.2 emailparser.tex,1.6,1.7 emailutil.tex,1.7,1.8 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv18370/lib Modified Files: email.tex emailencoders.tex emailgenerator.tex emailheaders.tex emailmessage.tex emailmimebase.tex emailparser.tex emailutil.tex Added Files: emailcharsets.tex Log Message: Proofread and spell checked, all except the Examples section (which I'll do next). --- NEW FILE: emailcharsets.tex --- \declaremodule{standard}{email.Charset} \modulesynopsis{Character Sets} This module provides a class \class{Charset} for representing character sets and character set conversions in email messages, as well as a character set registry and several convenience methods for manipulating this registry. Instances of \class{Charset} are used in several other modules within the \module{email} package. \versionadded{2.2.2} \begin{classdesc}{Charset}{\optional{input_charset}} Map character sets to their email properties. This class provides information about the requirements imposed on email for a specific character set. It also provides convenience routines for converting between character sets, given the availability of the applicable codecs. Given a character set, it will do its best to provide information on how to use that character set in an email message in an RFC-compliant way. Certain character sets must be encoded with quoted-printable or base64 when used in email headers or bodies. Certain character sets must be converted outright, and are not allowed in email. Optional \var{input_charset} is as described below. After being alias normalized it is also used as a lookup into the registry of character sets to find out the header encoding, body encoding, and output conversion codec to be used for the character set. For example, if \var{input_charset} is \code{iso-8859-1}, then headers and bodies will be encoded using quoted-printable and no output conversion codec is necessary. If \var{input_charset} is \code{euc-jp}, then headers will be encoded with base64, bodies will not be encoded, but output text will be converted from the \code{euc-jp} character set to the \code{iso-2022-jp} character set. \end{classdesc} \class{Charset} instances have the following data attributes: \begin{datadesc}{input_charset} The initial character set specified. Common aliases are converted to their \emph{official} email names (e.g. \code{latin_1} is converted to \code{iso-8859-1}). Defaults to 7-bit \code{us-ascii}. \end{datadesc} \begin{datadesc}{header_encoding} If the character set must be encoded before it can be used in an email header, this attribute will be set to \code{Charset.QP} (for quoted-printable), \code{Charset.BASE64} (for base64 encoding), or \code{Charset.SHORTEST} for the shortest of QP or BASE64 encoding. Otherwise, it will be \code{None}. \end{datadesc} \begin{datadesc}{body_encoding} Same as \var{header_encoding}, but describes the encoding for the mail message's body, which indeed may be different than the header encoding. \code{Charset.SHORTEST} is not allowed for \var{body_encoding}. \end{datadesc} \begin{datadesc}{output_charset} Some character sets must be converted before they can be used in email headers or bodies. If the \var{input_charset} is one of them, this attribute will contain the name of the character set output will be converted to. Otherwise, it will be \code{None}. \end{datadesc} \begin{datadesc}{input_codec} The name of the Python codec used to convert the \var{input_charset} to Unicode. If no conversion codec is necessary, this attribute will be \code{None}. \end{datadesc} \begin{datadesc}{output_codec} The name of the Python codec used to convert Unicode to the \var{output_charset}. If no conversion codec is necessary, this attribute will have the same value as the \var{input_codec}. \end{datadesc} \class{Charset} instances also have the following methods: \begin{methoddesc}[Charset]{get_body_encoding}{} Return the content transfer encoding used for body encoding. This is either the string \samp{quoted-printable} or \samp{base64} depending on the encoding used, or it is a function, in which case you should call the function with a single argument, the Message object being encoded. The function should then set the \mailheader{Content-Transfer-Encoding} header itself to whatever is appropriate. Returns the string \samp{quoted-printable} if \var{body_encoding} is \code{QP}, returns the string \samp{base64} if \var{body_encoding} is \code{BASE64}, and returns the string \samp{7bit} otherwise. \end{methoddesc} \begin{methoddesc}{convert}{s} Convert the string \var{s} from the \var{input_codec} to the \var{output_codec}. \end{methoddesc} \begin{methoddesc}{to_splittable}{s} Convert a possibly multibyte string to a safely splittable format. \var{s} is the string to split. Uses the \var{input_codec} to try and convert the string to Unicode, so it can be safely split on character boundaries (even for multibyte characters). Returns the string as-is if it isn't known how to convert \var{s} to Unicode with the \var{input_charset}. Characters that could not be converted to Unicode will be replaced with the Unicode replacement character \character{U+FFFD}. \end{methoddesc} \begin{methoddesc}{from_splittable}{ustr\optional{, to_output}} Convert a splittable string back into an encoded string. \var{ustr} is a Unicode string to ``unsplit''. This method uses the proper codec to try and convert the string from Unicode back into an encoded format. Return the string as-is if it is not Unicode, or if it could not be converted from Unicode. Characters that could not be converted from Unicode will be replaced with an appropriate character (usually \character{?}). If \var{to_output} is \code{True} (the default), uses \var{output_codec} to convert to an encoded format. If \var{to_output} is \code{False}, it uses \var{input_codec}. \end{methoddesc} \begin{methoddesc}{get_output_charset}{} Return the output character set. This is the \var{output_charset} attribute if that is not \code{None}, otherwise it is \var{input_charset}. \end{methoddesc} \begin{methoddesc}{encoded_header_len}{} Return the length of the encoded header string, properly calculating for quoted-printable or base64 encoding. \end{methoddesc} \begin{methoddesc}{header_encode}{s\optional{, convert}} Header-encode the string \var{s}. If \var{convert} is \code{True}, the string will be converted from the input charset to the output charset automatically. This is not useful for multibyte character sets, which have line length issues (multibyte characters must be split on a character, not a byte boundary); use the higher-level \class{Header} class to deal with these issues (see \refmodule{email.Header}). \var{convert} defaults to \code{False}. The type of encoding (base64 or quoted-printable) will be based on the \var{header_encoding} attribute. \end{methoddesc} \begin{methoddesc}{body_encode}{s\optional{, convert}} Body-encode the string \var{s}. If \var{convert} is \code{True} (the default), the string will be converted from the input charset to output charset automatically. Unlike \method{header_encode()}, there are no issues with byte boundaries and multibyte charsets in email bodies, so this is usually pretty safe. The type of encoding (base64 or quoted-printable) will be based on the \var{body_encoding} attribute. \end{methoddesc} The \class{Charset} class also provides a number of methods to support standard operations and built-in functions. \begin{methoddesc}[Charset]{__str__}{} Returns \var{input_charset} as a string coerced to lower case. \end{methoddesc} \begin{methoddesc}[Charset]{__eq__}{other} This method allows you to compare two \class{Charset} instances for equality. \end{methoddesc} \begin{methoddesc}[Header]{__ne__}{other} This method allows you to compare two \class{Charset} instances for inequality. \end{methoddesc} The \module{email.Charset} module also provides the following functions for adding new entries to the global character set, alias, and codec registries: \begin{funcdesc}{add_charset}{charset\optional{, header_enc\optional{, body_enc\optional{, output_charset}}}} Add character properties to the global registry. \var{charset} is the input character set, and must be the canonical name of a character set. Optional \var{header_enc} and \var{body_enc} is either \code{Charset.QP} for quoted-printable, \code{Charset.BASE64} for base64 encoding, \code{Charset.SHORTEST} for the shortest of quoted-printable or base64 encoding, or \code{None} for no encoding. \code{SHORTEST} is only valid for \var{header_enc}. The default is \code{None} for no encoding. Optional \var{output_charset} is the character set that the output should be in. Conversions will proceed from input charset, to Unicode, to the output charset when the method \method{Charset.convert()} is called. The default is to output in the same character set as the input. Both \var{input_charset} and \var{output_charset} must have Unicode codec entries in the module's character set-to-codec mapping; use \function{add_codec()} to add codecs the module does not know about. See the \refmodule{codecs} module's documentation for more information. The global character set registry is kept in the module global dictionary \code{CHARSETS}. \end{funcdesc} \begin{funcdesc}{add_alias}{alias, canonical} Add a character set alias. \var{alias} is the alias name, e.g. \code{latin-1}. \var{canonical} is the character set's canonical name, e.g. \code{iso-8859-1}. The global charset alias registry is kept in the module global dictionary \code{ALIASES}. \end{funcdesc} \begin{funcdesc}{add_codec}{charset, codecname} Add a codec that map characters in the given character set to and from Unicode. \var{charset} is the canonical name of a character set. \var{codecname} is the name of a Python codec, as appropriate for the second argument to the \function{unicode()} built-in, or to the \method{encode()} method of a Unicode string. \end{funcdesc} Index: email.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/email.tex,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** email.tex 1 Oct 2002 01:05:51 -0000 1.12 --- email.tex 1 Oct 2002 04:33:12 -0000 1.13 *************** *** 40,51 **** \module{email} package. The ordering follows a progression that should be common in applications: an email message is read as flat ! text from a file or other source, the text is parsed to produce an ! object model representation of the email message, this model is ! manipulated, and finally the model is rendered back into ! flat text. ! It is perfectly feasible to create the object model out of whole cloth ! --- i.e. completely from scratch. From there, a similar progression ! can be taken as above. Also included are detailed specifications of all the classes and --- 40,50 ---- \module{email} package. The ordering follows a progression that should be common in applications: an email message is read as flat ! text from a file or other source, the text is parsed to produce the ! object structure of the email message, this structure is manipulated, ! and finally rendered back into flat text. ! It is perfectly feasible to create the object structure out of whole ! cloth --- i.e. completely from scratch. From there, a similar ! progression can be taken as above. Also included are detailed specifications of all the classes and *************** *** 72,78 **** \input{emailmimebase} ! \subsection{Headers, Character sets, and Internationalization} \input{emailheaders} \subsection{Encoders} \input{emailencoders} --- 71,80 ---- \input{emailmimebase} ! \subsection{Internationalized headers} \input{emailheaders} + \subsection{Representing character sets} + \input{emailcharsets} + \subsection{Encoders} \input{emailencoders} *************** *** 93,97 **** 2.3 release, and backported to Python 2.2.2. It was also available as a separate distutils based package. \module{email} version 2 is ! almost entirely backwards compatible with version 1, with the following differences: --- 95,99 ---- 2.3 release, and backported to Python 2.2.2. It was also available as a separate distutils based package. \module{email} version 2 is ! almost entirely backward compatible with version 1, with the following differences: *************** *** 101,105 **** \item The pickle format for \class{Message} instances has changed. Since this was never (and still isn't) formally defined, this ! isn't considered a backwards incompatibility. However if your application pickles and unpickles \class{Message} instances, be aware that in \module{email} version 2, \class{Message} --- 103,107 ---- \item The pickle format for \class{Message} instances has changed. Since this was never (and still isn't) formally defined, this ! isn't considered a backward incompatibility. However if your application pickles and unpickles \class{Message} instances, be aware that in \module{email} version 2, \class{Message} *************** *** 107,113 **** \var{_default_type}. \item Several methods in the \class{Message} class have been ! deprecated, or their signatures changes. Also, many new methods have been added. See the documentation for the \class{Message} ! class for deatils. The changes should be completely backwards compatible. \item The object structure has changed in the face of --- 109,115 ---- \var{_default_type}. \item Several methods in the \class{Message} class have been ! deprecated, or their signatures changed. Also, many new methods have been added. See the documentation for the \class{Message} ! class for details. The changes should be completely backward compatible. \item The object structure has changed in the face of *************** *** 115,129 **** version 1, such a type would be represented by a scalar payload, i.e. the container message's \method{is_multipart()} returned ! false, \method{get_payload()} was not a list object, and was ! actually a \class{Message} instance. This structure was inconsistent with the rest of the package, so the object representation for \mimetype{message/rfc822} content ! types was changed. In module{email} version 2, the container \emph{does} return \code{True} from \method{is_multipart()}, and \method{get_payload()} returns a list containing a single \class{Message} item. ! Note that this is one place that backwards compatibility could not be completely maintained. However, if you're already testing the return type of \method{get_payload()}, you should be --- 117,131 ---- version 1, such a type would be represented by a scalar payload, i.e. the container message's \method{is_multipart()} returned ! false, \method{get_payload()} was not a list object, but a single ! \class{Message} instance. This structure was inconsistent with the rest of the package, so the object representation for \mimetype{message/rfc822} content ! types was changed. In \module{email} version 2, the container \emph{does} return \code{True} from \method{is_multipart()}, and \method{get_payload()} returns a list containing a single \class{Message} item. ! Note that this is one place that backward compatibility could not be completely maintained. However, if you're already testing the return type of \method{get_payload()}, you should be *************** *** 143,147 **** \item The intermediate base classes \class{MIMENonMultipart} and \class{MIMEMultipart} have been added, and interposed in the ! class heirarchy for most of the other MIME-related derived classes. \item The \var{_encoder} argument to the \class{MIMEText} constructor --- 145,149 ---- \item The intermediate base classes \class{MIMENonMultipart} and \class{MIMEMultipart} have been added, and interposed in the ! class hierarchy for most of the other MIME-related derived classes. \item The \var{_encoder} argument to the \class{MIMEText} constructor *************** *** 168,172 **** have also changed. For the most part, any functionality available in \module{mimelib} is still available in the \refmodule{email} package, ! albeit often in a different way. Here is a brief description of the differences between the --- 170,176 ---- have also changed. For the most part, any functionality available in \module{mimelib} is still available in the \refmodule{email} package, ! albeit often in a different way. Backward compatibility between ! the \module{mimelib} package and the \module{email} package was not a ! priority. Here is a brief description of the differences between the Index: emailencoders.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailencoders.tex,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** emailencoders.tex 1 Oct 2002 01:05:52 -0000 1.3 --- emailencoders.tex 1 Oct 2002 04:33:14 -0000 1.4 *************** *** 18,22 **** \begin{funcdesc}{encode_quopri}{msg} ! Encodes the payload into quoted-Printable form and sets the \mailheader{Content-Transfer-Encoding} header to \code{quoted-printable}\footnote{Note that encoding with --- 18,22 ---- \begin{funcdesc}{encode_quopri}{msg} ! Encodes the payload into quoted-printable form and sets the \mailheader{Content-Transfer-Encoding} header to \code{quoted-printable}\footnote{Note that encoding with Index: emailgenerator.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailgenerator.tex,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** emailgenerator.tex 1 Oct 2002 01:05:52 -0000 1.4 --- emailgenerator.tex 1 Oct 2002 04:33:14 -0000 1.5 *************** *** 25,34 **** object called \var{outfp} for an argument. \var{outfp} must support the \method{write()} method and be usable as the output file in a ! Python 2.0 extended print statement. Optional \var{mangle_from_} is a flag that, when \code{True}, puts a \samp{>} character in front of any line in the body that starts exactly as ! \samp{From } (i.e. \code{From} followed by a space at the front of the ! line). This is the only guaranteed portable way to avoid having such lines be mistaken for a Unix mailbox format envelope header separator (see \ulink{WHY THE CONTENT-LENGTH FORMAT IS BAD} --- 25,34 ---- object called \var{outfp} for an argument. \var{outfp} must support the \method{write()} method and be usable as the output file in a ! Python extended print statement. Optional \var{mangle_from_} is a flag that, when \code{True}, puts a \samp{>} character in front of any line in the body that starts exactly as ! \samp{From }, i.e. \code{From} followed by a space at the beginning of the ! line. This is the only guaranteed portable way to avoid having such lines be mistaken for a Unix mailbox format envelope header separator (see \ulink{WHY THE CONTENT-LENGTH FORMAT IS BAD} *************** *** 49,56 **** The other public \class{Generator} methods are: ! \begin{methoddesc}[Generator]{flatten()}{msg\optional{, unixfrom}} Print the textual representation of the message object structure rooted at \var{msg} to the output file specified when the \class{Generator} ! instance was created. Sub-objects are visited depth-first and the resulting text will be properly MIME encoded. --- 49,56 ---- The other public \class{Generator} methods are: ! \begin{methoddesc}[Generator]{flatten}{msg\optional{, unixfrom}} Print the textual representation of the message object structure rooted at \var{msg} to the output file specified when the \class{Generator} ! instance was created. Subparts are visited depth-first and the resulting text will be properly MIME encoded. *************** *** 61,65 **** inhibit the printing of the envelope delimiter. ! Note that for sub-objects, no envelope header is ever printed. \versionadded{2.2.2} --- 61,65 ---- inhibit the printing of the envelope delimiter. ! Note that for subparts, no envelope header is ever printed. \versionadded{2.2.2} *************** *** 100,113 **** If the subpart is not of main type \mimetype{text}, optional \var{fmt} ! is a format string that is used instead of the message ! payload. \var{fmt} is expanded with the following keywords (in ! \samp{\%(keyword)s} format): ! type : Full MIME type of the non-\mimetype{text} part ! maintype : Main MIME type of the non-\mimetype{text} part ! subtype : Sub-MIME type of the non-\mimetype{text} part ! filename : Filename of the non-\mimetype{text} part ! description: Description associated with the non-\mimetype{text} part ! encoding : Content transfer encoding of the non-\mimetype{text} part The default value for \var{fmt} is \code{None}, meaning --- 100,117 ---- If the subpart is not of main type \mimetype{text}, optional \var{fmt} ! is a format string that is used instead of the message payload. ! \var{fmt} is expanded with the following keywords, \samp{\%(keyword)s} ! format: ! \begin{itemize} ! \item \code{type} -- Full MIME type of the non-\mimetype{text} part ! \item \code{maintype} -- Main MIME type of the non-\mimetype{text} part ! \item \code{subtype} -- Sub-MIME type of the non-\mimetype{text} part ! \item \code{filename} -- Filename of the non-\mimetype{text} part ! \item \code{description} -- Description associated with the ! non-\mimetype{text} part ! \item \code{encoding} -- Content transfer encoding of the ! non-\mimetype{text} part ! \end{itemize} The default value for \var{fmt} is \code{None}, meaning Index: emailheaders.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailheaders.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** emailheaders.tex 1 Oct 2002 01:05:52 -0000 1.1 --- emailheaders.tex 1 Oct 2002 04:33:15 -0000 1.2 *************** *** 4,8 **** \rfc{2822} is the base standard that describes the format of email messages. It derives from the older \rfc{822} standard which came ! into widespread at a time when most email was composed of \ASCII{} characters only. \rfc{2822} is a specification written assuming email contains only 7-bit \ASCII{} characters. --- 4,8 ---- \rfc{2822} is the base standard that describes the format of email messages. It derives from the older \rfc{822} standard which came ! into widespread use at a time when most email was composed of \ASCII{} characters only. \rfc{2822} is a specification written assuming email contains only 7-bit \ASCII{} characters. *************** *** 20,27 **** If you want to include non-\ASCII{} characters in your email headers, say in the \mailheader{Subject} or \mailheader{To} fields, you should ! use the \class{Header} class (in module \module{email.Header} and ! assign the field in the \class{Message} object to an instance of ! \class{Header} instead of using a string for the header value. For ! example: \begin{verbatim} --- 20,26 ---- If you want to include non-\ASCII{} characters in your email headers, say in the \mailheader{Subject} or \mailheader{To} fields, you should ! use the \class{Header} class and assign the field in the ! \class{Message} object to an instance of \class{Header} instead of ! using a string for the header value. For example: \begin{verbatim} *************** *** 51,55 **** \begin{classdesc}{Header}{\optional{s\optional{, charset\optional{, maxlinelen\optional{, header_name\optional{, continuation_ws}}}}}} ! Create a MIME-compliant header that can contain many character sets. Optional \var{s} is the initial header value. If \code{None} (the --- 50,55 ---- \begin{classdesc}{Header}{\optional{s\optional{, charset\optional{, maxlinelen\optional{, header_name\optional{, continuation_ws}}}}}} ! Create a MIME-compliant header that can contain strings in different ! character sets. Optional \var{s} is the initial header value. If \code{None} (the *************** *** 75,79 **** taken into account for the first line of a long, split header. ! Optional \var{continuation_ws} must be RFC 2822 compliant folding whitespace, and is usually either a space or a hard tab character. This character will be prepended to continuation lines. --- 75,79 ---- taken into account for the first line of a long, split header. ! Optional \var{continuation_ws} must be \rfc{2822}-compliant folding whitespace, and is usually either a space or a hard tab character. This character will be prepended to continuation lines. *************** *** 90,94 **** \var{s} may be a byte string or a Unicode string. If it is a byte ! string (i.e. \code{isinstance(s, StringType)} is true), then \var{charset} is the encoding of that byte string, and a \exception{UnicodeError} will be raised if the string cannot be --- 90,94 ---- \var{s} may be a byte string or a Unicode string. If it is a byte ! string (i.e. \code{isinstance(s, str)} is true), then \var{charset} is the encoding of that byte string, and a \exception{UnicodeError} will be raised if the string cannot be *************** *** 114,118 **** \begin{methoddesc}[Header]{__str__}{} A synonym for \method{Header.encode()}. Useful for ! \code{str(aHeader)} calls. \end{methoddesc} --- 114,118 ---- \begin{methoddesc}[Header]{__str__}{} A synonym for \method{Header.encode()}. Useful for ! \code{str(aHeader)}. \end{methoddesc} *************** *** 165,409 **** \var{header_name}, and \var{continuation_ws} are as in the \class{Header} constructor. - \end{funcdesc} - - \declaremodule{standard}{email.Charset} - \modulesynopsis{Character Sets} - - This module provides a class \class{Charset} for representing - character sets and character set conversions in email messages, as - well as a character set registry and several convenience methods for - manipulating this registry. Instances of \class{Charset} are used in - several other modules within the \module{email} package. - - \versionadded{2.2.2} - - \begin{classdesc}{Charset}{\optional{input_charset}} - Map character sets to their email properties. - - This class provides information about the requirements imposed on - email for a specific character set. It also provides convenience - routines for converting between character sets, given the availability - of the applicable codecs. Given a character set, it will do its best - to provide information on how to use that character set in an email - message in an RFC-compliant way. - - Certain character sets must be encoded with quoted-printable or base64 - when used in email headers or bodies. Certain character sets must be - converted outright, and are not allowed in email. - - Optional \var{input_charset} is as described below. After being alias - normalized it is also used as a lookup into the registry of character - sets to find out the header encoding, body encoding, and output - conversion codec to be used for the character set. For example, if - \var{input_charset} is \code{iso-8859-1}, then headers and bodies will - be encoded using quoted-printable and no output conversion codec is - necessary. If \var{input_charset} is \code{euc-jp}, then headers will - be encoded with base64, bodies will not be encoded, but output text - will be converted from the \code{euc-jp} character set to the - \code{iso-2022-jp} character set. - \end{classdesc} - - \class{Charset} instances have the following data attributes: - - \begin{datadesc}{input_charset} - The initial character set specified. Common aliases are converted to - their \emph{official} email names (e.g. \code{latin_1} is converted to - \code{iso-8859-1}). Defaults to 7-bit \code{us-ascii}. - \end{datadesc} - - \begin{datadesc}{header_encoding} - If the character set must be encoded before it can be used in an - email header, this attribute will be set to \code{Charset.QP} (for - quoted-printable), \code{Charset.BASE64} (for base64 encoding), or - \code{Charset.SHORTEST} for the shortest of QP or BASE64 encoding. - Otherwise, it will be \code{None}. - \end{datadesc} - - \begin{datadesc}{body_encoding} - Same as \var{header_encoding}, but describes the encoding for the - mail message's body, which indeed may be different than the header - encoding. \code{Charset.SHORTEST} is not allowed for - \var{body_encoding}. - \end{datadesc} - - \begin{datadesc}{output_charset} - Some character sets must be converted before the can be used in - email headers or bodies. If the \var{input_charset} is one of - them, this attribute will contain the name of the character set - output will be converted to. Otherwise, it will be \code{None}. - \end{datadesc} - - \begin{datadesc}{input_codec} - The name of the Python codec used to convert the \var{input_charset} to - Unicode. If no conversion codec is necessary, this attribute will be - \code{None}. - \end{datadesc} - - \begin{datadesc}{output_codec} - The name of the Python codec used to convert Unicode to the - \var{output_charset}. If no conversion codec is necessary, this - attribute will have the same value as the \var{input_codec}. - \end{datadesc} - - \class{Charset} instances also have the following methods: - - \begin{methoddesc}[Charset]{get_body_encoding}{} - Return the content transfer encoding used for body encoding. - - This is either the string \samp{quoted-printable} or \samp{base64} - depending on the encoding used, or it is a function, in which case you - should call the function with a single argument, the Message object - being encoded. The function should then set the - \mailheader{Content-Transfer-Encoding} header itself to whatever is - appropriate. - - Returns the string \samp{quoted-printable} if - \var{body_encoding} is \code{QP}, returns the string - \samp{base64} if \var{body_encoding} is \code{BASE64}, and returns the - string \samp{7bit} otherwise. - \end{methoddesc} - - \begin{methoddesc}{convert}{s} - Convert the string \var{s} from the \var{input_codec} to the - \var{output_codec}. - \end{methoddesc} - - \begin{methoddesc}{to_splittable}{s} - Convert a possibly multibyte string to a safely splittable format. - \var{s} is the string to split. - - Uses the \var{input_codec} to try and convert the string to Unicode, - so it can be safely split on character boundaries (even for multibyte - characters). - - Returns the string as-is if it isn't known how to convert \var{s} to - Unicode with the \var{input_charset}. - - Characters that could not be converted to Unicode will be replaced - with the Unicode replacement character \character{U+FFFD}. - \end{methoddesc} - - \begin{methoddesc}{from_splittable}{ustr\optional{, to_output}} - Convert a splittable string back into an encoded string. \var{ustr} - is a Unicode string to ``unsplit''. - - This method uses the proper codec to try and convert the string from - Unicode back into an encoded format. Return the string as-is if it is - not Unicode, or if it could not be converted from Unicode. - - Characters that could not be converted from Unicode will be replaced - with an appropriate character (usually \character{?}). - - If \var{to_output} is \code{True} (the default), uses - \var{output_codec} to convert to an - encoded format. If \var{to_output} is \code{False}, it uses - \var{input_codec}. - \end{methoddesc} - - \begin{methoddesc}{get_output_charset}{} - Return the output character set. - - This is the \var{output_charset} attribute if that is not \code{None}, - otherwise it is \var{input_charset}. - \end{methoddesc} - - \begin{methoddesc}{encoded_header_len}{} - Return the length of the encoded header string, properly calculating - for quoted-printable or base64 encoding. - \end{methoddesc} - - \begin{methoddesc}{header_encode}{s\optional{, convert}} - Header-encode the string \var{s}. - - If \var{convert} is \code{True}, the string will be converted from the - input charset to the output charset automatically. This is not useful - for multibyte character sets, which have line length issues (multibyte - characters must be split on a character, not a byte boundary); use the - higher-level \class{Header} class to deal with these issues (see - \refmodule{email.Header}). \var{convert} defaults to \code{False}. - - The type of encoding (base64 or quoted-printable) will be based on - the \var{header_encoding} attribute. - \end{methoddesc} - - \begin{methoddesc}{body_encode}{s\optional{, convert}} - Body-encode the string \var{s}. - - If \var{convert} is \code{True} (the default), the string will be - converted from the input charset to output charset automatically. - Unlike \method{header_encode()}, there are no issues with byte - boundaries and multibyte charsets in email bodies, so this is usually - pretty safe. - - The type of encoding (base64 or quoted-printable) will be based on - the \var{body_encoding} attribute. - \end{methoddesc} - - The \class{Charset} class also provides a number of methods to support - standard operations and built-in functions. - - \begin{methoddesc}[Charset]{__str__}{} - Returns \var{input_charset} as a string coerced to lower case. - \end{methoddesc} - - \begin{methoddesc}[Charset]{__eq__}{other} - This method allows you to compare two \class{Charset} instances for equality. - \end{methoddesc} - - \begin{methoddesc}[Header]{__ne__}{other} - This method allows you to compare two \class{Charset} instances for inequality. - \end{methoddesc} - - The \module{email.Charset} module also provides the following - functions for adding new entries to the global character set, alias, - and codec registries: - - \begin{funcdesc}{add_charset}{charset\optional{, header_enc\optional{, - body_enc\optional{, output_charset}}}} - Add character properties to the global registry. - - \var{charset} is the input character set, and must be the canonical - name of a character set. - - Optional \var{header_enc} and \var{body_enc} is either - \code{Charset.QP} for quoted-printable, \code{Charset.BASE64} for - base64 encoding, \code{Charset.SHORTEST} for the shortest of qp or - base64 encoding, or \code{None} for no encoding. \code{SHORTEST} is - only valid for \var{header_enc}. It describes how message headers and - message bodies in the input charset are to be encoded. Default is no - encoding. - - Optional \var{output_charset} is the character set that the output - should be in. Conversions will proceed from input charset, to - Unicode, to the output charset when the method - \method{Charset.convert()} is called. The default is to output in the - same character set as the input. - - Both \var{input_charset} and \var{output_charset} must have Unicode - codec entries in the module's character set-to-codec mapping; use - \function{add_codec(charset, codecname)} to add codecs the module does - not know about. See the \refmodule{codecs} module's documentation for - more information. - - The global character set registry is kept in the module global - dictionary \code{CHARSETS}. - \end{funcdesc} - - \begin{funcdesc}{add_alias}{alias, canonical} - Add a character set alias. \var{alias} is the alias name, - e.g. \code{latin-1}. \var{canonical} is the character set's canonical - name, e.g. \code{iso-8859-1}. - - The global charset alias registry is kept in the module global - dictionary \code{ALIASES}. - \end{funcdesc} - - \begin{funcdesc}{add_codec}{charset, codecname} - Add a codec that map characters in the given character set to and from - Unicode. - - \var{charset} is the canonical name of a character set. - \var{codecname} is the name of a Python codec, as appropriate for the - second argument to the \function{unicode()} built-in, or to the - \method{encode()} method of a Unicode string. \end{funcdesc} --- 165,167 ---- Index: emailmessage.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailmessage.tex,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** emailmessage.tex 1 Oct 2002 01:05:52 -0000 1.6 --- emailmessage.tex 1 Oct 2002 04:33:16 -0000 1.7 *************** *** 34,40 **** \begin{methoddesc}[Message]{as_string}{\optional{unixfrom}} ! Return the entire formatted message as a string. Optional ! \var{unixfrom}, when true, specifies to include the \emph{Unix-From} ! envelope header; it defaults to \code{False}. \end{methoddesc} --- 34,40 ---- \begin{methoddesc}[Message]{as_string}{\optional{unixfrom}} ! Return the entire message flatten as a string. When optional ! \var{unixfrom} is \code{True}, the envelope header is included in the ! returned string. \var{unixfrom} defaults to \code{False}. \end{methoddesc} *************** *** 60,64 **** \begin{methoddesc}[Message]{attach}{payload} ! Add the given payload to the current payload, which must be \code{None} or a list of \class{Message} objects before the call. After the call, the payload will always be a list of \class{Message} --- 60,64 ---- \begin{methoddesc}[Message]{attach}{payload} ! Add the given \var{payload} to the current payload, which must be \code{None} or a list of \class{Message} objects before the call. After the call, the payload will always be a list of \class{Message} *************** *** 96,100 **** Set the entire message object's payload to \var{payload}. It is the client's responsibility to ensure the payload invariants. Optional ! \var{charset} sets the message's default character set (see \method{set_charset()} for details. --- 96,100 ---- Set the entire message object's payload to \var{payload}. It is the client's responsibility to ensure the payload invariants. Optional ! \var{charset} sets the message's default character set; see \method{set_charset()} for details. *************** *** 104,108 **** \begin{methoddesc}[Message]{set_charset}{charset} Set the character set of the payload to \var{charset}, which can ! either be a \class{Charset} instance (see \refmodule{email.Charset}, a string naming a character set, or \code{None}. If it is a string, it will be converted to a --- 104,108 ---- \begin{methoddesc}[Message]{set_charset}{charset} Set the character set of the payload to \var{charset}, which can ! either be a \class{Charset} instance (see \refmodule{email.Charset}), a string naming a character set, or \code{None}. If it is a string, it will be converted to a *************** *** 129,140 **** The following methods implement a mapping-like interface for accessing ! the message object's \rfc{2822} headers. Note that there are some semantic differences between these methods and a normal mapping (i.e. dictionary) interface. For example, in a dictionary there are no duplicate keys, but here there may be duplicate message headers. Also, in dictionaries there is no guaranteed order to the keys returned by ! \method{keys()}, but in a \class{Message} object, there is an explicit ! order. These semantic differences are intentional and are biased ! toward maximal convenience. Note that in all cases, any envelope header present in the message is --- 129,144 ---- The following methods implement a mapping-like interface for accessing ! the message's \rfc{2822} headers. Note that there are some semantic differences between these methods and a normal mapping (i.e. dictionary) interface. For example, in a dictionary there are no duplicate keys, but here there may be duplicate message headers. Also, in dictionaries there is no guaranteed order to the keys returned by ! \method{keys()}, but in a \class{Message} object, headers are always ! returned in the order they appeared in the original message, or were ! added to the message later. Any header deleted and then re-added are ! always appended to the end of the header list. ! ! These semantic differences are intentional and are biased toward ! maximal convenience. Note that in all cases, any envelope header present in the message is *************** *** 176,181 **** with the same name. If you want to ensure that the new header is the only one present in the message with field name ! \var{name}, first use \method{__delitem__()} to delete all named ! fields, e.g.: \begin{verbatim} --- 180,184 ---- with the same name. If you want to ensure that the new header is the only one present in the message with field name ! \var{name}, delete the field first, e.g.: \begin{verbatim} *************** *** 197,221 **** \begin{methoddesc}[Message]{keys}{} ! Return a list of all the message's header field names. These keys ! will be sorted in the order in which they appeared in the original ! message, or were added to the message and may contain ! duplicates. Any fields deleted and then subsequently re-added are ! always appended to the end of the header list. \end{methoddesc} \begin{methoddesc}[Message]{values}{} ! Return a list of all the message's field values. These will be sorted ! in the order in which they appeared in the original message, or were ! added to the message, and may contain ! duplicates. Any fields deleted and then subsequently re-added are ! always appended to the end of the header list. \end{methoddesc} \begin{methoddesc}[Message]{items}{} Return a list of 2-tuples containing all the message's field headers ! and values. These will be sorted in the order in which they appeared ! in the original message, or were added to the message, and may contain ! duplicates. Any fields deleted and then subsequently re-added are ! always appended to the end of the header list. \end{methoddesc} --- 200,213 ---- \begin{methoddesc}[Message]{keys}{} ! Return a list of all the message's header field names. \end{methoddesc} \begin{methoddesc}[Message]{values}{} ! Return a list of all the message's field values. \end{methoddesc} \begin{methoddesc}[Message]{items}{} Return a list of 2-tuples containing all the message's field headers ! and values. \end{methoddesc} *************** *** 229,237 **** \begin{methoddesc}[Message]{get_all}{name\optional{, failobj}} ! Return a list of all the values for the field named \var{name}. These ! will be sorted in the order in which they appeared in the original ! message, or were added to the message. Any fields deleted and then ! subsequently re-added are always appended to the end of the list. ! If there are no such named headers in the message, \var{failobj} is returned (defaults to \code{None}). --- 221,225 ---- \begin{methoddesc}[Message]{get_all}{name\optional{, failobj}} ! Return a list of all the values for the field named \var{name}. If there are no such named headers in the message, \var{failobj} is returned (defaults to \code{None}). *************** *** 352,359 **** value can either be a string, or a 3-tuple if the parameter was \rfc{2231} encoded. When it's a 3-tuple, the elements of the value are of ! the form \samp{(CHARSET, LANGUAGE, VALUE)}, where \var{LANGUAGE} may be the empty string. Your application should be prepared to deal with ! 3-tuple return values, which it can convert the parameter to a Unicode ! string like so: \begin{verbatim} --- 340,347 ---- value can either be a string, or a 3-tuple if the parameter was \rfc{2231} encoded. When it's a 3-tuple, the elements of the value are of ! the form \code{(CHARSET, LANGUAGE, VALUE)}, where \code{LANGUAGE} may be the empty string. Your application should be prepared to deal with ! 3-tuple return values, which it can convert to a Unicode string like ! so: \begin{verbatim} *************** *** 364,368 **** In any case, the parameter value (either the returned string, or the ! \var{VALUE} item in the 3-tuple) is always unquoted, unless \var{unquote} is set to \code{False}. --- 352,356 ---- In any case, the parameter value (either the returned string, or the ! \code{VALUE} item in the 3-tuple) is always unquoted, unless \var{unquote} is set to \code{False}. *************** *** 399,403 **** place without the parameter or its value. All values will be quoted as necessary unless \var{requote} is \code{False} (the default is ! \code{True}). Optional \var{header} specifies an alterative to \mailheader{Content-Type}. --- 387,391 ---- place without the parameter or its value. All values will be quoted as necessary unless \var{requote} is \code{False} (the default is ! \code{True}). Optional \var{header} specifies an alternative to \mailheader{Content-Type}. *************** *** 418,423 **** An alternative header can be specified in the \var{header} argument. ! When the \mailheader{Content-Type} header is set, we'll always also ! add a \mailheader{MIME-Version} header. \versionadded{2.2.2} --- 406,411 ---- An alternative header can be specified in the \var{header} argument. ! When the \mailheader{Content-Type} header is set a ! \mailheader{MIME-Version} header is also added. \versionadded{2.2.2} *************** *** 441,449 **** \begin{methoddesc}[Message]{set_boundary}{boundary} ! Set the \code{boundary} parameter of the \mailheader{Content-Type} header ! to \var{boundary}. \method{set_boundary()} will always quote ! \var{boundary} so you should not quote it yourself. A ! \exception{HeaderParseError} is raised if the message object has no ! \mailheader{Content-Type} header. Note that using this method is subtly different than deleting the old --- 429,436 ---- \begin{methoddesc}[Message]{set_boundary}{boundary} ! Set the \code{boundary} parameter of the \mailheader{Content-Type} ! header to \var{boundary}. \method{set_boundary()} will always quote ! \var{boundary} if necessary. A \exception{HeaderParseError} is raised ! if the message object has no \mailheader{Content-Type} header. Note that using this method is subtly different than deleting the old *************** *** 460,466 **** header has no \code{charset} parameter, \var{failobj} is returned. ! Note that this method differs from \method{get_charset} which returns ! the \class{Charset} instance for the default encoding of the message ! body. \versionadded{2.2.2} --- 447,453 ---- header has no \code{charset} parameter, \var{failobj} is returned. ! Note that this method differs from \method{get_charset()} which ! returns the \class{Charset} instance for the default encoding of the ! message body. \versionadded{2.2.2} *************** *** 485,497 **** used to iterate over all the parts and subparts of a message object tree, in depth-first traversal order. You will typically use ! \method{walk()} as the iterator in a \code{for ... in} loop; each iteration returns the next subpart. ! Here's an example that prints the MIME type of every part of a message ! object tree: \begin{verbatim} >>> for part in msg.walk(): ! >>> print part.get_type('text/plain') multipart/report text/plain --- 472,484 ---- used to iterate over all the parts and subparts of a message object tree, in depth-first traversal order. You will typically use ! \method{walk()} as the iterator in a \code{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: \begin{verbatim} >>> for part in msg.walk(): ! >>> print part.get_content_type() multipart/report text/plain Index: emailmimebase.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailmimebase.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** emailmimebase.tex 1 Oct 2002 01:05:52 -0000 1.1 --- emailmimebase.tex 1 Oct 2002 04:33:16 -0000 1.2 *************** *** 1,9 **** Ordinarily, you get a message object structure by passing a file or ! some text to a parser, which parses the text and returns the root of ! the message object structure. However you can also build a complete ! object structure from scratch, or even individual \class{Message} ! objects by hand. In fact, you can also take an existing structure and ! add new \class{Message} objects, move them around, etc. This makes a ! very convenient interface for slicing-and-dicing MIME messages. You can create a new object structure by creating \class{Message} --- 1,9 ---- Ordinarily, you get a message object structure by passing a file or ! some text to a parser, which parses the text and returns the root ! message object. However you can also build a complete message ! structure from scratch, or even individual \class{Message} objects by ! hand. In fact, you can also take an existing structure and add new ! \class{Message} objects, move them around, etc. This makes a very ! convenient interface for slicing-and-dicing MIME messages. You can create a new object structure by creating \class{Message} *************** *** 100,104 **** change the payload to encoded form. It should also add any \mailheader{Content-Transfer-Encoding} or other headers to the message ! object as necessary. The default encoding is \emph{Base64}. See the \refmodule{email.Encoders} module for a list of the built-in encoders. --- 100,104 ---- change the payload to encoded form. It should also add any \mailheader{Content-Transfer-Encoding} or other headers to the message ! object as necessary. The default encoding is base64. See the \refmodule{email.Encoders} module for a list of the built-in encoders. *************** *** 125,129 **** change the payload to encoded form. It should also add any \mailheader{Content-Transfer-Encoding} or other headers to the message ! object as necessary. The default encoding is \emph{Base64}. See the \refmodule{email.Encoders} module for a list of the built-in encoders. --- 125,129 ---- change the payload to encoded form. It should also add any \mailheader{Content-Transfer-Encoding} or other headers to the message ! object as necessary. The default encoding is base64. See the \refmodule{email.Encoders} module for a list of the built-in encoders. Index: emailparser.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailparser.tex,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** emailparser.tex 1 Oct 2002 01:05:52 -0000 1.6 --- emailparser.tex 1 Oct 2002 04:33:16 -0000 1.7 *************** *** 55,59 **** problems, the \class{Parser} will raise a \exception{MessageParseError}. However, when lax parsing is enabled, ! the \class{Parser} will attempt to workaround such broken formatting to produce a usable message structure (this doesn't mean \exception{MessageParseError}s are never raised; some ill-formatted --- 55,59 ---- problems, the \class{Parser} will raise a \exception{MessageParseError}. However, when lax parsing is enabled, ! the \class{Parser} will attempt to work around such broken formatting to produce a usable message structure (this doesn't mean \exception{MessageParseError}s are never raised; some ill-formatted *************** *** 74,85 **** The text contained in \var{fp} must be formatted as a block of \rfc{2822} ! style headers and header continuation lines, optionally preceeded by a envelope header. The header block is terminated either by the end of the data or by a blank line. Following the header block is the body of the message (which may contain MIME-encoded subparts). ! Optional \var{headersonly} is a flag specifying whether to stop ! parsing after reading the headers or not. The default is \code{False}, ! meaning it parses the entire contents of the file. \versionchanged[The \var{headersonly} flag was added]{2.2.2} --- 74,83 ---- The text contained in \var{fp} must be formatted as a block of \rfc{2822} ! style headers and header continuation lines, optionally preceded by a envelope header. The header block is terminated either by the end of the data or by a blank line. Following the header block is the body of the message (which may contain MIME-encoded subparts). ! Optional \var{headersonly} is as with the \method{parse()} method. \versionchanged[The \var{headersonly} flag was added]{2.2.2} *************** *** 105,109 **** \begin{funcdesc}{message_from_string}{s\optional{, _class\optional{, strict}}} ! Return a message object tree from a string. This is exactly equivalent to \code{Parser().parsestr(s)}. Optional \var{_class} and \var{strict} are interpreted as with the \class{Parser} class constructor. --- 103,107 ---- \begin{funcdesc}{message_from_string}{s\optional{, _class\optional{, strict}}} ! Return a message object structure from a string. This is exactly equivalent to \code{Parser().parsestr(s)}. Optional \var{_class} and \var{strict} are interpreted as with the \class{Parser} class constructor. *************** *** 113,119 **** \begin{funcdesc}{message_from_file}{fp\optional{, _class\optional{, strict}}} ! Return a message object tree from an open file object. This is exactly ! equivalent to \code{Parser().parse(fp)}. Optional \var{_class} and ! \var{strict} are interpreted as with the \class{Parser} class constructor. \versionchanged[The \var{strict} flag was added]{2.2.2} --- 111,118 ---- \begin{funcdesc}{message_from_file}{fp\optional{, _class\optional{, strict}}} ! Return a message object structure tree from an open file object. This ! is exactly equivalent to \code{Parser().parse(fp)}. Optional ! \var{_class} and \var{strict} are interpreted as with the ! \class{Parser} class constructor. \versionchanged[The \var{strict} flag was added]{2.2.2} *************** *** 139,145 **** \item All \mimetype{multipart} type messages will be parsed as a container message object with a list of sub-message objects for ! their payload. These messages will return \code{True} for ! \method{is_multipart()} and their \method{get_payload()} method ! will return a list of \class{Message} instances. \item Most messages with a content type of \mimetype{message/*} (e.g. \mimetype{message/deliver-status} and --- 138,145 ---- \item All \mimetype{multipart} type messages will be parsed as a container message object with a list of sub-message objects for ! their payload. The outer container message will return ! \code{True} for \method{is_multipart()} and their ! \method{get_payload()} method will return the list of ! \class{Message} subparts. \item Most messages with a content type of \mimetype{message/*} (e.g. \mimetype{message/deliver-status} and Index: emailutil.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailutil.tex,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** emailutil.tex 1 Oct 2002 01:05:52 -0000 1.7 --- emailutil.tex 1 Oct 2002 04:33:16 -0000 1.8 *************** *** 7,11 **** \begin{funcdesc}{quote}{str} Return a new string with backslashes in \var{str} replaced by two ! backslashes and double quotes replaced by backslash-double quote. \end{funcdesc} --- 7,11 ---- \begin{funcdesc}{quote}{str} Return a new string with backslashes in \var{str} replaced by two ! backslashes, and double quotes replaced by backslash-double quote. \end{funcdesc} *************** *** 86,90 **** \begin{funcdesc}{formatdate}{\optional{timeval\optional{, localtime}}} ! Returns a date string as per Internet standard \rfc{2822}, e.g.: \begin{verbatim} --- 86,90 ---- \begin{funcdesc}{formatdate}{\optional{timeval\optional{, localtime}}} ! Returns a date string as per \rfc{2822}, e.g.: \begin{verbatim} From barry@users.sourceforge.net Tue Oct 1 05:48:09 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 30 Sep 2002 21:48:09 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib email.tex,1.13,1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv21417 Modified Files: email.tex Log Message: Cleaned up the examples. Index: email.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/email.tex,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** email.tex 1 Oct 2002 04:33:12 -0000 1.13 --- email.tex 1 Oct 2002 04:48:06 -0000 1.14 *************** *** 290,302 **** import smtplib ! # Here are the email pacakge modules we'll need ! from email import Encoders from email.MIMEText import MIMEText ! # Open a plain text file for reading ! fp = open(textfile) ! # Create a text/plain message, using Quoted-Printable encoding for non-ASCII ! # characters. ! msg = MIMEText(fp.read(), _encoder=Encoders.encode_quopri) fp.close() --- 290,301 ---- import smtplib ! # Import the email modules we'll need from email.MIMEText import MIMEText ! # Open a plain text file for reading. For this example, assume that ! # the text file contains only ASCII characters. ! fp = open(textfile, 'rb') ! # Create a text/plain message ! msg = MIMEText(fp.read()) fp.close() *************** *** 307,320 **** msg['To'] = you ! # Send the message via our own SMTP server. Use msg.as_string() with ! # unixfrom=0 so as not to confuse SMTP. s = smtplib.SMTP() s.connect() ! s.sendmail(me, [you], msg.as_string(0)) s.close() \end{verbatim} Here's an example of how to send a MIME message containing a bunch of ! family pictures: \begin{verbatim} --- 306,319 ---- msg['To'] = you ! # Send the message via our own SMTP server, but don't include the ! # envelope header. s = smtplib.SMTP() s.connect() ! s.sendmail(me, [you], msg.as_string()) s.close() \end{verbatim} Here's an example of how to send a MIME message containing a bunch of ! family pictures that may be residing in a directory: \begin{verbatim} *************** *** 324,336 **** # Here are the email pacakge modules we'll need from email.MIMEImage import MIMEImage ! from email.MIMEBase import MIMEBase COMMASPACE = ', ' # Create the container (outer) email message. # me == the sender's email address # family = the list of all recipients' email addresses - msg = MIMEBase('multipart', 'mixed') - msg['Subject'] = 'Our family reunion' msg['From'] = me msg['To'] = COMMASPACE.join(family) --- 323,335 ---- # Here are the email pacakge modules we'll need from email.MIMEImage import MIMEImage ! from email.MIMEMultipart import MIMEMultipart COMMASPACE = ', ' # Create the container (outer) email message. + msg = MIMEMultipart() + msg['Subject'] = 'Our family reunion' # me == the sender's email address # family = the list of all recipients' email addresses msg['From'] = me msg['To'] = COMMASPACE.join(family) *************** *** 341,345 **** # Assume we know that the image files are all in PNG format for file in pngfiles: ! # Open the files in binary mode. Let the MIMEIMage class automatically # guess the specific image type. fp = open(file, 'rb') --- 340,344 ---- # Assume we know that the image files are all in PNG format for file in pngfiles: ! # Open the files in binary mode. Let the MIMEImage class automatically # guess the specific image type. fp = open(file, 'rb') *************** *** 351,355 **** s = smtplib.SMTP() s.connect() ! s.sendmail(me, family, msg.as_string(unixfrom=0)) s.close() \end{verbatim} --- 350,354 ---- s = smtplib.SMTP() s.connect() ! s.sendmail(me, family, msg.as_string()) s.close() \end{verbatim} *************** *** 395,399 **** from email.Message import Message from email.MIMEAudio import MIMEAudio ! from email.MIMEBase import MIMEBase from email.MIMEImage import MIMEImage from email.MIMEText import MIMEText --- 394,398 ---- from email.Message import Message from email.MIMEAudio import MIMEAudio ! from email.MIMEMultipart import MIMEMultipart from email.MIMEImage import MIMEImage from email.MIMEText import MIMEText *************** *** 429,433 **** # Create the enclosing (outer) message ! outer = MIMEBase('multipart', 'mixed') outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) outer['To'] = COMMASPACE.join(recips) --- 428,432 ---- # Create the enclosing (outer) message ! outer = MIMEMultipart() outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) outer['To'] = COMMASPACE.join(recips) *************** *** 441,447 **** if not os.path.isfile(path): continue ! # Guess the Content-Type: based on the file's extension. Encoding # will be ignored, although we should check for simple things like ! # gzip'd or compressed files ctype, encoding = mimetypes.guess_type(path) if ctype is None or encoding is not None: --- 440,446 ---- if not os.path.isfile(path): continue ! # Guess the content type based on the file's extension. Encoding # will be ignored, although we should check for simple things like ! # gzip'd or compressed files. ctype, encoding = mimetypes.guess_type(path) if ctype is None or encoding is not None: *************** *** 466,470 **** fp = open(path, 'rb') msg = MIMEBase(maintype, subtype) ! msg.add_payload(fp.read()) fp.close() # Encode the payload using Base64 --- 465,469 ---- fp = open(path, 'rb') msg = MIMEBase(maintype, subtype) ! msg.set_payload(fp.read()) fp.close() # Encode the payload using Base64 *************** *** 474,485 **** outer.attach(msg) - fp = open('/tmp/debug.pck', 'w') - import cPickle - cPickle.dump(outer, fp) - fp.close() # Now send the message s = smtplib.SMTP() s.connect() ! s.sendmail(sender, recips, outer.as_string(0)) s.close() --- 473,480 ---- outer.attach(msg) # Now send the message s = smtplib.SMTP() s.connect() ! s.sendmail(sender, recips, outer.as_string()) s.close() *************** *** 557,561 **** for part in msg.walk(): # multipart/* are just containers ! if part.get_main_type() == 'multipart': continue # Applications should really sanitize the given filename so that an --- 552,556 ---- for part in msg.walk(): # multipart/* are just containers ! if part.get_content_maintype() == 'multipart': continue # Applications should really sanitize the given filename so that an From fdrake@users.sourceforge.net Tue Oct 1 15:17:20 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 01 Oct 2002 07:17:20 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib email-dir.py,NONE,1.1 email-mime.py,NONE,1.1 email-simple.py,NONE,1.1 email-unpack.py,NONE,1.1 email.tex,1.14,1.15 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv9580 Modified Files: email.tex Added Files: email-dir.py email-mime.py email-simple.py email-unpack.py Log Message: Split the long email package examples into separate files and use \verbatiminput instead of the verbatim environment -- this does the "right thing" regarding page breaks in long examples for the typeset formats, and has nice benefits for the HTML version as well. --- NEW FILE: email-dir.py --- #!/usr/bin/env python """Send the contents of a directory as a MIME message. Usage: dirmail [options] from to [to ...]* Options: -h / --help Print this message and exit. -d directory --directory=directory Mail the contents of the specified directory, otherwise use the current directory. Only the regular files in the directory are sent, and we don't recurse to subdirectories. `from' is the email address of the sender of the message. `to' is the email address of the recipient of the message, and multiple recipients may be given. The email is sent by forwarding to your local SMTP server, which then does the normal delivery process. Your local machine must be running an SMTP server. """ import sys import os import getopt import smtplib # For guessing MIME type based on file name extension import mimetypes from email import Encoders from email.Message import Message from email.MIMEAudio import MIMEAudio from email.MIMEMultipart import MIMEMultipart from email.MIMEImage import MIMEImage from email.MIMEText import MIMEText COMMASPACE = ', ' def usage(code, msg=''): print >> sys.stderr, __doc__ if msg: print >> sys.stderr, msg sys.exit(code) def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) except getopt.error, msg: usage(1, msg) dir = os.curdir for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-d', '--directory'): dir = arg if len(args) < 2: usage(1) sender = args[0] recips = args[1:] # Create the enclosing (outer) message outer = MIMEMultipart() outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) outer['To'] = COMMASPACE.join(recips) outer['From'] = sender outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' # To guarantee the message ends with a newline outer.epilogue = '' for filename in os.listdir(dir): path = os.path.join(dir, filename) if not os.path.isfile(path): continue # Guess the content type based on the file's extension. Encoding # will be ignored, although we should check for simple things like # gzip'd or compressed files. ctype, encoding = mimetypes.guess_type(path) if ctype is None or encoding is not None: # No guess could be made, or the file is encoded (compressed), so # use a generic bag-of-bits type. ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) if maintype == 'text': fp = open(path) # Note: we should handle calculating the charset msg = MIMEText(fp.read(), _subtype=subtype) fp.close() elif maintype == 'image': fp = open(path, 'rb') msg = MIMEImage(fp.read(), _subtype=subtype) fp.close() elif maintype == 'audio': fp = open(path, 'rb') msg = MIMEAudio(fp.read(), _subtype=subtype) fp.close() else: fp = open(path, 'rb') msg = MIMEBase(maintype, subtype) msg.set_payload(fp.read()) fp.close() # Encode the payload using Base64 Encoders.encode_base64(msg) # Set the filename parameter msg.add_header('Content-Disposition', 'attachment', filename=filename) outer.attach(msg) # Now send the message s = smtplib.SMTP() s.connect() s.sendmail(sender, recips, outer.as_string()) s.close() if __name__ == '__main__': main() --- NEW FILE: email-mime.py --- # Import smtplib for the actual sending function import smtplib # Here are the email pacakge modules we'll need from email.MIMEImage import MIMEImage from email.MIMEMultipart import MIMEMultipart COMMASPACE = ', ' # Create the container (outer) email message. msg = MIMEMultipart() msg['Subject'] = 'Our family reunion' # me == the sender's email address # family = the list of all recipients' email addresses msg['From'] = me msg['To'] = COMMASPACE.join(family) msg.preamble = 'Our family reunion' # Guarantees the message ends in a newline msg.epilogue = '' # Assume we know that the image files are all in PNG format for file in pngfiles: # Open the files in binary mode. Let the MIMEImage class automatically # guess the specific image type. fp = open(file, 'rb') img = MIMEImage(fp.read()) fp.close() msg.attach(img) # Send the email via our own SMTP server. s = smtplib.SMTP() s.connect() s.sendmail(me, family, msg.as_string()) s.close() --- NEW FILE: email-simple.py --- # Import smtplib for the actual sending function import smtplib # Import the email modules we'll need from email.MIMEText import MIMEText # Open a plain text file for reading. For this example, assume that # the text file contains only ASCII characters. fp = open(textfile, 'rb') # Create a text/plain message msg = MIMEText(fp.read()) fp.close() # me == the sender's email address # you == the recipient's email address msg['Subject'] = 'The contents of %s' % textfile msg['From'] = me msg['To'] = you # Send the message via our own SMTP server, but don't include the # envelope header. s = smtplib.SMTP() s.connect() s.sendmail(me, [you], msg.as_string()) s.close() --- NEW FILE: email-unpack.py --- #!/usr/bin/env python """Unpack a MIME message into a directory of files. Usage: unpackmail [options] msgfile Options: -h / --help Print this message and exit. -d directory --directory=directory Unpack the MIME message into the named directory, which will be created if it doesn't already exist. msgfile is the path to the file containing the MIME message. """ import sys import os import getopt import errno import mimetypes import email def usage(code, msg=''): print >> sys.stderr, __doc__ if msg: print >> sys.stderr, msg sys.exit(code) def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) except getopt.error, msg: usage(1, msg) dir = os.curdir for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-d', '--directory'): dir = arg try: msgfile = args[0] except IndexError: usage(1) try: os.mkdir(dir) except OSError, e: # Ignore directory exists error if e.errno <> errno.EEXIST: raise fp = open(msgfile) msg = email.message_from_file(fp) fp.close() counter = 1 for part in msg.walk(): # multipart/* are just containers if part.get_content_maintype() == 'multipart': continue # Applications should really sanitize the given filename so that an # email message can't be used to overwrite important files filename = part.get_filename() if not filename: ext = mimetypes.guess_extension(part.get_type()) if not ext: # Use a generic bag-of-bits extension ext = '.bin' filename = 'part-%03d%s' % (counter, ext) counter += 1 fp = open(os.path.join(dir, filename), 'wb') fp.write(part.get_payload(decode=1)) fp.close() if __name__ == '__main__': main() Index: email.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/email.tex,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** email.tex 1 Oct 2002 04:48:06 -0000 1.14 --- email.tex 1 Oct 2002 14:17:10 -0000 1.15 *************** *** 286,356 **** First, let's see how to create and send a simple text message: ! \begin{verbatim} ! # Import smtplib for the actual sending function ! import smtplib ! ! # Import the email modules we'll need ! from email.MIMEText import MIMEText ! ! # Open a plain text file for reading. For this example, assume that ! # the text file contains only ASCII characters. ! fp = open(textfile, 'rb') ! # Create a text/plain message ! msg = MIMEText(fp.read()) ! fp.close() ! ! # me == the sender's email address ! # you == the recipient's email address ! msg['Subject'] = 'The contents of %s' % textfile ! msg['From'] = me ! msg['To'] = you ! ! # Send the message via our own SMTP server, but don't include the ! # envelope header. ! s = smtplib.SMTP() ! s.connect() ! s.sendmail(me, [you], msg.as_string()) ! s.close() ! \end{verbatim} Here's an example of how to send a MIME message containing a bunch of family pictures that may be residing in a directory: ! \begin{verbatim} ! # Import smtplib for the actual sending function ! import smtplib ! ! # Here are the email pacakge modules we'll need ! from email.MIMEImage import MIMEImage ! from email.MIMEMultipart import MIMEMultipart ! ! COMMASPACE = ', ' ! ! # Create the container (outer) email message. ! msg = MIMEMultipart() ! msg['Subject'] = 'Our family reunion' ! # me == the sender's email address ! # family = the list of all recipients' email addresses ! msg['From'] = me ! msg['To'] = COMMASPACE.join(family) ! msg.preamble = 'Our family reunion' ! # Guarantees the message ends in a newline ! msg.epilogue = '' ! ! # Assume we know that the image files are all in PNG format ! for file in pngfiles: ! # Open the files in binary mode. Let the MIMEImage class automatically ! # guess the specific image type. ! fp = open(file, 'rb') ! img = MIMEImage(fp.read()) ! fp.close() ! msg.attach(img) ! ! # Send the email via our own SMTP server. ! s = smtplib.SMTP() ! s.connect() ! s.sendmail(me, family, msg.as_string()) ! s.close() ! \end{verbatim} Here's an example\footnote{Thanks to Matthew Dixon Cowles for the --- 286,295 ---- First, let's see how to create and send a simple text message: ! \verbatiminput{email-simple.py} Here's an example of how to send a MIME message containing a bunch of family pictures that may be residing in a directory: ! \verbatiminput{email-mime.py} Here's an example\footnote{Thanks to Matthew Dixon Cowles for the *************** *** 358,573 **** of a directory as an email message: ! \begin{verbatim} ! #!/usr/bin/env python ! ! """Send the contents of a directory as a MIME message. ! ! Usage: dirmail [options] from to [to ...]* ! ! Options: ! -h / --help ! Print this message and exit. ! ! -d directory ! --directory=directory ! Mail the contents of the specified directory, otherwise use the ! current directory. Only the regular files in the directory are sent, ! and we don't recurse to subdirectories. ! ! `from' is the email address of the sender of the message. ! ! `to' is the email address of the recipient of the message, and multiple ! recipients may be given. ! ! The email is sent by forwarding to your local SMTP server, which then does the ! normal delivery process. Your local machine must be running an SMTP server. ! """ ! ! import sys ! import os ! import getopt ! import smtplib ! # For guessing MIME type based on file name extension ! import mimetypes ! ! from email import Encoders ! from email.Message import Message ! from email.MIMEAudio import MIMEAudio ! from email.MIMEMultipart import MIMEMultipart ! from email.MIMEImage import MIMEImage ! from email.MIMEText import MIMEText ! ! COMMASPACE = ', ' ! ! ! def usage(code, msg=''): ! print >> sys.stderr, __doc__ ! if msg: ! print >> sys.stderr, msg ! sys.exit(code) ! ! ! def main(): ! try: ! opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) ! except getopt.error, msg: ! usage(1, msg) ! ! dir = os.curdir ! for opt, arg in opts: ! if opt in ('-h', '--help'): ! usage(0) ! elif opt in ('-d', '--directory'): ! dir = arg ! ! if len(args) < 2: ! usage(1) ! ! sender = args[0] ! recips = args[1:] ! ! # Create the enclosing (outer) message ! outer = MIMEMultipart() ! outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) ! outer['To'] = COMMASPACE.join(recips) ! outer['From'] = sender ! outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' ! # To guarantee the message ends with a newline ! outer.epilogue = '' ! ! for filename in os.listdir(dir): ! path = os.path.join(dir, filename) ! if not os.path.isfile(path): ! continue ! # Guess the content type based on the file's extension. Encoding ! # will be ignored, although we should check for simple things like ! # gzip'd or compressed files. ! ctype, encoding = mimetypes.guess_type(path) ! if ctype is None or encoding is not None: ! # No guess could be made, or the file is encoded (compressed), so ! # use a generic bag-of-bits type. ! ctype = 'application/octet-stream' ! maintype, subtype = ctype.split('/', 1) ! if maintype == 'text': ! fp = open(path) ! # Note: we should handle calculating the charset ! msg = MIMEText(fp.read(), _subtype=subtype) ! fp.close() ! elif maintype == 'image': ! fp = open(path, 'rb') ! msg = MIMEImage(fp.read(), _subtype=subtype) ! fp.close() ! elif maintype == 'audio': ! fp = open(path, 'rb') ! msg = MIMEAudio(fp.read(), _subtype=subtype) ! fp.close() ! else: ! fp = open(path, 'rb') ! msg = MIMEBase(maintype, subtype) ! msg.set_payload(fp.read()) ! fp.close() ! # Encode the payload using Base64 ! Encoders.encode_base64(msg) ! # Set the filename parameter ! msg.add_header('Content-Disposition', 'attachment', filename=filename) ! outer.attach(msg) ! ! # Now send the message ! s = smtplib.SMTP() ! s.connect() ! s.sendmail(sender, recips, outer.as_string()) ! s.close() ! ! ! if __name__ == '__main__': ! main() ! \end{verbatim} And finally, here's an example of how to unpack a MIME message like the one above, into a directory of files: ! \begin{verbatim} ! #!/usr/bin/env python ! ! """Unpack a MIME message into a directory of files. ! ! Usage: unpackmail [options] msgfile ! ! Options: ! -h / --help ! Print this message and exit. ! ! -d directory ! --directory=directory ! Unpack the MIME message into the named directory, which will be ! created if it doesn't already exist. ! ! msgfile is the path to the file containing the MIME message. ! """ ! ! import sys ! import os ! import getopt ! import errno ! import mimetypes ! import email ! ! ! def usage(code, msg=''): ! print >> sys.stderr, __doc__ ! if msg: ! print >> sys.stderr, msg ! sys.exit(code) ! ! ! def main(): ! try: ! opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) ! except getopt.error, msg: ! usage(1, msg) ! ! dir = os.curdir ! for opt, arg in opts: ! if opt in ('-h', '--help'): ! usage(0) ! elif opt in ('-d', '--directory'): ! dir = arg ! ! try: ! msgfile = args[0] ! except IndexError: ! usage(1) ! ! try: ! os.mkdir(dir) ! except OSError, e: ! # Ignore directory exists error ! if e.errno <> errno.EEXIST: raise ! ! fp = open(msgfile) ! msg = email.message_from_file(fp) ! fp.close() ! ! counter = 1 ! for part in msg.walk(): ! # multipart/* are just containers ! if part.get_content_maintype() == 'multipart': ! continue ! # Applications should really sanitize the given filename so that an ! # email message can't be used to overwrite important files ! filename = part.get_filename() ! if not filename: ! ext = mimetypes.guess_extension(part.get_type()) ! if not ext: ! # Use a generic bag-of-bits extension ! ext = '.bin' ! filename = 'part-%03d%s' % (counter, ext) ! counter += 1 ! fp = open(os.path.join(dir, filename), 'wb') ! fp.write(part.get_payload(decode=1)) ! fp.close() ! ! ! if __name__ == '__main__': ! main() ! \end{verbatim} --- 297,304 ---- of a directory as an email message: ! \verbatiminput{email-dir.py} And finally, here's an example of how to unpack a MIME message like the one above, into a directory of files: ! \verbatiminput{email-unpack.py} From fdrake@users.sourceforge.net Tue Oct 1 15:30:00 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 01 Oct 2002 07:30:00 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib emailmessage.tex,1.7,1.8 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv15298 Modified Files: emailmessage.tex Log Message: Minor style nit for referring to other attributes of the same class from an attributes description. Index: emailmessage.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailmessage.tex,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** emailmessage.tex 1 Oct 2002 04:33:16 -0000 1.7 --- emailmessage.tex 1 Oct 2002 14:29:58 -0000 1.8 *************** *** 40,44 **** \begin{methoddesc}[Message]{__str__}{} ! Equivalent to \method{aMessage.as_string(unixfrom=True)}. \end{methoddesc} --- 40,44 ---- \begin{methoddesc}[Message]{__str__}{} ! Equivalent to \method{as_string(unixfrom=True)}. \end{methoddesc} From fdrake@users.sourceforge.net Tue Oct 1 15:38:49 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 01 Oct 2002 07:38:49 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib mimelib.tex,NONE,1.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv18923 Added Files: mimelib.tex Log Message: Stub document for the stand-alone email package distribution. Barry, please add a reasonable abstract! --- NEW FILE: mimelib.tex --- \documentclass{howto} \title{email Package Reference} \author{Barry Warsaw} \authoraddress{\email{barry@zope.com}} \date{\today} \release{2.4} % software release, not documentation \setreleaseinfo{} % empty for final release \setshortversion{2.4} % major.minor only for software \begin{document} \maketitle \begin{abstract} The \module{email} package can be used to handle email. \end{abstract} % The ugly "%begin{latexonly}" pseudo-environment supresses the table % of contents for HTML generation. % %begin{latexonly} \tableofcontents %end{latexonly} \input{email} \end{document} From barry@users.sourceforge.net Tue Oct 1 16:13:33 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Tue, 01 Oct 2002 08:13:33 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib mimelib.tex,1.1,1.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv32371 Modified Files: mimelib.tex Log Message: Added an introduction. Index: mimelib.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/mimelib.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** mimelib.tex 1 Oct 2002 14:38:47 -0000 1.1 --- mimelib.tex 1 Oct 2002 15:13:29 -0000 1.2 *************** *** 15,19 **** \begin{abstract} ! The \module{email} package can be used to handle email. \end{abstract} --- 15,21 ---- \begin{abstract} ! The \module{email} package provides classes and utilities to create, ! parse, generate, and modify email messages, conforming to all the ! relevant email and MIME related RFCs. \end{abstract} *************** *** 24,27 **** --- 26,83 ---- \tableofcontents %end{latexonly} + + \section{Introduction} + The \module{email} package provides classes and utilities to create, + parse, generate, and modify email messages, conforming to all the + relevant email and MIME related RFCs. + + This document describes the current version of the \module{email} + package, which is available to Python programmers in a number of ways. + Python 2.2.2 and 2.3 come with \module{email} version 2, while earlier + versions of Python 2.2.x come with \module{email} version 1. Python + 2.1.x and earlier do not come with any version of the \module{email} + package. + + The \module{email} package is also available as a standalone distutils + package, and is compatible with Python 2.1.3 and beyond. Thus, if + you're using Python 2.1.3 you can download the standalone package and + install it in your \file{site-packages} directory. The standalone + \module{email} package is available on the + \ulink{SourceForge \module{mimelib} project}{http://mimelib.sf.net}. + + The documentation that follows was written for the Python project, so + if you're reading this as part of the standalone \module{email} + package documentation, there are a few notes to be aware of: + + \begin{itemize} + \item Deprecation and ``version added'' notes are relative to the + Python version a feature was added or deprecated. To find out + what version of the \module{email} package a particular item was + added, changed, or removed, refer to the package's + \ulink{\file{NEWS} file}{http://cvs.sf.net/cgi-bin/viewcvs.cgi/mimelib/mimelib/NEWS?rev=1.36&content-type=text/vnd.viewcvs-markup}. + + \item The code samples are written with Python 2.2 in mind. For + Python 2.1.3, some adjustments are necessary. For example, this + code snippet; + + \begin{verbatim} + if isinstance(s, str): + # ... + \end{verbatim} + + would need to be written this way in Python 2.1.3: + + \begin{verbatim} + from types import StringType + # ... + if isinstance(s, StringType): + # ... + \end{verbatim} + + \item If you're reading this documentation as part of the + standalone \module{email} package, some of the internal links to + other sections of the Python standard library may not resolve. + + \end{itemize} \input{email} From fdrake@users.sourceforge.net Tue Oct 1 16:20:22 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 01 Oct 2002 08:20:22 -0700 Subject: [Python-checkins] python/dist/src/Doc/tools mkhowto,1.32,1.33 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tools In directory usw-pr-cvs1:/tmp/cvs-serv2304/tools Modified Files: mkhowto Log Message: Change the default path to icons so that "mkhowto" does the "right thing" by default when used for 3rd-party docs. This requires the standard Python docs to specify a location, but they are a bit of a special case in sharing one set of icons among several documents. Index: mkhowto =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tools/mkhowto,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -d -r1.32 -r1.33 *** mkhowto 27 Aug 2002 16:34:54 -0000 1.32 --- mkhowto 1 Oct 2002 15:20:20 -0000 1.33 *************** *** 16,20 **** --link Specify the number of levels to include on each page. --split, -s Specify a section level for page splitting, default: %(max_split_depth)s. ! --iconserver, -i Specify location of icons (default: ../). --image-type Specify the image type to use in HTML output; values: gif (default), png. --- 16,20 ---- --link Specify the number of levels to include on each page. --split, -s Specify a section level for page splitting, default: %(max_split_depth)s. ! --iconserver, -i Specify location of icons (default: ./). --image-type Specify the image type to use in HTML output; values: gif (default), png. *************** *** 94,98 **** discard_temps = 1 have_temps = 0 ! icon_server = None image_type = "gif" logging = 0 --- 94,98 ---- discard_temps = 1 have_temps = 0 ! icon_server = "." image_type = "gif" logging = 0 From fdrake@users.sourceforge.net Tue Oct 1 16:20:22 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 01 Oct 2002 08:20:22 -0700 Subject: [Python-checkins] python/dist/src/Doc/perl l2hinit.perl,1.63,1.64 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/perl In directory usw-pr-cvs1:/tmp/cvs-serv2304/perl Modified Files: l2hinit.perl Log Message: Change the default path to icons so that "mkhowto" does the "right thing" by default when used for 3rd-party docs. This requires the standard Python docs to specify a location, but they are a bit of a special case in sharing one set of icons among several documents. Index: l2hinit.perl =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/perl/l2hinit.perl,v retrieving revision 1.63 retrieving revision 1.64 diff -C2 -d -r1.63 -r1.64 *** l2hinit.perl 23 May 2002 17:59:16 -0000 1.63 --- l2hinit.perl 1 Oct 2002 15:20:19 -0000 1.64 *************** *** 18,22 **** $SHOW_SECTION_NUMBERS = 1; ! $ICONSERVER = '../icons'; $IMAGE_TYPE = 'gif'; --- 18,22 ---- $SHOW_SECTION_NUMBERS = 1; ! $ICONSERVER = '.'; $IMAGE_TYPE = 'gif'; From fdrake@users.sourceforge.net Tue Oct 1 16:20:21 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 01 Oct 2002 08:20:21 -0700 Subject: [Python-checkins] python/dist/src/Doc Makefile,1.245,1.246 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory usw-pr-cvs1:/tmp/cvs-serv2304 Modified Files: Makefile Log Message: Change the default path to icons so that "mkhowto" does the "right thing" by default when used for 3rd-party docs. This requires the standard Python docs to specify a location, but they are a bit of a special case in sharing one set of icons among several documents. Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile,v retrieving revision 1.245 retrieving revision 1.246 diff -C2 -d -r1.245 -r1.246 *** Makefile 9 Aug 2002 20:20:50 -0000 1.245 --- Makefile 1 Oct 2002 15:20:18 -0000 1.246 *************** *** 74,81 **** --- 74,83 ---- MKDVI= $(PYTHON) ../tools/mkhowto --paper=$(PAPER) --dvi MKHTML= $(PYTHON) tools/mkhowto --html --about html/stdabout.dat \ + --iconserver ../icons \ --address $(PYTHONDOCS) --up-link ../index.html \ --up-title "Python Documentation Index" \ --global-module-index "../modindex.html" --dvips-safe MKISILOHTML=$(PYTHON) tools/mkhowto --html --about html/stdabout.dat \ + --iconserver ../icons \ --l2h-init perl/isilo.perl --numeric --split 1 \ --dvips-safe From fdrake@users.sourceforge.net Tue Oct 1 16:24:06 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 01 Oct 2002 08:24:06 -0700 Subject: [Python-checkins] python/dist/src/Doc/tools mkhowto,1.33,1.34 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tools In directory usw-pr-cvs1:/tmp/cvs-serv3668 Modified Files: mkhowto Log Message: Include the --dir argument in the help text. Index: mkhowto =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tools/mkhowto,v retrieving revision 1.33 retrieving revision 1.34 diff -C2 -d -r1.33 -r1.34 *** mkhowto 1 Oct 2002 15:20:20 -0000 1.33 --- mkhowto 1 Oct 2002 15:24:03 -0000 1.34 *************** *** 14,17 **** --- 14,18 ---- HTML options: --address, -a Specify an address for page footers. + --dir Specify the directory for HTML output. --link Specify the number of levels to include on each page. --split, -s Specify a section level for page splitting, default: %(max_split_depth)s. From barry@users.sourceforge.net Tue Oct 1 16:29:11 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Tue, 01 Oct 2002 08:29:11 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib email.tex,1.15,1.16 emailgenerator.tex,1.5,1.6 emailparser.tex,1.7,1.8 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv5163 Modified Files: email.tex emailgenerator.tex emailparser.tex Log Message: nits Index: email.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/email.tex,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** email.tex 1 Oct 2002 14:17:10 -0000 1.15 --- email.tex 1 Oct 2002 15:29:08 -0000 1.16 *************** *** 101,104 **** --- 101,105 ---- \item The \module{email.Header} and \module{email.Charset} modules have been added. + \item The pickle format for \class{Message} instances has changed. Since this was never (and still isn't) formally defined, this *************** *** 108,111 **** --- 109,113 ---- instances now have private variables \var{_charset} and \var{_default_type}. + \item Several methods in the \class{Message} class have been deprecated, or their signatures changed. Also, many new methods *************** *** 113,116 **** --- 115,119 ---- class for details. The changes should be completely backward compatible. + \item The object structure has changed in the face of \mimetype{message/rfc822} content types. In \module{email} *************** *** 133,136 **** --- 136,140 ---- \method{set_payload()} with a \class{Message} instance on a container with a content type of \mimetype{message/rfc822}. + \item The \class{Parser} constructor's \var{strict} argument was added, and its \method{parse()} and \method{parsestr()} methods *************** *** 138,153 **** --- 142,162 ---- also added to functions \function{email.message_from_file()} and \function{email.message_from_string()}. + \item \method{Generator.__call__()} is deprecated; use \method{Generator.flatten()} instead. The \class{Generator} class has also grown the \method{clone()} method. + \item The \class{DecodedGenerator} class in the \module{email.Generator} module was added. + \item The intermediate base classes \class{MIMENonMultipart} and \class{MIMEMultipart} have been added, and interposed in the class hierarchy for most of the other MIME-related derived classes. + \item The \var{_encoder} argument to the \class{MIMEText} constructor has been deprecated. Encoding now happens implicitly based on the \var{_charset} argument. + \item The following functions in the \module{email.Utils} module have been deprecated: \function{dump_address_pairs()}, *************** *** 156,159 **** --- 165,169 ---- \function{make_msgid()}, \function{decode_rfc2231()}, \function{encode_rfc2231()}, and \function{decode_params()}. + \item The non-public function \function{email.Iterators._structure()} was added. *************** *** 185,190 **** --- 195,202 ---- \item \function{messageFromString()} has been renamed to \function{message_from_string()}. + \item \function{messageFromFile()} has been renamed to \function{message_from_file()}. + \end{itemize} *************** *** 193,207 **** --- 205,227 ---- \begin{itemize} \item The method \method{asString()} was renamed to \method{as_string()}. + \item The method \method{ismultipart()} was renamed to \method{is_multipart()}. + \item The \method{get_payload()} method has grown a \var{decode} optional argument. + \item The method \method{getall()} was renamed to \method{get_all()}. + \item The method \method{addheader()} was renamed to \method{add_header()}. + \item The method \method{gettype()} was renamed to \method{get_type()}. + \item The method\method{getmaintype()} was renamed to \method{get_main_type()}. + \item The method \method{getsubtype()} was renamed to \method{get_subtype()}. + \item The method \method{getparams()} was renamed to \method{get_params()}. *************** *** 210,229 **** --- 230,257 ---- the key/value pairs of the parameters, split on the \character{=} sign. + \item The method \method{getparam()} was renamed to \method{get_param()}. + \item The method \method{getcharsets()} was renamed to \method{get_charsets()}. + \item The method \method{getfilename()} was renamed to \method{get_filename()}. + \item The method \method{getboundary()} was renamed to \method{get_boundary()}. + \item The method \method{setboundary()} was renamed to \method{set_boundary()}. + \item The method \method{getdecodedpayload()} was removed. To get similar functionality, pass the value 1 to the \var{decode} flag of the {get_payload()} method. + \item The method \method{getpayloadastext()} was removed. Similar functionality is supported by the \class{DecodedGenerator} class in the \refmodule{email.Generator} module. + \item The method \method{getbodyastext()} was removed. You can get similar functionality by creating an iterator with *************** *** 252,261 **** --- 280,292 ---- and \var{_minor} have changed to \var{_maintype} and \var{_subtype} respectively. + \item The \code{Image} class/module has been renamed to \code{MIMEImage}. The \var{_minor} argument has been renamed to \var{_subtype}. + \item The \code{Text} class/module has been renamed to \code{MIMEText}. The \var{_minor} argument has been renamed to \var{_subtype}. + \item The \code{MessageRFC822} class/module has been renamed to \code{MIMEMessage}. Note that an earlier version of Index: emailgenerator.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailgenerator.tex,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** emailgenerator.tex 1 Oct 2002 04:33:14 -0000 1.5 --- emailgenerator.tex 1 Oct 2002 15:29:09 -0000 1.6 *************** *** 106,116 **** --- 106,122 ---- \begin{itemize} \item \code{type} -- Full MIME type of the non-\mimetype{text} part + \item \code{maintype} -- Main MIME type of the non-\mimetype{text} part + \item \code{subtype} -- Sub-MIME type of the non-\mimetype{text} part + \item \code{filename} -- Filename of the non-\mimetype{text} part + \item \code{description} -- Description associated with the non-\mimetype{text} part + \item \code{encoding} -- Content transfer encoding of the non-\mimetype{text} part + \end{itemize} Index: emailparser.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailparser.tex,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** emailparser.tex 1 Oct 2002 04:33:16 -0000 1.7 --- emailparser.tex 1 Oct 2002 15:29:09 -0000 1.8 *************** *** 136,139 **** --- 136,140 ---- \code{False} for \method{is_multipart()}. Their \method{get_payload()} method will return a string object. + \item All \mimetype{multipart} type messages will be parsed as a container message object with a list of sub-message objects for *************** *** 142,145 **** --- 143,147 ---- \method{get_payload()} method will return the list of \class{Message} subparts. + \item Most messages with a content type of \mimetype{message/*} (e.g. \mimetype{message/deliver-status} and From fdrake@users.sourceforge.net Tue Oct 1 16:30:59 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 01 Oct 2002 08:30:59 -0700 Subject: [Python-checkins] python/dist/src/Doc/tools mkhowto,1.34,1.35 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tools In directory usw-pr-cvs1:/tmp/cvs-serv5567 Modified Files: mkhowto Log Message: When the HTML output dir is specified using --dir=~/foo, the tilde needs to be expanded by mkhowto, since the shell won't touch it except at the start of the complete argument. Index: mkhowto =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tools/mkhowto,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -d -r1.34 -r1.35 *** mkhowto 1 Oct 2002 15:24:03 -0000 1.34 --- mkhowto 1 Oct 2002 15:30:56 -0000 1.35 *************** *** 206,210 **** if os.sep == "\\": arg = re.sub("/", "\\", arg) ! self.builddir = arg elif opt == "--paper": self.paper = arg --- 206,210 ---- if os.sep == "\\": arg = re.sub("/", "\\", arg) ! self.builddir = os.path.expanduser(arg) elif opt == "--paper": self.paper = arg From barry@users.sourceforge.net Tue Oct 1 16:38:04 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Tue, 01 Oct 2002 08:38:04 -0700 Subject: [Python-checkins] python/dist/src/Doc/tools mkhowto,1.35,1.36 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tools In directory usw-pr-cvs1:/tmp/cvs-serv7534 Modified Files: mkhowto Log Message: build(): Use self.builddir, not self.doc when copying the icons, so they'll end up in the right directory when --dir is used. Index: mkhowto =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tools/mkhowto,v retrieving revision 1.35 retrieving revision 1.36 diff -C2 -d -r1.35 -r1.36 *** mkhowto 1 Oct 2002 15:30:56 -0000 1.35 --- mkhowto 1 Oct 2002 15:38:01 -0000 1.36 *************** *** 295,299 **** % `self.options.image_type`) for fn in imgs: ! new_fn = os.path.join(self.doc, os.path.basename(fn)) shutil.copyfile(fn, new_fn) if "text" in formats: --- 295,299 ---- % `self.options.image_type`) for fn in imgs: ! new_fn = os.path.join(self.builddir, os.path.basename(fn)) shutil.copyfile(fn, new_fn) if "text" in formats: From montanaro@users.sourceforge.net Tue Oct 1 18:40:02 2002 From: montanaro@users.sourceforge.net (montanaro@users.sourceforge.net) Date: Tue, 01 Oct 2002 10:40:02 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils ccompiler.py,1.48,1.49 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/distutils In directory usw-pr-cvs1:/tmp/cvs-serv19762 Modified Files: ccompiler.py Log Message: save the verbose argument as an instance attributes. Subclasses of CCompiler may rely on the presence of self.verbose (SciPy's distutils appears to). Index: ccompiler.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/distutils/ccompiler.py,v retrieving revision 1.48 retrieving revision 1.49 diff -C2 -d -r1.48 -r1.49 *** ccompiler.py 1 Oct 2002 04:14:17 -0000 1.48 --- ccompiler.py 1 Oct 2002 17:39:59 -0000 1.49 *************** *** 83,86 **** --- 83,87 ---- self.dry_run = dry_run self.force = force + self.verbose = verbose # 'output_dir': a common output directory for object, library, From loewis@users.sourceforge.net Tue Oct 1 18:48:34 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Tue, 01 Oct 2002 10:48:34 -0700 Subject: [Python-checkins] python/dist/src/Modules _tkinter.c,1.127,1.128 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv22703 Modified Files: _tkinter.c Log Message: Drop support for Tk 8.0 and 8.1. Index: _tkinter.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_tkinter.c,v retrieving revision 1.127 retrieving revision 1.128 diff -C2 -d -r1.127 -r1.128 *** _tkinter.c 23 Jul 2002 06:31:14 -0000 1.127 --- _tkinter.c 1 Oct 2002 17:48:31 -0000 1.128 *************** *** 52,57 **** #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) ! #if TKMAJORMINOR < 8000 ! #error "Tk older than 8.0 not supported" #endif --- 52,57 ---- #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) ! #if TKMAJORMINOR < 8002 ! #error "Tk older than 8.2 not supported" #endif *************** *** 499,508 **** /** Tcl Eval **/ - #if TKMAJORMINOR >= 8001 - #define USING_OBJECTS - #endif - - #ifdef USING_OBJECTS - static Tcl_Obj* AsObj(PyObject *value) --- 499,502 ---- *************** *** 531,544 **** #ifdef Py_USING_UNICODE else if (PyUnicode_Check(value)) { - #if TKMAJORMINOR <= 8001 - /* In Tcl 8.1 we must use UTF-8 */ - PyObject* utf8 = PyUnicode_AsUTF8String(value); - if (!utf8) - return 0; - result = Tcl_NewStringObj(PyString_AS_STRING(utf8), - PyString_GET_SIZE(utf8)); - Py_DECREF(utf8); - return result; - #else /* TKMAJORMINOR > 8001 */ /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */ if (sizeof(Py_UNICODE) != sizeof(Tcl_UniChar)) { --- 525,528 ---- *************** *** 550,554 **** return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value), PyUnicode_GET_SIZE(value)); - #endif /* TKMAJORMINOR > 8001 */ } #endif --- 534,537 ---- *************** *** 664,785 **** } - #else /* !USING_OBJECTS */ - - static PyObject * - Tkapp_Call(PyObject *self, PyObject *args) - { - /* This is copied from Merge() */ - PyObject *tmp = NULL; - char *argvStore[ARGSZ]; - char **argv = NULL; - int fvStore[ARGSZ]; - int *fv = NULL; - int argc = 0, fvc = 0, i; - PyObject *res = NULL; /* except this has a different type */ - Tcl_CmdInfo info; /* and this is added */ - Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */ - - if (!(tmp = PyList_New(0))) - return NULL; - - argv = argvStore; - fv = fvStore; - - if (args == NULL) - argc = 0; - - else if (!PyTuple_Check(args)) { - argc = 1; - fv[0] = 0; - if (!(argv[0] = AsString(args, tmp))) - goto finally; - } - else { - argc = PyTuple_Size(args); - - if (argc > ARGSZ) { - argv = (char **)ckalloc(argc * sizeof(char *)); - fv = (int *)ckalloc(argc * sizeof(int)); - if (argv == NULL || fv == NULL) { - PyErr_NoMemory(); - goto finally; - } - } - - for (i = 0; i < argc; i++) { - PyObject *v = PyTuple_GetItem(args, i); - if (PyTuple_Check(v)) { - fv[i] = 1; - if (!(argv[i] = Merge(v))) - goto finally; - fvc++; - } - else if (v == Py_None) { - argc = i; - break; - } - else { - fv[i] = 0; - if (!(argv[i] = AsString(v, tmp))) - goto finally; - fvc++; - } - } - } - /* End code copied from Merge() */ - - /* All this to avoid a call to Tcl_Merge() and the corresponding call - to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */ - if (Py_VerboseFlag >= 2) { - for (i = 0; i < argc; i++) - PySys_WriteStderr("%s ", argv[i]); - } - ENTER_TCL - info.proc = NULL; - if (argc < 1 || - !Tcl_GetCommandInfo(interp, argv[0], &info) || - info.proc == NULL) - { - char *cmd; - cmd = Tcl_Merge(argc, argv); - i = Tcl_Eval(interp, cmd); - ckfree(cmd); - } - else { - Tcl_ResetResult(interp); - i = (*info.proc)(info.clientData, interp, argc, argv); - } - ENTER_OVERLAP - if (info.proc == NULL && Py_VerboseFlag >= 2) - PySys_WriteStderr("... use TclEval "); - if (i == TCL_ERROR) { - if (Py_VerboseFlag >= 2) - PySys_WriteStderr("... error: '%s'\n", - Tcl_GetStringResult(interp)); - Tkinter_Error(self); - } - else { - if (Py_VerboseFlag >= 2) - PySys_WriteStderr("-> '%s'\n", Tcl_GetStringResult(interp)); - res = PyString_FromString(Tcl_GetStringResult(interp)); - } - LEAVE_OVERLAP_TCL - - /* Copied from Merge() again */ - finally: - for (i = 0; i < fvc; i++) - if (fv[i]) { - ckfree(argv[i]); - } - if (argv != argvStore) - ckfree(FREECAST argv); - if (fv != fvStore) - ckfree(FREECAST fv); - - Py_DECREF(tmp); - return res; - } - - #endif /* !USING_OBJECTS */ static PyObject * --- 647,650 ---- From barry@users.sourceforge.net Tue Oct 1 18:57:08 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Tue, 01 Oct 2002 10:57:08 -0700 Subject: [Python-checkins] python/dist/src/Lib/email/test test_email.py,1.16,1.17 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email/test In directory usw-pr-cvs1:/tmp/cvs-serv25649 Modified Files: test_email.py Log Message: test__all__(): Fix the import list. Index: test_email.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/test/test_email.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** test_email.py 30 Sep 2002 15:23:17 -0000 1.16 --- test_email.py 1 Oct 2002 17:57:06 -0000 1.17 *************** *** 1605,1612 **** all.sort() self.assertEqual(all, ['Charset', 'Encoders', 'Errors', 'Generator', ! 'Header', 'Iterators', 'MIMEAudio', ! 'MIMEBase', 'MIMEImage', 'MIMEMessage', ! 'MIMEText', 'Message', 'Parser', ! 'Utils', 'base64MIME', 'message_from_file', 'message_from_string', 'quopriMIME']) --- 1605,1612 ---- all.sort() self.assertEqual(all, ['Charset', 'Encoders', 'Errors', 'Generator', ! 'Header', 'Iterators', 'MIMEAudio', 'MIMEBase', ! 'MIMEImage', 'MIMEMessage', 'MIMEMultipart', ! 'MIMENonMultipart', 'MIMEText', 'Message', ! 'Parser', 'Utils', 'base64MIME', 'message_from_file', 'message_from_string', 'quopriMIME']) From loewis@users.sourceforge.net Tue Oct 1 19:08:08 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Tue, 01 Oct 2002 11:08:08 -0700 Subject: [Python-checkins] python/dist/src/Modules _tkinter.c,1.128,1.129 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv29494 Modified Files: _tkinter.c Log Message: Eliminate constness warnings with Tcl 8.4. Index: _tkinter.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_tkinter.c,v retrieving revision 1.128 retrieving revision 1.129 diff -C2 -d -r1.128 -r1.129 *** _tkinter.c 1 Oct 2002 17:48:31 -0000 1.128 --- _tkinter.c 1 Oct 2002 18:08:06 -0000 1.129 *************** *** 42,45 **** --- 42,52 ---- #endif + /* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately, + making _tkinter correct for this API means to break earlier + versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and + earlier versions. Once Tcl releases before 8.4 don't need to be supported + anymore, this should go. */ + #define USE_COMPAT_CONST + #ifdef TK_FRAMEWORK #include *************** *** 608,613 **** /* We could request the object result here, but doing so would confuse applications that expect a string. */ ! char *s = Tcl_GetStringResult(interp); ! char *p = s; /* If the result contains any bytes with the top bit set, --- 615,620 ---- /* We could request the object result here, but doing so would confuse applications that expect a string. */ ! const char *s = Tcl_GetStringResult(interp); ! const char *p = s; /* If the result contains any bytes with the top bit set, *************** *** 784,788 **** SetVar(PyObject *self, PyObject *args, int flags) { ! char *name1, *name2, *ok, *s; PyObject *newValue; PyObject *tmp; --- 791,796 ---- SetVar(PyObject *self, PyObject *args, int flags) { ! char *name1, *name2, *s; ! const char *ok; PyObject *newValue; PyObject *tmp; *************** *** 844,848 **** GetVar(PyObject *self, PyObject *args, int flags) { ! char *name1, *name2=NULL, *s; PyObject *res = NULL; --- 852,857 ---- GetVar(PyObject *self, PyObject *args, int flags) { ! char *name1, *name2=NULL; ! const char *s; PyObject *res = NULL; From brianl@real.com Tue Oct 1 19:10:39 2002 From: brianl@real.com (Brian Lenihan) Date: Tue, 01 Oct 2002 11:10:39 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils ccompiler.py,1.47,1.48 In-Reply-To: Message-ID: <5.1.0.14.2.20021001110815.014bc1f8@cowzilla.dev.prognet.com> This also affected mxBase. I believe the other change you are referring to was adding a compiler class to config.py, which mx subclasses in its setup.py Both Twisted and mx attempt to compile conftest.c before doing the normal compiler setup and both stopped at the assert you just removed. Strangely, this assert did not affect Windows installs, probably because of the special case for adding Release and Debug dirs. I got mx to install by adding an output_dir to it's subclassed config.compiler. At 09:14 PM 9/30/2002 -0700, gvanrossum@users.sourceforge.net wrote: >Update of /cvsroot/python/python/dist/src/Lib/distutils >In directory usw-pr-cvs1:/tmp/cvs-serv13686 > >Modified Files: > ccompiler.py >Log Message: >Commit fix for SF 603831. > >Strangely, two out of three patches there seem already committed; but >the essential one (get rid of the assert in object_filenames in >ccompiler.py) was not yet applied. > >This makes the build procedure for Twisted work again. > >This is *not* a backport candidate despite the fact that identical >code appears to exist in 2.2.2; Twisted builds fine there, so there >must have been a change elsewhere. > > >Index: ccompiler.py >=================================================================== >RCS file: /cvsroot/python/python/dist/src/Lib/distutils/ccompiler.py,v >retrieving revision 1.47 >retrieving revision 1.48 >diff -C2 -d -r1.47 -r1.48 >*** ccompiler.py 11 Sep 2002 16:31:53 -0000 1.47 >--- ccompiler.py 1 Oct 2002 04:14:17 -0000 1.48 >*************** >*** 877,881 **** > > def object_filenames(self, source_filenames, strip_dir=0, > output_dir=''): >! assert output_dir is not None > obj_names = [] > for src_name in source_filenames: >--- 877,882 ---- > > def object_filenames(self, source_filenames, strip_dir=0, > output_dir=''): >! if output_dir is None: >! output_dir = '' > obj_names = [] > for src_name in source_filenames: > > > >_______________________________________________ >Python-checkins mailing list >Python-checkins@python.org >http://mail.python.org/mailman/listinfo/python-checkins From gvanrossum@users.sourceforge.net Tue Oct 1 19:19:02 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Tue, 01 Oct 2002 11:19:02 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.490,1.491 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv1568 Modified Files: NEWS Log Message: Mention droped support for Tcl/Tk 8.0 and 8.1. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.490 retrieving revision 1.491 diff -C2 -d -r1.490 -r1.491 *** NEWS 30 Sep 2002 15:23:01 -0000 1.490 --- NEWS 1 Oct 2002 18:18:58 -0000 1.491 *************** *** 285,288 **** --- 285,292 ---- ----------------- + - The _tkinter module (and hence Tkinter) has dropped support for + Tcl/Tk 8.0 and 8.1. Only Tcl/Tk versions 8.2, 8.3 and 8.4 are + supported. + - cPickle.BadPickleGet is now a class. From fdrake@users.sourceforge.net Tue Oct 1 19:20:19 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 01 Oct 2002 11:20:19 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib mimelib.tex,1.2,1.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv2087 Modified Files: mimelib.tex Log Message: Add a comment to the top of the file explaining why the file is here. Index: mimelib.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/mimelib.tex,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** mimelib.tex 1 Oct 2002 15:13:29 -0000 1.2 --- mimelib.tex 1 Oct 2002 18:20:16 -0000 1.3 *************** *** 1,2 **** --- 1,9 ---- + % This document is largely a stub used to allow the email package docs + % to be formatted separately from the rest of the Python + % documentation. This allows the documentation to be released + % independently of the rest of Python since the email package is being + % maintained for multiple Python versions, and on an accelerated + % schedule. + \documentclass{howto} From jhylton@users.sourceforge.net Tue Oct 1 19:31:07 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Tue, 01 Oct 2002 11:31:07 -0700 Subject: [Python-checkins] python/dist/src/Python ast.c,1.1.2.7,1.1.2.8 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv5977 Modified Files: Tag: ast-branch ast.c Log Message: Properly compute size of return sequence for testlist. If the number of children is oddd e.g. "1 , 2" we must round up. Index: ast.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/ast.c,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.8 diff -C2 -d -r1.1.2.7 -r1.1.2.8 *** ast.c 30 Sep 2002 18:21:45 -0000 1.1.2.7 --- ast.c 1 Oct 2002 18:31:05 -0000 1.1.2.8 *************** *** 330,337 **** seq_for_testlist(const node *n) { asdl_seq *seq; int i; ! seq = asdl_seq_new(NCH(n) / 2); for (i = 0; i < NCH(n); i += 2) { asdl_seq_SET(seq, i / 2, ast_for_expr(CHILD(n, i))); --- 330,338 ---- seq_for_testlist(const node *n) { + /* testlist: test (',' test)* [','] */ asdl_seq *seq; int i; ! seq = asdl_seq_new((NCH(n) + 1) / 2); for (i = 0; i < NCH(n); i += 2) { asdl_seq_SET(seq, i / 2, ast_for_expr(CHILD(n, i))); From jhylton@users.sourceforge.net Tue Oct 1 19:33:49 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Tue, 01 Oct 2002 11:33:49 -0700 Subject: [Python-checkins] python/dist/src/Python ast.c,1.1.2.8,1.1.2.9 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv6799 Modified Files: Tag: ast-branch ast.c Log Message: Fix List handling. Use seq_for_testlist() to compute the sequence elements, rather than ast_for_testlist(). The latter returns a tuple, when we want a sequence. Index: ast.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/ast.c,v retrieving revision 1.1.2.8 retrieving revision 1.1.2.9 diff -C2 -d -r1.1.2.8 -r1.1.2.9 *** ast.c 1 Oct 2002 18:31:05 -0000 1.1.2.8 --- ast.c 1 Oct 2002 18:33:47 -0000 1.1.2.9 *************** *** 570,577 **** REQ(ch, listmaker); if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { ! asdl_seq *elts = asdl_seq_new(1); ! if (!elts) ! return NULL; ! asdl_seq_SET(elts, 0, ast_for_testlist(ch)); return List(elts, Load); } --- 570,574 ---- REQ(ch, listmaker); if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { ! asdl_seq *elts = seq_for_testlist(ch); return List(elts, Load); } From loewis@users.sourceforge.net Tue Oct 1 19:50:58 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Tue, 01 Oct 2002 11:50:58 -0700 Subject: [Python-checkins] python/dist/src/Modules _tkinter.c,1.129,1.130 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv12617 Modified Files: _tkinter.c Log Message: Support UCS-4 builds. Index: _tkinter.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_tkinter.c,v retrieving revision 1.129 retrieving revision 1.130 diff -C2 -d -r1.129 -r1.130 *** _tkinter.c 1 Oct 2002 18:08:06 -0000 1.129 --- _tkinter.c 1 Oct 2002 18:50:56 -0000 1.130 *************** *** 63,66 **** --- 63,74 ---- #endif + /* Unicode conversion assumes that Tcl_UniChar is two bytes. + We cannot test this directly, so we test UTF-8 size instead, + expecting that TCL_UTF_MAX is changed if Tcl ever supports + either UTF-16 or UCS-4. */ + #if TCL_UTF_MAX != 3 + #error "unsupported Tcl configuration" + #endif + #if defined(macintosh) /* Sigh, we have to include this to get at the tcl qd pointer */ *************** *** 532,544 **** #ifdef Py_USING_UNICODE else if (PyUnicode_Check(value)) { ! /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */ ! if (sizeof(Py_UNICODE) != sizeof(Tcl_UniChar)) { ! /* XXX Should really test this at compile time */ ! PyErr_SetString(PyExc_SystemError, ! "Py_UNICODE and Tcl_UniChar differ in size"); ! return 0; } ! return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value), ! PyUnicode_GET_SIZE(value)); } #endif --- 540,572 ---- #ifdef Py_USING_UNICODE else if (PyUnicode_Check(value)) { ! Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value); ! int size = PyUnicode_GET_SIZE(value); ! /* This #ifdef assumes that Tcl uses UCS-2. ! See TCL_UTF_MAX test above. */ ! #ifdef Py_UNICODE_WIDE ! Tcl_UniChar *outbuf; ! int i; ! outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar)); ! if (!outbuf) { ! PyErr_NoMemory(); ! return NULL; } ! for (i = 0; i < size; i++) { ! if (inbuf[i] >= 0x10000) { ! /* Tcl doesn't do UTF-16, yet. */ ! PyErr_SetString(PyExc_ValueError, ! "unsupported character"); ! ckfree(FREECAST outbuf); ! return NULL; ! } ! outbuf[i] = inbuf[i]; ! } ! result = Tcl_NewUnicodeObj(outbuf, size); ! ckfree(FREECAST outbuf); ! return result; ! #else ! return Tcl_NewUnicodeObj(inbuf, size); ! #endif ! } #endif From jhylton@users.sourceforge.net Tue Oct 1 20:34:40 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Tue, 01 Oct 2002 12:34:40 -0700 Subject: [Python-checkins] python/dist/src/Python ast.c,1.1.2.9,1.1.2.10 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv27948 Modified Files: Tag: ast-branch ast.c Log Message: Small step towards parsing arglists: Handle simple positional arguments. Index: ast.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/ast.c,v retrieving revision 1.1.2.9 retrieving revision 1.1.2.10 diff -C2 -d -r1.1.2.9 -r1.1.2.10 *** ast.c 1 Oct 2002 18:33:47 -0000 1.1.2.9 --- ast.c 1 Oct 2002 19:34:38 -0000 1.1.2.10 *************** *** 807,812 **** */ REQ(n, arglist); ! return Call(func, NULL, NULL, NULL, NULL); } --- 807,836 ---- */ + int i, nargs; + asdl_seq *args = NULL; + REQ(n, arglist); ! ! nargs = 0; ! for (i = 0; i < NCH(n); i++) ! if (TYPE(CHILD(n, i)) == argument) ! nargs++; ! ! args = asdl_seq_new(nargs); ! for (i = 0; i < NCH(n); i++) { ! node *ch = CHILD(n, i); ! if (TYPE(ch) == argument) { ! expr_ty e; ! if (NCH(ch) == 1) ! e = ast_for_expr(CHILD(ch, 0)); ! else ! e = NULL; ! asdl_seq_SET(args, i / 2, e); ! } ! } ! ! ! /* XXX syntax error if more than 255 arguments */ ! return Call(func, args, NULL, NULL, NULL); } From jhylton@users.sourceforge.net Tue Oct 1 20:35:38 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Tue, 01 Oct 2002 12:35:38 -0700 Subject: [Python-checkins] python/dist/src/Python newcompile.c,1.1.2.11,1.1.2.12 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv28371 Modified Files: Tag: ast-branch newcompile.c Log Message: Emit BUILD_LIST, BUILD_TUPLE, and CALL_FUNCTION; CALL_FUNCTION only handles simple positional arguments. Also extend the debugging output to print the name of the opcode along with the number. Index: newcompile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/newcompile.c,v retrieving revision 1.1.2.11 retrieving revision 1.1.2.12 diff -C2 -d -r1.1.2.11 -r1.1.2.12 *** newcompile.c 30 Sep 2002 22:12:05 -0000 1.1.2.11 --- newcompile.c 1 Oct 2002 19:35:36 -0000 1.1.2.12 *************** *** 82,85 **** --- 82,87 ---- static PyCodeObject *assemble(struct compiler *); + static char *opnames[]; + #define IS_JUMP(I) ((I)->i_jrel || (I)->i_jabs) *************** *** 1022,1025 **** --- 1024,1032 ---- break; case Call_kind: + VISIT(c, expr, e->v.Call.func); + n = asdl_seq_LEN(e->v.Call.args); + /* XXX other args */ + VISIT_SEQ(c, expr, e->v.Call.args); + ADDOP_I(c, CALL_FUNCTION, n); break; case Repr_kind: *************** *** 1060,1066 **** --- 1067,1075 ---- case List_kind: VISIT_SEQ(c, expr, e->v.List.elts); + ADDOP_I(c, BUILD_LIST, asdl_seq_LEN(e->v.List.elts)); break; case Tuple_kind: VISIT_SEQ(c, expr, e->v.Tuple.elts); + ADDOP_I(c, BUILD_TUPLE, asdl_seq_LEN(e->v.Tuple.elts)); break; } *************** *** 1226,1231 **** code = PyString_AS_STRING(a->a_bytecode) + a->a_offset; fprintf(stderr, ! "emit %3d %5d\toffset = %2d\tsize = %d\text = %d\n", ! i->i_opcode, i->i_oparg, a->a_offset, size, ext); a->a_offset += size; if (ext > 0) { --- 1235,1241 ---- code = PyString_AS_STRING(a->a_bytecode) + a->a_offset; fprintf(stderr, ! "emit %3d %-10s %5d\toffset = %2d\tsize = %d\text = %d\n", ! i->i_opcode, opnames[i->i_opcode], ! i->i_oparg, a->a_offset, size, ext); a->a_offset += size; if (ext > 0) { *************** *** 1386,1387 **** --- 1396,1544 ---- return co; } + + static char *opnames[] = { + "STOP_CODE", + "POP_TOP", + "ROT_TWO", + "ROT_THREE", + "DUP_TOP", + "ROT_FOUR", + "<6>", + "<7>", + "<8>", + "<9>", + "UNARY_POSITIVE", + "UNARY_NEGATIVE", + "UNARY_NOT", + "UNARY_CONVERT", + "<14>", + "UNARY_INVERT", + "<16>", + "<17>", + "<18>", + "BINARY_POWER", + "BINARY_MULTIPLY", + "BINARY_DIVIDE", + "BINARY_MODULO", + "BINARY_ADD", + "BINARY_SUBTRACT", + "BINARY_SUBSCR", + "BINARY_FLOOR_DIVIDE", + "BINARY_TRUE_DIVIDE", + "INPLACE_FLOOR_DIVIDE", + "INPLACE_TRUE_DIVIDE", + "SLICE+0", + "SLICE+1", + "SLICE+2", + "SLICE+3", + "<34>", + "<35>", + "<36>", + "<37>", + "<38>", + "<39>", + "STORE_SLICE+0", + "STORE_SLICE+1", + "STORE_SLICE+2", + "STORE_SLICE+3", + "<44>", + "<45>", + "<46>", + "<47>", + "<48>", + "<49>", + "DELETE_SLICE+0", + "DELETE_SLICE+1", + "DELETE_SLICE+2", + "DELETE_SLICE+3", + "<54>", + "INPLACE_ADD", + "INPLACE_SUBTRACT", + "INPLACE_MULTIPLY", + "INPLACE_DIVIDE", + "INPLACE_MODULO", + "STORE_SUBSCR", + "DELETE_SUBSCR", + "BINARY_LSHIFT", + "BINARY_RSHIFT", + "BINARY_AND", + "BINARY_XOR", + "BINARY_OR", + "INPLACE_POWER", + "GET_ITER", + "<69>", + "PRINT_EXPR", + "PRINT_ITEM", + "PRINT_NEWLINE", + "PRINT_ITEM_TO", + "PRINT_NEWLINE_TO", + "INPLACE_LSHIFT", + "INPLACE_RSHIFT", + "INPLACE_AND", + "INPLACE_XOR", + "INPLACE_OR", + "BREAK_LOOP", + "<81>", + "LOAD_LOCALS", + "RETURN_VALUE", + "IMPORT_STAR", + "EXEC_STMT", + "YIELD_VALUE", + "POP_BLOCK", + "END_FINALLY", + "BUILD_CLASS", + "STORE_NAME", + "DELETE_NAME", + "UNPACK_SEQUENCE", + "FOR_ITER", + "<94>", + "STORE_ATTR", + "DELETE_ATTR", + "STORE_GLOBAL", + "DELETE_GLOBAL", + "DUP_TOPX", + "LOAD_CONST", + "LOAD_NAME", + "BUILD_TUPLE", + "BUILD_LIST", + "BUILD_MAP", + "LOAD_ATTR", + "COMPARE_OP", + "IMPORT_NAME", + "IMPORT_FROM", + "<109>", + "JUMP_FORWARD", + "JUMP_IF_FALSE", + "JUMP_IF_TRUE", + "JUMP_ABSOLUTE", + "<114>", + "<115>", + "LOAD_GLOBAL", + "<117>", + "<118>", + "CONTINUE_LOOP", + "SETUP_LOOP", + "SETUP_EXCEPT", + "SETUP_FINALLY", + "<123>", + "LOAD_FAST", + "STORE_FAST", + "DELETE_FAST", + "<127>", + "<128>", + "<129>", + "RAISE_VARARGS", + "CALL_FUNCTION", + "MAKE_FUNCTION", + "BUILD_SLICE", + "MAKE_CLOSURE", + "LOAD_CLOSURE", + "LOAD_DEREF", + "STORE_DEREF", + "<138>", + "<139>", + "CALL_FUNCTION_VAR", + "CALL_FUNCTION_KW", + "CALL_FUNCTION_VAR_KW", + "EXTENDED_ARG", + }; From jhylton@users.sourceforge.net Wed Oct 2 12:47:56 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Wed, 02 Oct 2002 04:47:56 -0700 Subject: [Python-checkins] python/dist/src/Parser Python.asdl,1.1.2.4,1.1.2.5 Message-ID: Update of /cvsroot/python/python/dist/src/Parser In directory usw-pr-cvs1:/tmp/cvs-serv8983/Parser Modified Files: Tag: ast-branch Python.asdl Log Message: Experimental change: Add Param to expr_context. It's convenient to represent a function's parameter list as a sequence of expressions, because they can contain names or tuples. Rather than re-using an existing expr_context for the names, make one explicitly for this purpose. There are some downsides: Must cover Param in all switch statements. Param isn't used directly by the AST. Index: Python.asdl =================================================================== RCS file: /cvsroot/python/python/dist/src/Parser/Attic/Python.asdl,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -C2 -d -r1.1.2.4 -r1.1.2.5 *** Python.asdl 30 Aug 2002 22:09:38 -0000 1.1.2.4 --- Python.asdl 2 Oct 2002 11:47:54 -0000 1.1.2.5 *************** *** 71,75 **** | Tuple(expr *elts, expr_context ctx) ! expr_context = Load | Store | Del | AugStore slice = Ellipsis | Slice(expr? lower, expr? upper, expr? step) --- 71,75 ---- | Tuple(expr *elts, expr_context ctx) ! expr_context = Load | Store | Del | AugStore | Param slice = Ellipsis | Slice(expr? lower, expr? upper, expr? step) From jhylton@users.sourceforge.net Wed Oct 2 12:48:46 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Wed, 02 Oct 2002 04:48:46 -0700 Subject: [Python-checkins] python/dist/src/Include Python-ast.h,1.1.2.4,1.1.2.5 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv9163/Include Modified Files: Tag: ast-branch Python-ast.h Log Message: Experimental change: Add Param to expr_context. It's convenient to represent a function's parameter list as a sequence of expressions, because they can contain names or tuples. Rather than re-using an existing expr_context for the names, make one explicitly for this purpose. There are some downsides: Must cover Param in all switch statements. Param isn't used directly by the AST. Index: Python-ast.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/Attic/Python-ast.h,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -C2 -d -r1.1.2.4 -r1.1.2.5 *** Python-ast.h 13 Sep 2002 14:32:12 -0000 1.1.2.4 --- Python-ast.h 2 Oct 2002 11:48:43 -0000 1.1.2.5 *************** *** 1,3 **** ! /* File automatically generated by Parser/asdl_c.py */ #include "asdl.h" --- 1,3 ---- ! /* File automatically generated by ../Parser/asdl_c.py */ #include "asdl.h" *************** *** 9,13 **** typedef struct _expr *expr_ty; ! typedef enum _expr_context { Load=1, Store=2, Del=3, AugStore=4 } expr_context_ty; --- 9,13 ---- typedef struct _expr *expr_ty; ! typedef enum _expr_context { Load=1, Store=2, Del=3, AugStore=4, Param=5 } expr_context_ty; From jhylton@users.sourceforge.net Wed Oct 2 12:48:46 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Wed, 02 Oct 2002 04:48:46 -0700 Subject: [Python-checkins] python/dist/src/Python Python-ast.c,1.1.2.4,1.1.2.5 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv9163/Python Modified Files: Tag: ast-branch Python-ast.c Log Message: Experimental change: Add Param to expr_context. It's convenient to represent a function's parameter list as a sequence of expressions, because they can contain names or tuples. Rather than re-using an existing expr_context for the names, make one explicitly for this purpose. There are some downsides: Must cover Param in all switch statements. Param isn't used directly by the AST. Index: Python-ast.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/Python-ast.c,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -C2 -d -r1.1.2.4 -r1.1.2.5 *** Python-ast.c 3 Sep 2002 23:18:53 -0000 1.1.2.4 --- Python-ast.c 2 Oct 2002 11:48:44 -0000 1.1.2.5 *************** *** 1508,1511 **** --- 1508,1514 ---- marshal_write_int(buf, off, 4); break; + case Param: + marshal_write_int(buf, off, 5); + break; } return 1; From jhylton@users.sourceforge.net Wed Oct 2 12:49:17 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Wed, 02 Oct 2002 04:49:17 -0700 Subject: [Python-checkins] python/dist/src/Python ast.c,1.1.2.10,1.1.2.11 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv9358/Python Modified Files: Tag: ast-branch ast.c Log Message: Experimental change: Add Param to expr_context. It's convenient to represent a function's parameter list as a sequence of expressions, because they can contain names or tuples. Rather than re-using an existing expr_context for the names, make one explicitly for this purpose. There are some downsides: Must cover Param in all switch statements. Param isn't used directly by the AST. Index: ast.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/ast.c,v retrieving revision 1.1.2.10 retrieving revision 1.1.2.11 diff -C2 -d -r1.1.2.10 -r1.1.2.11 *** ast.c 1 Oct 2002 19:34:38 -0000 1.1.2.10 --- ast.c 2 Oct 2002 11:49:15 -0000 1.1.2.11 *************** *** 390,394 **** } if (TYPE(CHILD(ch, 0)) == NAME) ! asdl_seq_APPEND(args, NEW_IDENTIFIER(CHILD(ch, 0))); if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { asdl_seq_APPEND(defaults, ast_for_expr(CHILD(n, i + 2))); --- 390,395 ---- } if (TYPE(CHILD(ch, 0)) == NAME) ! asdl_seq_APPEND(args, Name(NEW_IDENTIFIER(CHILD(ch, 0)), ! Param)); if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { asdl_seq_APPEND(defaults, ast_for_expr(CHILD(n, i + 2))); From jhylton@users.sourceforge.net Wed Oct 2 12:50:16 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Wed, 02 Oct 2002 04:50:16 -0700 Subject: [Python-checkins] python/dist/src/Python symtable.c,2.10.8.8,2.10.8.9 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv9716/Python Modified Files: Tag: ast-branch symtable.c Log Message: Experimental change: Add Param to expr_context. It's convenient to represent a function's parameter list as a sequence of expressions, because they can contain names or tuples. Rather than re-using an existing expr_context for the names, make one explicitly for this purpose. There are some downsides: Must cover Param in all switch statements. Param isn't used directly by the AST. Index: symtable.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v retrieving revision 2.10.8.8 retrieving revision 2.10.8.9 diff -C2 -d -r2.10.8.8 -r2.10.8.9 *** symtable.c 27 Sep 2002 23:13:38 -0000 2.10.8.8 --- symtable.c 2 Oct 2002 11:50:14 -0000 2.10.8.9 *************** *** 612,616 **** symtable_visit_stmt(struct symtable *st, stmt_ty s) { - fprintf(stderr, "symtable %d %d\n", s->kind, s->lineno); switch (s->kind) { case FunctionDef_kind: --- 612,615 ---- *************** *** 838,842 **** expr_ty arg = asdl_seq_GET(args, i); if (arg->kind == Name_kind) { ! assert(arg->v.Name.ctx == Load); if (!symtable_add_def(st, arg->v.Name.id, DEF_PARAM)) return 0; --- 837,841 ---- expr_ty arg = asdl_seq_GET(args, i); if (arg->kind == Name_kind) { ! assert(arg->v.Name.ctx == Param); if (!symtable_add_def(st, arg->v.Name.id, DEF_PARAM)) return 0; *************** *** 853,859 **** else { /* syntax error */ return 0; } ! } return 1; --- 852,859 ---- else { /* syntax error */ + fprintf(stderr, "unexpected expr in parameter list\n"); return 0; } ! } return 1; *************** *** 872,876 **** if (a->kwarg && !symtable_add_def(st, a->kwarg, DEF_PARAM)) return 0; - return 1; } --- 872,875 ---- From jhylton@users.sourceforge.net Wed Oct 2 12:58:55 2002 From: jhylton@users.sourceforge.net (jhylton@users.sourceforge.net) Date: Wed, 02 Oct 2002 04:58:55 -0700 Subject: [Python-checkins] python/dist/src/Python newcompile.c,1.1.2.12,1.1.2.13 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv12002/Python Modified Files: Tag: ast-branch newcompile.c Log Message: Restructure struct compiler into two parts. Each block needs to store its own state. This state had been stored in struct compiler initially. Now stored in struct compiler_unit. The compiler_unit is changed whenever a block is entered or exited, using c_stack. XXX This makes a lot of code a lot uglier because there are two pointer dereferences. The extra dereference seems preferable to passing it as a separate argument everywhere. Probably need to rework individual functions to use local variable. Function objects are now created, although their code objects are bogus. Also, extend switch statements to handle Param. Index: newcompile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/newcompile.c,v retrieving revision 1.1.2.12 retrieving revision 1.1.2.13 diff -C2 -d -r1.1.2.12 -r1.1.2.13 *** newcompile.c 1 Oct 2002 19:35:36 -0000 1.1.2.12 --- newcompile.c 2 Oct 2002 11:58:53 -0000 1.1.2.13 *************** *** 23,26 **** --- 23,50 ---- }; + /* The following items change on entry and exit of code blocks. + They must be saved and restored when returning to a block. + */ + struct compiler_unit { + PySTEntryObject *u_ste; + + PyObject *u_name; + PyObject *u_consts; + PyObject *u_names; + PyObject *u_varnames; + + int u_argcount; + int u_nblocks; + int u_curblock; + struct basicblock u_entry; + struct basicblock u_exit; + struct basicblock **u_blocks; + + int u_nfblocks; + struct fblockinfo u_fblock[CO_MAXBLOCKS]; + + int u_lineno; + }; + struct compiler { const char *c_filename; *************** *** 31,53 **** int c_interactive; ! /* info that changes for each code block */ ! PySTEntryObject *c_ste; ! ! PyObject *c_name; ! PyObject *c_consts; ! PyObject *c_names; ! PyObject *c_varnames; ! ! int c_argcount; ! int c_nblocks; ! int c_curblock; ! struct basicblock c_entry; ! struct basicblock c_exit; ! struct basicblock **c_blocks; ! ! int c_nfblocks; ! struct fblockinfo c_fblock[CO_MAXBLOCKS]; ! ! int c_lineno; }; --- 55,60 ---- int c_interactive; ! struct compiler_unit *u; ! PyObject *c_stack; }; *************** *** 86,89 **** --- 93,99 ---- #define IS_JUMP(I) ((I)->i_jrel || (I)->i_jabs) + #define BLOCK(U, I) (U)->u_blocks[I] + #define CURBLOCK(U) BLOCK(U, (U)->u_curblock) + int _Py_Mangle(char *p, char *name, char *buffer, size_t maxlen) *************** *** 119,122 **** --- 129,136 ---- memset(c, 0, sizeof(struct compiler)); + c->c_stack = PyList_New(0); + if (!c->c_stack) + return 0; + return 1; } *************** *** 152,156 **** fprintf(stderr, "ast %s\n", filename); - c.c_st = PySymtable_Build(mod, filename, c.c_future); if (c.c_st == NULL) { --- 166,169 ---- *************** *** 173,190 **** compiler_free(struct compiler *c) { - int i; - if (c->c_st) PySymtable_Free(c->c_st); if (c->c_future) PyObject_Free((void *)c->c_future); ! for (i = 0; i < c->c_nblocks; i++) ! PyObject_Free((void *)c->c_blocks[i]); ! if (c->c_blocks) ! PyObject_Free((void *)c->c_blocks); ! Py_XDECREF(c->c_name); ! Py_XDECREF(c->c_consts); ! Py_XDECREF(c->c_names); ! Py_XDECREF(c->c_varnames); } --- 186,194 ---- compiler_free(struct compiler *c) { if (c->c_st) PySymtable_Free(c->c_st); if (c->c_future) PyObject_Free((void *)c->c_future); ! Py_DECREF(c->c_stack); } *************** *** 192,220 **** compiler_enter_scope(struct compiler *c, identifier name, void *key) { ! c->c_ste = PySymtable_Lookup(c->c_st, key); ! if (!c->c_ste) { return 0; } Py_INCREF(name); ! c->c_name = name; ! c->c_varnames = c->c_ste->ste_varnames; ! Py_INCREF(c->c_varnames); fprintf(stderr, "block %s varnames %s\n", PyObject_REPR(name), ! PyObject_REPR(c->c_varnames)); ! c->c_nblocks = 0; ! c->c_blocks = (struct basicblock **)PyObject_Malloc( ! sizeof(struct basicblock *) * DEFAULT_BLOCKS); ! if (!c->c_blocks) return 0; ! memset(c->c_blocks, 0, sizeof(struct basicblock *) * DEFAULT_BLOCKS); ! if (compiler_use_new_block(c) < 0) return 0; ! c->c_consts = PyDict_New(); ! if (!c->c_consts) return 0; ! c->c_names = PyDict_New(); ! if (!c->c_names) return 0; return 1; } --- 196,240 ---- compiler_enter_scope(struct compiler *c, identifier name, void *key) { ! struct compiler_unit *u; ! ! u = PyObject_Malloc(sizeof(struct compiler_unit)); ! u->u_argcount = 0; ! u->u_ste = PySymtable_Lookup(c->c_st, key); ! if (!u->u_ste) { return 0; } Py_INCREF(name); ! u->u_name = name; ! u->u_varnames = u->u_ste->ste_varnames; ! Py_INCREF(u->u_varnames); fprintf(stderr, "block %s varnames %s\n", PyObject_REPR(name), ! PyObject_REPR(u->u_varnames)); ! u->u_nblocks = 0; ! u->u_blocks = (struct basicblock **)PyObject_Malloc( ! sizeof(struct basicblock *) * DEFAULT_BLOCKS); ! if (!u->u_blocks) return 0; ! memset(u->u_blocks, 0, sizeof(struct basicblock *) * DEFAULT_BLOCKS); ! u->u_consts = PyDict_New(); ! if (!u->u_consts) return 0; ! u->u_names = PyDict_New(); ! if (!u->u_names) return 0; ! ! /* Push the old compiler_unit on the stack. */ ! if (c->u) { ! PyObject *wrapper = PyCObject_FromVoidPtr(c->u, NULL); ! if (PyList_Append(c->c_stack, wrapper) < 0) ! return 0; ! Py_DECREF(wrapper); ! fprintf(stderr, "stack = %s\n", PyObject_REPR(c->c_stack)); ! } ! c->u = u; ! ! if (compiler_use_new_block(c) < 0) return 0; + return 1; } *************** *** 223,234 **** compiler_exit_scope(struct compiler *c) { ! Py_DECREF(c->c_name); ! c->c_name = NULL; ! Py_DECREF(c->c_consts); ! c->c_consts = NULL; ! Py_DECREF(c->c_names); ! c->c_names = NULL; ! Py_DECREF(c->c_varnames); ! c->c_varnames = NULL; return 1; /* XXX void? */ } --- 243,272 ---- compiler_exit_scope(struct compiler *c) { ! struct compiler_unit *u = c->u; ! int i, n; ! PyObject *wrapper; ! ! for (i = 0; i < u->u_nblocks; i++) ! PyObject_Free((void *)u->u_blocks[i]); ! if (u->u_blocks) ! PyObject_Free((void *)u->u_blocks); ! Py_XDECREF(u->u_name); ! Py_XDECREF(u->u_consts); ! Py_XDECREF(u->u_names); ! Py_XDECREF(u->u_varnames); ! ! PyObject_Free(u); ! ! /* Restore c->u to the parent unit. */ ! n = PyList_GET_SIZE(c->c_stack) - 1; ! if (n >= 0) { ! wrapper = PyList_GET_ITEM(c->c_stack, n); ! c->u = (struct compiler_unit *)PyCObject_AsVoidPtr(wrapper); ! if (PySequence_DelItem(c->c_stack, n) < 0) ! return 0; ! } ! else ! c->u = NULL; ! return 1; /* XXX void? */ } *************** *** 242,253 **** { struct basicblock *b; int block; ! if (c->c_nblocks && c->c_nblocks % DEFAULT_BLOCKS == 0) { /* XXX should double */ ! int newsize = c->c_nblocks + DEFAULT_BLOCKS; ! c->c_blocks = (struct basicblock **)PyObject_Realloc( ! c->c_blocks, newsize); ! if (c->c_blocks == NULL) return -1; } --- 280,293 ---- { struct basicblock *b; + struct compiler_unit *u; int block; ! u = c->u; ! if (u->u_nblocks && u->u_nblocks % DEFAULT_BLOCKS == 0) { /* XXX should double */ ! int newsize = u->u_nblocks + DEFAULT_BLOCKS; ! u->u_blocks = (struct basicblock **)PyObject_Realloc( ! u->u_blocks, newsize); ! if (u->u_blocks == NULL) return -1; } *************** *** 257,262 **** memset((void *)b, 0, sizeof(struct basicblock)); b->b_ialloc = DEFAULT_BLOCK_SIZE; ! block = c->c_nblocks++; ! c->c_blocks[block] = b; return block; } --- 297,302 ---- memset((void *)b, 0, sizeof(struct basicblock)); b->b_ialloc = DEFAULT_BLOCK_SIZE; ! block = u->u_nblocks++; ! u->u_blocks[block] = b; return block; } *************** *** 265,271 **** compiler_use_block(struct compiler *c, int block) { ! assert(block < c->c_nblocks); ! c->c_curblock = block; ! assert(c->c_blocks[block]); } --- 305,311 ---- compiler_use_block(struct compiler *c, int block) { ! assert(block < c->u->u_nblocks); ! c->u->u_curblock = block; ! assert(c->u->u_blocks[block]); } *************** *** 276,280 **** if (block < 0) return 0; ! c->c_curblock = block; return block; } --- 316,320 ---- if (block < 0) return 0; ! c->u->u_curblock = block; return block; } *************** *** 286,291 **** if (block < 0) return 0; ! c->c_blocks[c->c_curblock]->b_next = block; ! c->c_curblock = block; return block; } --- 326,331 ---- if (block < 0) return 0; ! c->u->u_blocks[c->u->u_curblock]->b_next = block; ! c->u->u_curblock = block; return block; } *************** *** 294,301 **** compiler_use_next_block(struct compiler *c, int block) { ! assert(block < c->c_nblocks); ! c->c_blocks[c->c_curblock]->b_next = block; ! assert(c->c_blocks[block]); ! c->c_curblock = block; return block; } --- 334,341 ---- compiler_use_next_block(struct compiler *c, int block) { ! assert(block < c->u->u_nblocks); ! c->u->u_blocks[c->u->u_curblock]->b_next = block; ! assert(c->u->u_blocks[block]); ! c->u->u_curblock = block; return block; } *************** *** 310,315 **** { struct basicblock *b; ! assert(block < c->c_nblocks); ! b = c->c_blocks[block]; assert(b); if (b->b_iused == b->b_ialloc) { --- 350,355 ---- { struct basicblock *b; ! assert(block < c->u->u_nblocks); ! b = c->u->u_blocks[block]; assert(b); if (b->b_iused == b->b_ialloc) { *************** *** 324,328 **** return -1; if (ptr != (void *)b) ! c->c_blocks[block] = (struct basicblock *)ptr; } return b->b_iused++; --- 364,368 ---- return -1; if (ptr != (void *)b) ! c->u->u_blocks[block] = (struct basicblock *)ptr; } return b->b_iused++; *************** *** 338,345 **** struct instr *i; int off; ! off = compiler_next_instr(c, c->c_curblock); if (off < 0) return 0; ! i = &c->c_blocks[c->c_curblock]->b_instr[off]; i->i_opcode = opcode; i->i_hasarg = 0; --- 378,385 ---- struct instr *i; int off; ! off = compiler_next_instr(c, c->u->u_curblock); if (off < 0) return 0; ! i = &c->u->u_blocks[c->u->u_curblock]->b_instr[off]; i->i_opcode = opcode; i->i_hasarg = 0; *************** *** 380,387 **** struct instr *i; int off; ! off = compiler_next_instr(c, c->c_curblock); if (off < 0) return 0; ! i = &c->c_blocks[c->c_curblock]->b_instr[off]; i->i_opcode = opcode; i->i_oparg = oparg; --- 420,427 ---- struct instr *i; int off; ! off = compiler_next_instr(c, c->u->u_curblock); if (off < 0) return 0; ! i = &c->u->u_blocks[c->u->u_curblock]->b_instr[off]; i->i_opcode = opcode; i->i_oparg = oparg; *************** *** 395,402 **** struct instr *i; int off; ! off = compiler_next_instr(c, c->c_curblock); if (off < 0) return 0; ! i = &c->c_blocks[c->c_curblock]->b_instr[off]; i->i_opcode = opcode; i->i_oparg = block; --- 435,442 ---- struct instr *i; int off; ! off = compiler_next_instr(c, c->u->u_curblock); if (off < 0) return 0; ! i = &c->u->u_blocks[c->u->u_curblock]->b_instr[off]; i->i_opcode = opcode; i->i_oparg = block; *************** *** 432,436 **** #define ADDOP_O(C, OP, O, TYPE) { \ ! if (!compiler_addop_o((C), (OP), (C)->c_ ## TYPE, (O))) \ return 0; \ } --- 472,476 ---- #define ADDOP_O(C, OP, O, TYPE) { \ ! if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \ return 0; \ } *************** *** 518,527 **** if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s)) return 0; ! ndefs += asdl_seq_LEN(args->args); ! c->c_argcount = ndefs; ! if (args->vararg) ! ndefs++; ! if (args->kwarg) ! ndefs++; VISIT_SEQ(c, stmt, s->v.FunctionDef.body); co = assemble(c); --- 558,562 ---- if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s)) return 0; ! c->u->u_argcount = ndefs; VISIT_SEQ(c, stmt, s->v.FunctionDef.body); co = assemble(c); *************** *** 601,605 **** elif = 1; s = t; ! c->c_lineno = t->lineno; } } --- 636,640 ---- elif = 1; s = t; ! c->u->u_lineno = t->lineno; } } *************** *** 689,707 **** int i; ! if (!c->c_nfblocks) return compiler_error(c, "'continue' outside loop"); ! i = c->c_nfblocks - 1; ! switch (c->c_fblock[i].fb_type) { case LOOP: ! ADDOP_JABS(c, JUMP_ABSOLUTE, c->c_fblock[i].fb_block); NEW_BLOCK(c); break; case EXCEPT: case FINALLY_TRY: ! while (--i > 0 && c->c_fblock[i].fb_type != LOOP) ; if (i == -1) return compiler_error(c, "'continue' outside loop"); ! ADDOP_I(c, CONTINUE_LOOP, c->c_fblock[i].fb_block); NEW_BLOCK(c); break; --- 724,742 ---- int i; ! if (!c->u->u_nfblocks) return compiler_error(c, "'continue' outside loop"); ! i = c->u->u_nfblocks - 1; ! switch (c->u->u_fblock[i].fb_type) { case LOOP: ! ADDOP_JABS(c, JUMP_ABSOLUTE, c->u->u_fblock[i].fb_block); NEW_BLOCK(c); break; case EXCEPT: case FINALLY_TRY: ! while (--i > 0 && c->u->u_fblock[i].fb_type != LOOP) ; if (i == -1) return compiler_error(c, "'continue' outside loop"); ! ADDOP_I(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block); NEW_BLOCK(c); break; *************** *** 722,726 **** fprintf(stderr, "compile stmt %d lineno %d\n", s->kind, s->lineno); ! c->c_lineno = s->lineno; /* XXX this isn't right */ switch (s->kind) { case FunctionDef_kind: --- 757,761 ---- fprintf(stderr, "compile stmt %d lineno %d\n", s->kind, s->lineno); ! c->u->u_lineno = s->lineno; /* XXX this isn't right */ switch (s->kind) { case FunctionDef_kind: *************** *** 822,826 **** break; case Break_kind: ! if (!c->c_nfblocks) return compiler_error(c, "'break' outside loop"); ADDOP(c, BREAK_LOOP); --- 857,861 ---- break; case Break_kind: ! if (!c->u->u_nfblocks) return compiler_error(c, "'break' outside loop"); ADDOP(c, BREAK_LOOP); *************** *** 893,897 **** op = 0; optype = OP_NAME; ! scope = PyST_GetScope(c->c_ste, name); switch (scope) { case FREE: --- 928,932 ---- op = 0; optype = OP_NAME; ! scope = PyST_GetScope(c->u->u_ste, name); switch (scope) { case FREE: *************** *** 900,908 **** break; case LOCAL: ! if (c->c_ste->ste_type == FunctionBlock) optype = OP_FAST; break; case GLOBAL_IMPLICIT: ! if (c->c_ste->ste_optimized) optype = OP_GLOBAL; break; --- 935,943 ---- break; case LOCAL: ! if (c->u->u_ste->ste_type == FunctionBlock) optype = OP_FAST; break; case GLOBAL_IMPLICIT: ! if (c->u->u_ste->ste_optimized) optype = OP_GLOBAL; break; *************** *** 920,923 **** --- 955,959 ---- break; case Del: + case Param: assert(0); /* impossible */ } *************** *** 929,932 **** --- 965,970 ---- case AugStore: break; + case Param: + assert(0); /* impossible */ } case OP_GLOBAL: *************** *** 937,940 **** --- 975,980 ---- case AugStore: break; + case Param: + assert(0); /* impossible */ } case OP_NAME: *************** *** 945,948 **** --- 985,990 ---- case AugStore: break; + case Param: + assert(0); /* impossible */ } } *************** *** 1055,1058 **** --- 1097,1103 ---- /* XXX */ break; + case Param: + assert(0); + break; } break; *************** *** 1081,1087 **** { struct fblockinfo *f; ! if (c->c_nfblocks >= CO_MAXBLOCKS) return 0; ! f = &c->c_fblock[c->c_nfblocks++]; f->fb_type = t; f->fb_block = b; --- 1126,1132 ---- { struct fblockinfo *f; ! if (c->u->u_nfblocks >= CO_MAXBLOCKS) return 0; ! f = &c->u->u_fblock[c->u->u_nfblocks++]; f->fb_type = t; f->fb_block = b; *************** *** 1092,1099 **** compiler_pop_fblock(struct compiler *c, enum fblocktype t, int b) { ! assert(c->c_nfblocks > 0); ! c->c_nfblocks--; ! assert(c->c_fblock[c->c_nfblocks].fb_type == t); ! assert(c->c_fblock[c->c_nfblocks].fb_block == b); } --- 1137,1145 ---- compiler_pop_fblock(struct compiler *c, enum fblocktype t, int b) { ! struct compiler_unit *u = c->u; ! assert(u->u_nfblocks > 0); ! u->u_nfblocks--; ! assert(u->u_fblock[u->u_nfblocks].fb_type == t); ! assert(u->u_fblock[u->u_nfblocks].fb_block == b); } *************** *** 1108,1117 **** PyObject *u = NULL, *v = NULL; ! loc = PyErr_ProgramText(c->c_filename, c->c_lineno); if (!loc) { Py_INCREF(Py_None); loc = Py_None; } ! u = Py_BuildValue("(ziOO)", c->c_filename, c->c_lineno, Py_None, loc); if (!u) goto exit; --- 1154,1164 ---- PyObject *u = NULL, *v = NULL; ! loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno); if (!loc) { Py_INCREF(Py_None); loc = Py_None; } ! u = Py_BuildValue("(ziOO)", c->c_filename, c->u->u_lineno, ! Py_None, loc); if (!u) goto exit; *************** *** 1146,1152 **** struct instr *instr = NULL; ! if (block >= c->c_nblocks) return; ! b = c->c_blocks[block]; if (b->b_seen) return; --- 1193,1199 ---- struct instr *instr = NULL; ! if (block >= c->u->u_nblocks) return; ! b = c->u->u_blocks[block]; if (b->b_seen) return; *************** *** 1235,1239 **** code = PyString_AS_STRING(a->a_bytecode) + a->a_offset; fprintf(stderr, ! "emit %3d %-10s %5d\toffset = %2d\tsize = %d\text = %d\n", i->i_opcode, opnames[i->i_opcode], i->i_oparg, a->a_offset, size, ext); --- 1282,1286 ---- code = PyString_AS_STRING(a->a_bytecode) + a->a_offset; fprintf(stderr, ! "emit %3d %-15s %5d\toffset = %2d\tsize = %d\text = %d\n", i->i_opcode, opnames[i->i_opcode], i->i_oparg, a->a_offset, size, ext); *************** *** 1270,1279 **** for (i = a->a_nblocks - 1; i >= 0; i--) { int block = a->a_postorder[i]; ! bsize = blocksize(c->c_blocks[block]); blockoff[block] = totsize; totsize += bsize; } ! for (i = 0; i < c->c_nblocks; i++) { ! struct basicblock *b = c->c_blocks[i]; bsize = blockoff[i]; for (j = 0; j < b->b_iused; j++) { --- 1317,1326 ---- for (i = a->a_nblocks - 1; i >= 0; i--) { int block = a->a_postorder[i]; ! bsize = blocksize(c->u->u_blocks[block]); blockoff[block] = totsize; totsize += bsize; } ! for (i = 0; i < c->u->u_nblocks; i++) { ! struct basicblock *b = c->u->u_blocks[i]; bsize = blockoff[i]; for (j = 0; j < b->b_iused; j++) { *************** *** 1325,1335 **** PyObject *nil = PyTuple_New(0); ! consts = dict_keys_inorder(c->c_consts, 0); if (!consts) goto error; ! names = dict_keys_inorder(c->c_names, 0); if (!names) goto error; ! varnames = PySequence_Tuple(c->c_varnames); if (!varnames) goto error; --- 1372,1382 ---- PyObject *nil = PyTuple_New(0); ! consts = dict_keys_inorder(c->u->u_consts, 0); if (!consts) goto error; ! names = dict_keys_inorder(c->u->u_names, 0); if (!names) goto error; ! varnames = PySequence_Tuple(c->u->u_varnames); if (!varnames) goto error; *************** *** 1338,1345 **** goto error; ! co = PyCode_New(c->c_argcount, 0, stackdepth(c), 0, a->a_bytecode, consts, names, varnames, nil, nil, ! filename, c->c_name, 0, filename); /* XXX lnotab */ --- 1385,1392 ---- goto error; ! co = PyCode_New(c->u->u_argcount, 0, stackdepth(c), 0, a->a_bytecode, consts, names, varnames, nil, nil, ! filename, c->u->u_name, 0, filename); /* XXX lnotab */ *************** *** 1369,1373 **** ADDOP(c, RETURN_VALUE); ! if (!assemble_init(&a, c->c_nblocks)) goto error; dfs(c, 0, &a); --- 1416,1420 ---- ADDOP(c, RETURN_VALUE); ! if (!assemble_init(&a, c->u->u_nblocks)) goto error; dfs(c, 0, &a); *************** *** 1379,1383 **** /* Emit code in reverse postorder from dfs. */ for (i = a.a_nblocks - 1; i >= 0; i--) { ! struct basicblock *b = c->c_blocks[a.a_postorder[i]]; fprintf(stderr, "block %d(%d): used=%d alloc=%d\n", i, a.a_postorder[i], b->b_iused, b->b_ialloc); --- 1426,1430 ---- /* Emit code in reverse postorder from dfs. */ for (i = a.a_nblocks - 1; i >= 0; i--) { ! struct basicblock *b = c->u->u_blocks[a.a_postorder[i]]; fprintf(stderr, "block %d(%d): used=%d alloc=%d\n", i, a.a_postorder[i], b->b_iused, b->b_ialloc); *************** *** 1387,1390 **** --- 1434,1438 ---- } } + fprintf(stderr, "\n"); if (_PyString_Resize(&a.a_bytecode, a.a_offset) < 0) From mwh@users.sourceforge.net Wed Oct 2 14:13:48 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Wed, 02 Oct 2002 06:13:48 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_trace.py,1.3,1.4 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv1712/src/Lib/test Modified Files: test_trace.py Log Message: Fix for the recursion_level bug Armin Rigo reported in sf patch #617312, both on the trunk and the 22-maint branch. Also added a test case, and ported the test_trace I wrote for HEAD to 2.2.2 (with all those horrible extra 'line' events ;-). Index: test_trace.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_trace.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** test_trace.py 11 Sep 2002 15:36:32 -0000 1.3 --- test_trace.py 2 Oct 2002 13:13:46 -0000 1.4 *************** *** 178,183 **** --- 178,203 ---- self.run_test2(settrace_and_raise) + class RaisingTraceFuncTestCase(unittest.TestCase): + def test_it(self): + def tr(frame, event, arg): + raise ValueError # just something that isn't RuntimeError + def f(): + return 1 + try: + for i in xrange(sys.getrecursionlimit() + 1): + sys.settrace(tr) + try: + f() + except ValueError: + pass + else: + self.fail("exception not thrown!") + except RuntimeError: + self.fail("recursion counter not reset") + + def test_main(): test_support.run_unittest(TraceTestCase) + test_support.run_unittest(RaisingTraceFuncTestCase) if __name__ == "__main__": From mwh@users.sourceforge.net Wed Oct 2 14:13:48 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Wed, 02 Oct 2002 06:13:48 -0700 Subject: [Python-checkins] python/dist/src/Python ceval.c,2.336,2.337 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv1712/src/Python Modified Files: ceval.c Log Message: Fix for the recursion_level bug Armin Rigo reported in sf patch #617312, both on the trunk and the 22-maint branch. Also added a test case, and ported the test_trace I wrote for HEAD to 2.2.2 (with all those horrible extra 'line' events ;-). Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.336 retrieving revision 2.337 diff -C2 -d -r2.336 -r2.337 *** ceval.c 11 Sep 2002 15:36:31 -0000 2.336 --- ceval.c 2 Oct 2002 13:13:46 -0000 2.337 *************** *** 637,640 **** --- 637,642 ---- f, PyTrace_CALL, Py_None)) { /* Trace function raised an error */ + --tstate->recursion_depth; + tstate->frame = f->f_back; return NULL; } *************** *** 647,650 **** --- 649,654 ---- f, PyTrace_CALL, Py_None)) { /* Profile function raised an error */ + --tstate->recursion_depth; + tstate->frame = f->f_back; return NULL; } From mwh@users.sourceforge.net Wed Oct 2 14:13:49 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Wed, 02 Oct 2002 06:13:49 -0700 Subject: [Python-checkins] python/dist/src/Python ceval.c,2.301.4.4,2.301.4.5 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv1712/src-22x/Python Modified Files: Tag: release22-maint ceval.c Log Message: Fix for the recursion_level bug Armin Rigo reported in sf patch #617312, both on the trunk and the 22-maint branch. Also added a test case, and ported the test_trace I wrote for HEAD to 2.2.2 (with all those horrible extra 'line' events ;-). Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.301.4.4 retrieving revision 2.301.4.5 diff -C2 -d -r2.301.4.4 -r2.301.4.5 *** ceval.c 5 Aug 2002 14:46:29 -0000 2.301.4.4 --- ceval.c 2 Oct 2002 13:13:47 -0000 2.301.4.5 *************** *** 613,616 **** --- 613,618 ---- f, PyTrace_CALL, Py_None)) { /* Trace function raised an error */ + --tstate->recursion_depth; + tstate->frame = f->f_back; return NULL; } *************** *** 623,626 **** --- 625,630 ---- f, PyTrace_CALL, Py_None)) { /* Profile function raised an error */ + --tstate->recursion_depth; + tstate->frame = f->f_back; return NULL; } From mwh@users.sourceforge.net Wed Oct 2 14:13:49 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Wed, 02 Oct 2002 06:13:49 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_trace.py,NONE,1.4.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv1712/src-22x/Lib/test Added Files: Tag: release22-maint test_trace.py Log Message: Fix for the recursion_level bug Armin Rigo reported in sf patch #617312, both on the trunk and the 22-maint branch. Also added a test case, and ported the test_trace I wrote for HEAD to 2.2.2 (with all those horrible extra 'line' events ;-). --- NEW FILE: test_trace.py --- # Testing the line trace facility. import test_support import unittest import sys import difflib # A very basic example. If this fails, we're in deep trouble. def basic(): return 1 basic.events = [(0, 'call'), (0, 'line'), (1, 'line'), (1, 'return')] # Armin Rigo's failing example: def arigo_example(): x = 1 del x while 0: pass x = 1 arigo_example.events = [(0, 'call'), (0, 'line'), (1, 'line'), (2, 'line'), (3, 'line'), (3, 'line'), (5, 'line'), (5, 'return')] # check that lines consisting of just one instruction get traced: def one_instr_line(): x = 1 del x x = 1 one_instr_line.events = [(0, 'call'), (0, 'line'), (1, 'line'), (2, 'line'), (3, 'line'), (3, 'return')] def no_pop_tops(): # 0 x = 1 # 1 for a in range(2): # 2 if a: # 3 x = 1 # 4 else: # 5 x = 1 # 6 no_pop_tops.events = [(0, 'call'), (0, 'line'), (1, 'line'), (2, 'line'), (2, 'line'), (3, 'line'), (6, 'line'), (2, 'line'), (3, 'line'), (4, 'line'), (2, 'line'), (2, 'return')] def no_pop_blocks(): while 0: bla x = 1 no_pop_blocks.events = [(0, 'call'), (0, 'line'), (1, 'line'), (1, 'line'), (3, 'line'), (3, 'return')] def called(): # line -3 x = 1 def call(): # line 0 called() call.events = [(0, 'call'), (0, 'line'), (1, 'line'), (-3, 'call'), (-3, 'line'), (-2, 'line'), (-2, 'return'), (1, 'return')] def raises(): raise Exception def test_raise(): try: raises() except Exception, exc: x = 1 test_raise.events = [(0, 'call'), (0, 'line'), (1, 'line'), (2, 'line'), (-3, 'call'), (-3, 'line'), (-2, 'line'), (-2, 'exception'), (2, 'exception'), (3, 'line'), (4, 'line'), (4, 'return')] def _settrace_and_return(tracefunc): sys.settrace(tracefunc) sys._getframe().f_back.f_trace = tracefunc def settrace_and_return(tracefunc): _settrace_and_return(tracefunc) settrace_and_return.events = [(1, 'return')] def _settrace_and_raise(tracefunc): sys.settrace(tracefunc) sys._getframe().f_back.f_trace = tracefunc raise RuntimeError def settrace_and_raise(tracefunc): try: _settrace_and_raise(tracefunc) except RuntimeError, exc: pass settrace_and_raise.events = [(2, 'exception'), (3, 'line'), (4, 'line'), (4, 'return')] class Tracer: def __init__(self): self.events = [] def trace(self, frame, event, arg): self.events.append((frame.f_lineno, event)) return self.trace class TraceTestCase(unittest.TestCase): def compare_events(self, line_offset, events, expected_events): events = [(l - line_offset, e) for (l, e) in events] if events != expected_events: self.fail( "events did not match expectation:\n" + "\n".join(difflib.ndiff(map(str, expected_events), map(str, events)))) def run_test(self, func): tracer = Tracer() sys.settrace(tracer.trace) func() sys.settrace(None) self.compare_events(func.func_code.co_firstlineno, tracer.events, func.events) def run_test2(self, func): tracer = Tracer() func(tracer.trace) sys.settrace(None) self.compare_events(func.func_code.co_firstlineno, tracer.events, func.events) def test_1_basic(self): self.run_test(basic) def test_2_arigo(self): self.run_test(arigo_example) def test_3_one_instr(self): self.run_test(one_instr_line) def test_4_no_pop_blocks(self): self.run_test(no_pop_blocks) def test_5_no_pop_tops(self): self.run_test(no_pop_tops) def test_6_call(self): self.run_test(call) def test_7_raise(self): self.run_test(test_raise) def test_8_settrace_and_return(self): self.run_test2(settrace_and_return) def test_9_settrace_and_raise(self): self.run_test2(settrace_and_raise) class RaisingTraceFuncTestCase(unittest.TestCase): def test_it(self): def tr(frame, event, arg): raise ValueError # just something that isn't RuntimeError def f(): return 1 try: for i in xrange(sys.getrecursionlimit() + 1): sys.settrace(tr) try: f() except ValueError: pass else: self.fail("exception not thrown!") except RuntimeError: self.fail("recursion counter not reset") def test_main(): test_support.run_unittest(TraceTestCase) test_support.run_unittest(RaisingTraceFuncTestCase) if __name__ == "__main__": test_main() From gvanrossum@users.sourceforge.net Wed Oct 2 16:47:07 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Wed, 02 Oct 2002 08:47:07 -0700 Subject: [Python-checkins] python/dist/src/Lib textwrap.py,1.15,1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv26720 Modified Files: textwrap.py Log Message: Fix an endcase bug: initial_indent was ignored when the text was short enough to fit in one line. Index: textwrap.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/textwrap.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** textwrap.py 22 Aug 2002 21:28:00 -0000 1.15 --- textwrap.py 2 Oct 2002 15:47:05 -0000 1.16 *************** *** 238,243 **** """ text = self._munge_whitespace(text) ! if len(text) <= self.width: ! return [text] chunks = self._split(text) if self.fix_sentence_endings: --- 238,244 ---- """ text = self._munge_whitespace(text) ! indent = self.initial_indent ! if len(text) + len(indent) <= self.width: ! return [indent + text] chunks = self._split(text) if self.fix_sentence_endings: From gvanrossum@users.sourceforge.net Wed Oct 2 16:47:34 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Wed, 02 Oct 2002 08:47:34 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_textwrap.py,1.14,1.15 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv26905 Modified Files: test_textwrap.py Log Message: Fix an endcase bug: initial_indent was ignored when the text was short enough to fit in one line. Index: test_textwrap.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_textwrap.py,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** test_textwrap.py 22 Aug 2002 21:27:05 -0000 1.14 --- test_textwrap.py 2 Oct 2002 15:47:32 -0000 1.15 *************** *** 34,42 **** self.show(expect), self.show(result))) ! def check_wrap (self, text, width, expect): ! result = wrap(text, width) self.check(result, expect) ! def check_split (self, wrapper, text, expect): result = wrapper._split(text) self.assertEquals(result, expect, --- 34,42 ---- self.show(expect), self.show(result))) ! def check_wrap(self, text, width, expect, **kwargs): ! result = wrap(text, width, **kwargs) self.check(result, expect) ! def check_split(self, wrapper, text, expect): result = wrapper._split(text) self.assertEquals(result, expect, *************** *** 100,103 **** --- 100,113 ---- "paragraph."]) self.check_wrap(text, 40, ["This is a short paragraph."]) + + + def test_wrap_short_1line(self): + # Test endcases + + text = "This is a short line." + + self.check_wrap(text, 30, ["This is a short line."]) + self.check_wrap(text, 30, ["(1) This is a short line."], + initial_indent="(1) ") From mhammond@users.sourceforge.net Thu Oct 3 06:10:40 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Wed, 02 Oct 2002 22:10:40 -0700 Subject: [Python-checkins] python/dist/src/Include pyerrors.h,2.60,2.61 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv29768/Include Modified Files: pyerrors.h Log Message: Patch 594001: PEP 277 - Unicode file name support for Windows NT. Index: pyerrors.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pyerrors.h,v retrieving revision 2.60 retrieving revision 2.61 diff -C2 -d -r2.60 -r2.61 *** pyerrors.h 15 Sep 2002 14:09:21 -0000 2.60 --- pyerrors.h 3 Oct 2002 05:10:38 -0000 2.61 *************** *** 82,95 **** PyAPI_FUNC(PyObject *) PyErr_NoMemory(void); PyAPI_FUNC(PyObject *) PyErr_SetFromErrno(PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilename(PyObject *, char *); PyAPI_FUNC(PyObject *) PyErr_Format(PyObject *, const char *, ...) Py_GCC_ATTRIBUTE((format(printf, 2, 3))); #ifdef MS_WINDOWS ! PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename(int, const char *); PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilename( PyObject *,int, const char *); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int); ! #endif /* Export the old function so that the existing API remains available: */ --- 82,116 ---- PyAPI_FUNC(PyObject *) PyErr_NoMemory(void); PyAPI_FUNC(PyObject *) PyErr_SetFromErrno(PyObject *); + PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenameObject( + PyObject *, PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilename(PyObject *, char *); + #ifdef Py_WIN_WIDE_FILENAMES + PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilename( + PyObject *, Py_UNICODE *); + #endif /* Py_WIN_WIDE_FILENAMES */ + PyAPI_FUNC(PyObject *) PyErr_Format(PyObject *, const char *, ...) Py_GCC_ATTRIBUTE((format(printf, 2, 3))); + #ifdef MS_WINDOWS ! PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilenameObject( ! int, const char *); ! PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename( ! int, const char *); ! #ifdef Py_WIN_WIDE_FILENAMES ! PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilename( ! int, const Py_UNICODE *); ! #endif /* Py_WIN_WIDE_FILENAMES */ PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int); + PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObject( + PyObject *,int, PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilename( PyObject *,int, const char *); + #ifdef Py_WIN_WIDE_FILENAMES + PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilename( + PyObject *,int, const Py_UNICODE *); + #endif /* Py_WIN_WIDE_FILENAMES */ PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int); ! #endif /* MS_WINDOWS */ /* Export the old function so that the existing API remains available: */ From mhammond@users.sourceforge.net Thu Oct 3 06:10:40 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Wed, 02 Oct 2002 22:10:40 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_unicode_file.py,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv29768/Lib/test Modified Files: test_unicode_file.py Log Message: Patch 594001: PEP 277 - Unicode file name support for Windows NT. Index: test_unicode_file.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_unicode_file.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** test_unicode_file.py 23 Jul 2002 19:04:08 -0000 1.5 --- test_unicode_file.py 3 Oct 2002 05:10:38 -0000 1.6 *************** *** 41,44 **** --- 41,48 ---- # Test rename + try: + os.unlink(TESTFN_ENCODED + ".new") + except os.error: + pass os.rename(TESTFN_ENCODED, TESTFN_ENCODED + ".new") os.rename(TESTFN_UNICODE+".new", TESTFN_ENCODED) From mhammond@users.sourceforge.net Thu Oct 3 06:10:41 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Wed, 02 Oct 2002 22:10:41 -0700 Subject: [Python-checkins] python/dist/src/PC pyconfig.h,1.14,1.15 Message-ID: Update of /cvsroot/python/python/dist/src/PC In directory usw-pr-cvs1:/tmp/cvs-serv29768/PC Modified Files: pyconfig.h Log Message: Patch 594001: PEP 277 - Unicode file name support for Windows NT. Index: pyconfig.h =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/pyconfig.h,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** pyconfig.h 19 Jul 2002 06:55:41 -0000 1.14 --- pyconfig.h 3 Oct 2002 05:10:39 -0000 1.15 *************** *** 401,404 **** --- 401,408 ---- #if Py_UNICODE_SIZE == 2 #define HAVE_USABLE_WCHAR_T + + /* Define to indicate that the Python Unicode representation can be passed + as-is to Win32 Wide API. */ + #define Py_WIN_WIDE_FILENAMES #endif From mhammond@users.sourceforge.net Thu Oct 3 06:10:41 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Wed, 02 Oct 2002 22:10:41 -0700 Subject: [Python-checkins] python/dist/src/Python errors.c,2.71,2.72 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv29768/Python Modified Files: errors.c Log Message: Patch 594001: PEP 277 - Unicode file name support for Windows NT. Index: errors.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/errors.c,v retrieving revision 2.71 retrieving revision 2.72 diff -C2 -d -r2.71 -r2.72 *** errors.c 29 Jul 2002 14:27:41 -0000 2.71 --- errors.c 3 Oct 2002 05:10:39 -0000 2.72 *************** *** 260,264 **** PyObject * ! PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) { PyObject *v; --- 260,264 ---- PyObject * ! PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) { PyObject *v; *************** *** 315,320 **** #endif /* Unix/Windows */ #endif /* PLAN 9*/ ! if (filename != NULL) ! v = Py_BuildValue("(iss)", i, s, filename); else v = Py_BuildValue("(is)", i, s); --- 315,320 ---- #endif /* Unix/Windows */ #endif /* PLAN 9*/ ! if (filenameObject != NULL) ! v = Py_BuildValue("(isO)", i, s, filenameObject); else v = Py_BuildValue("(is)", i, s); *************** *** 331,345 **** PyObject * PyErr_SetFromErrno(PyObject *exc) { ! return PyErr_SetFromErrnoWithFilename(exc, NULL); } #ifdef MS_WINDOWS /* Windows specific error code handling */ ! PyObject *PyErr_SetExcFromWindowsErrWithFilename( PyObject *exc, int ierr, ! const char *filename) { int len; --- 331,367 ---- PyObject * + PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) + { + PyObject *name = filename ? PyString_FromString(filename) : NULL; + PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); + Py_DECREF(name); + return result; + } + + #ifdef Py_WIN_WIDE_FILENAMES + PyObject * + PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, Py_UNICODE *filename) + { + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); + Py_XDECREF(name); + return result; + } + #endif /* Py_WIN_WIDE_FILENAMES */ + + PyObject * PyErr_SetFromErrno(PyObject *exc) { ! return PyErr_SetFromErrnoWithFilenameObject(exc, NULL); } #ifdef MS_WINDOWS /* Windows specific error code handling */ ! PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject( PyObject *exc, int ierr, ! PyObject *filenameObject) { int len; *************** *** 363,368 **** while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) s[--len] = '\0'; ! if (filename != NULL) ! v = Py_BuildValue("(iss)", err, s, filename); else v = Py_BuildValue("(is)", err, s); --- 385,390 ---- while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) s[--len] = '\0'; ! if (filenameObject != NULL) ! v = Py_BuildValue("(isO)", err, s, filenameObject); else v = Py_BuildValue("(is)", err, s); *************** *** 375,378 **** --- 397,430 ---- } + PyObject *PyErr_SetExcFromWindowsErrWithFilename( + PyObject *exc, + int ierr, + const char *filename) + { + PyObject *name = filename ? PyString_FromString(filename) : NULL; + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + ierr, + name); + Py_XDECREF(name); + return ret; + } + + #ifdef Py_WIN_WIDE_FILENAMES + PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename( + PyObject *exc, + int ierr, + const Py_UNICODE *filename) + { + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + ierr, + name); + Py_XDECREF(name); + return ret; + } + #endif /* Py_WIN_WIDE_FILENAMES */ + PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr) { *************** *** 389,395 **** const char *filename) { ! return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError, ! ierr, filename); } #endif /* MS_WINDOWS */ --- 441,467 ---- const char *filename) { ! PyObject *name = filename ? PyString_FromString(filename) : NULL; ! PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( ! PyExc_WindowsError, ! ierr, name); ! Py_XDECREF(result); ! return result; } + + #ifdef Py_WIN_WIDE_FILENAMES + PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename( + int ierr, + const Py_UNICODE *filename) + { + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( + PyExc_WindowsError, + ierr, name); + Py_XDECREF(result); + return result; + } + #endif /* Py_WIN_WIDE_FILENAMES */ #endif /* MS_WINDOWS */ From mhammond@users.sourceforge.net Thu Oct 3 06:10:41 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Wed, 02 Oct 2002 22:10:41 -0700 Subject: [Python-checkins] python/dist/src/Objects fileobject.c,2.168,2.169 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv29768/Objects Modified Files: fileobject.c Log Message: Patch 594001: PEP 277 - Unicode file name support for Windows NT. Index: fileobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v retrieving revision 2.168 retrieving revision 2.169 diff -C2 -d -r2.168 -r2.169 *** fileobject.c 14 Aug 2002 21:01:41 -0000 2.168 --- fileobject.c 3 Oct 2002 05:10:39 -0000 2.169 *************** *** 16,19 **** --- 16,25 ---- #endif + #ifdef _MSC_VER + /* Need GetVersion to see if on NT so safe to use _wfopen */ + #define WIN32_LEAN_AND_MEAN + #include + #endif /* _MSC_VER */ + #ifdef macintosh #ifdef USE_GUSI *************** *** 103,107 **** static PyObject * fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode, ! int (*close)(FILE *)) { assert(f != NULL); --- 109,113 ---- static PyObject * fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode, ! int (*close)(FILE *), PyObject *wname) { assert(f != NULL); *************** *** 111,115 **** Py_DECREF(f->f_name); Py_DECREF(f->f_mode); ! f->f_name = PyString_FromString(name); f->f_mode = PyString_FromString(mode); --- 117,124 ---- Py_DECREF(f->f_name); Py_DECREF(f->f_mode); ! if (wname) ! f->f_name = PyUnicode_FromObject(wname); ! else ! f->f_name = PyString_FromString(name); f->f_mode = PyString_FromString(mode); *************** *** 136,140 **** --- 145,154 ---- assert(f != NULL); assert(PyFile_Check(f)); + #ifdef MS_WINDOWS + /* windows ignores the passed name in order to support Unicode */ + assert(f->f_name != NULL); + #else assert(name != NULL); + #endif assert(mode != NULL); assert(f->f_fp == NULL); *************** *** 157,161 **** #endif { - Py_BEGIN_ALLOW_THREADS #ifdef WITH_UNIVERSAL_NEWLINES if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0) --- 171,174 ---- *************** *** 169,174 **** mode = "r"; #endif ! f->f_fp = fopen(name, mode); ! Py_END_ALLOW_THREADS } if (f->f_fp == NULL) { --- 182,205 ---- mode = "r"; #endif ! #ifdef MS_WINDOWS ! if (PyUnicode_Check(f->f_name)) { ! PyObject *wmode; ! wmode = PyUnicode_DecodeASCII(mode, strlen(mode), NULL); ! if (f->f_name && wmode) { ! Py_BEGIN_ALLOW_THREADS ! /* PyUnicode_AS_UNICODE OK without thread ! lock as it is a simple dereference. */ ! f->f_fp = _wfopen(PyUnicode_AS_UNICODE(f->f_name), ! PyUnicode_AS_UNICODE(wmode)); ! Py_END_ALLOW_THREADS ! } ! Py_XDECREF(wmode); ! } ! #endif ! if (NULL == f->f_fp && NULL != name) { ! Py_BEGIN_ALLOW_THREADS ! f->f_fp = fopen(name, mode); ! Py_END_ALLOW_THREADS ! } } if (f->f_fp == NULL) { *************** *** 202,206 **** --- 233,241 ---- mode); else + #ifdef MS_WINDOWS + PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, f->f_name); + #else PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); + #endif /* MS_WINDOWS */ f = NULL; } *************** *** 216,220 **** NULL, NULL); if (f != NULL) { ! if (fill_file_fields(f, fp, name, mode, close) == NULL) { Py_DECREF(f); f = NULL; --- 251,255 ---- NULL, NULL); if (f != NULL) { ! if (fill_file_fields(f, fp, name, mode, close, NULL) == NULL) { Py_DECREF(f); f = NULL; *************** *** 294,302 **** file_repr(PyFileObject *f) { ! return PyString_FromFormat("<%s file '%s', mode '%s' at %p>", f->f_fp == NULL ? "closed" : "open", PyString_AsString(f->f_name), PyString_AsString(f->f_mode), f); } --- 329,350 ---- file_repr(PyFileObject *f) { ! if (PyUnicode_Check(f->f_name)) { ! PyObject *ret = NULL; ! PyObject *name; ! name = PyUnicode_AsUnicodeEscapeString(f->f_name); ! ret = PyString_FromFormat("<%s file u'%s', mode '%s' at %p>", ! f->f_fp == NULL ? "closed" : "open", ! PyString_AsString(name), ! PyString_AsString(f->f_mode), ! f); ! Py_XDECREF(name); ! return ret; ! } else { ! return PyString_FromFormat("<%s file '%s', mode '%s' at %p>", f->f_fp == NULL ? "closed" : "open", PyString_AsString(f->f_name), PyString_AsString(f->f_mode), f); + } } *************** *** 1767,1770 **** --- 1815,1819 ---- char *mode = "r"; int bufsize = -1; + int wideargument = 0; assert(PyFile_Check(self)); *************** *** 1777,1786 **** } ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist, ! Py_FileSystemDefaultEncoding, &name, ! &mode, &bufsize)) ! return -1; ! if (fill_file_fields(foself, NULL, name, mode, fclose) == NULL) ! goto Error; if (open_the_file(foself, name, mode) == NULL) goto Error; --- 1826,1856 ---- } ! #ifdef Py_WIN_WIDE_FILENAMES ! if (GetVersion() < 0x80000000) { /* On NT, so wide API available */ ! PyObject *po; ! if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:file", ! kwlist, &po, &mode, &bufsize)) { ! wideargument = 1; ! if (fill_file_fields(foself, NULL, name, mode, ! fclose, po) == NULL) ! goto Error; ! } else { ! /* Drop the argument parsing error as narrow ! strings are also valid. */ ! PyErr_Clear(); ! } ! } ! #endif ! ! if (!wideargument) { ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist, ! Py_FileSystemDefaultEncoding, ! &name, ! &mode, &bufsize)) ! return -1; ! if (fill_file_fields(foself, NULL, name, mode, ! fclose, NULL) == NULL) ! goto Error; ! } if (open_the_file(foself, name, mode) == NULL) goto Error; From mhammond@users.sourceforge.net Thu Oct 3 06:10:41 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Wed, 02 Oct 2002 22:10:41 -0700 Subject: [Python-checkins] python/dist/src/Modules posixmodule.c,2.260,2.261 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv29768/Modules Modified Files: posixmodule.c Log Message: Patch 594001: PEP 277 - Unicode file name support for Windows NT. Index: posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.260 retrieving revision 2.261 diff -C2 -d -r2.260 -r2.261 *** posixmodule.c 19 Sep 2002 08:03:20 -0000 2.260 --- posixmodule.c 3 Oct 2002 05:10:38 -0000 2.261 *************** *** 368,371 **** --- 368,380 ---- } + #ifdef Py_WIN_WIDE_FILENAMES + static PyObject * + posix_error_with_unicode_filename(Py_UNICODE* name) + { + return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name); + } + #endif /* Py_WIN_WIDE_FILENAMES */ + + static PyObject * posix_error_with_allocated_filename(char* name) *************** *** 391,394 **** --- 400,437 ---- return PyErr_SetFromWindowsErr(errno); } + + #ifdef Py_WIN_WIDE_FILENAMES + static PyObject * + win32_error_unicode(char* function, Py_UNICODE* filename) + { + /* XXX - see win32_error for comments on 'function' */ + errno = GetLastError(); + if (filename) + return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename); + else + return PyErr_SetFromWindowsErr(errno); + } + + static PyObject *_PyUnicode_FromFileSystemEncodedObject(register PyObject *obj) + { + /* XXX Perhaps we should make this API an alias of + PyObject_Unicode() instead ?! */ + if (PyUnicode_CheckExact(obj)) { + Py_INCREF(obj); + return obj; + } + if (PyUnicode_Check(obj)) { + /* For a Unicode subtype that's not a Unicode object, + return a true Unicode object with the same data. */ + return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(obj), + PyUnicode_GET_SIZE(obj)); + } + return PyUnicode_FromEncodedObject(obj, + Py_FileSystemDefaultEncoding, + "strict"); + } + + #endif /* Py_WIN_WIDE_FILENAMES */ + #endif *************** *** 488,496 **** } static PyObject * ! posix_1str(PyObject *args, char *format, int (*func)(const char*)) { char *path1 = NULL; int res; if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1)) --- 531,578 ---- } + #ifdef Py_WIN_WIDE_FILENAMES + static int + unicode_file_names(void) + { + static int canusewide = -1; + if (canusewide == -1) { + /* As per doc for ::GetVersion(), this is the correct test for + the Windows NT family. */ + canusewide = (GetVersion() < 0x80000000) ? 1 : 0; + } + return canusewide; + } + #endif + static PyObject * ! posix_1str(PyObject *args, char *format, int (*func)(const char*), ! char *wformat, int (*wfunc)(const Py_UNICODE*)) { char *path1 = NULL; int res; + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, wformat, &po)) { + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE OK without thread + lock as it is a simple dereference. */ + res = (*wfunc)(PyUnicode_AS_UNICODE(po)); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; + } + /* Drop the argument parsing error as narrow + strings are also valid. */ + PyErr_Clear(); + } + #else + /* Platforms that don't support Unicode filenames + shouldn't be passing these extra params */ + assert(wformat==NULL && wfunc == NULL); + #endif + if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1)) *************** *** 507,515 **** static PyObject * ! posix_2str(PyObject *args, char *format, ! int (*func)(const char *, const char *)) { char *path1 = NULL, *path2 = NULL; int res; if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1, --- 589,640 ---- static PyObject * ! posix_2str(PyObject *args, ! char *format, ! int (*func)(const char *, const char *), ! char *wformat, ! int (*wfunc)(const Py_UNICODE *, const Py_UNICODE *)) { char *path1 = NULL, *path2 = NULL; int res; + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + PyObject *po1; + PyObject *po2; + if (PyArg_ParseTuple(args, wformat, &po1, &po2)) { + if (PyUnicode_Check(po1) || PyUnicode_Check(po2)) { + PyObject *wpath1; + PyObject *wpath2; + wpath1 = _PyUnicode_FromFileSystemEncodedObject(po1); + wpath2 = _PyUnicode_FromFileSystemEncodedObject(po2); + if (!wpath1 || !wpath2) { + Py_XDECREF(wpath1); + Py_XDECREF(wpath2); + return NULL; + } + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE OK without thread + lock as it is a simple dereference. */ + res = (*wfunc)(PyUnicode_AS_UNICODE(wpath1), + PyUnicode_AS_UNICODE(wpath2)); + Py_END_ALLOW_THREADS + Py_XDECREF(wpath1); + Py_XDECREF(wpath2); + if (res != 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; + } + /* Else flow through as neither is Unicode. */ + } + /* Drop the argument parsing error as narrow + strings are also valid. */ + PyErr_Clear(); + } + #else + /* Platforms that don't support Unicode filenames + shouldn't be passing these extra params */ + assert(wformat==NULL && wfunc == NULL); + #endif + if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1, *************** *** 693,698 **** static PyObject * ! posix_do_stat(PyObject *self, PyObject *args, char *format, ! int (*statfunc)(const char *, STRUCT_STAT *)) { STRUCT_STAT st; --- 818,826 ---- static PyObject * ! posix_do_stat(PyObject *self, PyObject *args, ! char *format, ! int (*statfunc)(const char *, STRUCT_STAT *), ! char *wformat, ! int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *)) { STRUCT_STAT st; *************** *** 706,709 **** --- 834,881 ---- #endif /* MS_WINDOWS */ + + #ifdef Py_WIN_WIDE_FILENAMES + /* If on wide-character-capable OS see if argument + is Unicode and if so use wide API. */ + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, wformat, &po)) { + Py_UNICODE wpath[MAX_PATH+1]; + pathlen = wcslen(PyUnicode_AS_UNICODE(po)); + /* the library call can blow up if the file name is too long! */ + if (pathlen > MAX_PATH) { + errno = ENAMETOOLONG; + return posix_error(); + } + wcscpy(wpath, PyUnicode_AS_UNICODE(po)); + /* Remove trailing slash or backslash, unless it's the current + drive root (/ or \) or a specific drive's root (like c:\ or c:/). + */ + if (pathlen > 0 && + (wpath[pathlen-1]== L'\\' || wpath[pathlen-1] == L'/')) { + /* It does end with a slash -- exempt the root drive cases. */ + /* XXX UNC root drives should also be exempted? */ + if (pathlen == 1 || (pathlen == 3 && wpath[1] == L':')) + /* leave it alone */; + else { + /* nuke the trailing backslash */ + wpath[pathlen-1] = L'\0'; + } + } + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE result OK without + thread lock as it is a simple dereference. */ + res = wstatfunc(wpath, &st); + Py_END_ALLOW_THREADS + if (res != 0) + return posix_error_with_unicode_filename(wpath); + return _pystat_fromstructstat(st); + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif + if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path)) *************** *** 840,847 **** posix_chdir(PyObject *self, PyObject *args) { ! #if defined(PYOS_OS2) && defined(PYCC_GCC) ! return posix_1str(args, "et:chdir", _chdir2); #else ! return posix_1str(args, "et:chdir", chdir); #endif } --- 1012,1021 ---- posix_chdir(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_1str(args, "et:chdir", chdir, "U:chdir", _wchdir); ! #elif defined(PYOS_OS2) && defined(PYCC_GCC) ! return posix_1str(args, "et:chdir", _chdir2, NULL, NULL); #else ! return posix_1str(args, "et:chdir", chdir, NULL, NULL); #endif } *************** *** 893,897 **** posix_chroot(PyObject *self, PyObject *args) { ! return posix_1str(args, "et:chroot", chroot); } #endif --- 1067,1071 ---- posix_chroot(PyObject *self, PyObject *args) { ! return posix_1str(args, "et:chroot", chroot, NULL, NULL); } #endif *************** *** 1005,1008 **** --- 1179,1219 ---- return PyString_FromString(buf); } + + PyDoc_STRVAR(posix_getcwdu__doc__, + "getcwdu() -> path\n\n\ + Return a unicode string representing the current working directory."); + + static PyObject * + posix_getcwdu(PyObject *self, PyObject *args) + { + char buf[1026]; + char *res; + if (!PyArg_ParseTuple(args, ":getcwd")) + return NULL; + + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + wchar_t *wres; + wchar_t wbuf[1026]; + Py_BEGIN_ALLOW_THREADS + wres = _wgetcwd(wbuf, sizeof wbuf/ sizeof wbuf[0]); + Py_END_ALLOW_THREADS + if (wres == NULL) + return posix_error(); + return PyUnicode_FromWideChar(wbuf, wcslen(wbuf)); + } + #endif + + Py_BEGIN_ALLOW_THREADS + #if defined(PYOS_OS2) && defined(PYCC_GCC) + res = _getcwd2(buf, sizeof buf); + #else + res = getcwd(buf, sizeof buf); + #endif + Py_END_ALLOW_THREADS + if (res == NULL) + return posix_error(); + return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict"); + } #endif *************** *** 1016,1020 **** posix_link(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:link", link); } #endif /* HAVE_LINK */ --- 1227,1231 ---- posix_link(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:link", link, NULL, NULL); } #endif /* HAVE_LINK */ *************** *** 1045,1048 **** --- 1256,1319 ---- int len = sizeof(namebuf)/sizeof(namebuf[0]); + #ifdef Py_WIN_WIDE_FILENAMES + /* If on wide-character-capable OS see if argument + is Unicode and if so use wide API. */ + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, "U:listdir", &po)) { + WIN32_FIND_DATAW wFileData; + Py_UNICODE wnamebuf[MAX_PATH*2+5]; + Py_UNICODE wch; + wcsncpy(wnamebuf, PyUnicode_AS_UNICODE(po), MAX_PATH); + wnamebuf[MAX_PATH] = L'\0'; + len = wcslen(wnamebuf); + wch = (len > 0) ? wnamebuf[len-1] : L'\0'; + if (wch != L'/' && wch != L'\\' && wch != L':') + wnamebuf[len++] = L'/'; + wcscpy(wnamebuf + len, L"*.*"); + if ((d = PyList_New(0)) == NULL) + return NULL; + hFindFile = FindFirstFileW(wnamebuf, &wFileData); + if (hFindFile == INVALID_HANDLE_VALUE) { + errno = GetLastError(); + if (errno == ERROR_FILE_NOT_FOUND) { + return d; + } + Py_DECREF(d); + return win32_error_unicode("FindFirstFileW", wnamebuf); + } + do { + if (wFileData.cFileName[0] == L'.' && + (wFileData.cFileName[1] == L'\0' || + wFileData.cFileName[1] == L'.' && + wFileData.cFileName[2] == L'\0')) + continue; + v = PyUnicode_FromUnicode(wFileData.cFileName, wcslen(wFileData.cFileName)); + if (v == NULL) { + Py_DECREF(d); + d = NULL; + break; + } + if (PyList_Append(d, v) != 0) { + Py_DECREF(v); + Py_DECREF(d); + d = NULL; + break; + } + Py_DECREF(v); + } while (FindNextFileW(hFindFile, &wFileData) == TRUE); + + if (FindClose(hFindFile) == FALSE) { + Py_DECREF(d); + return win32_error_unicode("FindClose", wnamebuf); + } + return d; + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif + if (!PyArg_ParseTuple(args, "et#:listdir", Py_FileSystemDefaultEncoding, &bufptr, &len)) *************** *** 1062,1066 **** errno = GetLastError(); if (errno == ERROR_FILE_NOT_FOUND) ! return PyList_New(0); return win32_error("FindFirstFile", namebuf); } --- 1333,1338 ---- errno = GetLastError(); if (errno == ERROR_FILE_NOT_FOUND) ! return d; ! Py_DECREF(d); return win32_error("FindFirstFile", namebuf); } *************** *** 1086,1091 **** } while (FindNextFile(hFindFile, &FileData) == TRUE); ! if (FindClose(hFindFile) == FALSE) return win32_error("FindClose", namebuf); return d; --- 1358,1365 ---- } while (FindNextFile(hFindFile, &FileData) == TRUE); ! if (FindClose(hFindFile) == FALSE) { ! Py_DECREF(d); return win32_error("FindClose", namebuf); + } return d; *************** *** 1214,1217 **** --- 1488,1508 ---- char outbuf[MAX_PATH*2]; char *temp; + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) { + Py_UNICODE woutbuf[MAX_PATH*2]; + Py_UNICODE *wtemp; + if (!GetFullPathNameW(PyUnicode_AS_UNICODE(po), + sizeof(woutbuf)/sizeof(woutbuf[0]), + woutbuf, &wtemp)) + return win32_error("GetFullPathName", ""); + return PyUnicode_FromUnicode(woutbuf, wcslen(woutbuf)); + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif if (!PyArg_ParseTuple (args, "et#:_getfullpathname", Py_FileSystemDefaultEncoding, &inbufp, *************** *** 1235,1238 **** --- 1526,1550 ---- char *path = NULL; int mode = 0777; + + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, "U|i:mkdir", &po)) { + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE OK without thread lock as + it is a simple dereference. */ + res = _wmkdir(PyUnicode_AS_UNICODE(po)); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif + if (!PyArg_ParseTuple(args, "et|i:mkdir", Py_FileSystemDefaultEncoding, &path, &mode)) *************** *** 1303,1307 **** posix_rename(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:rename", rename); } --- 1615,1623 ---- posix_rename(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_2str(args, "etet:rename", rename, "OO:rename", _wrename); ! #else ! return posix_2str(args, "etet:rename", rename, NULL, NULL); ! #endif } *************** *** 1314,1318 **** posix_rmdir(PyObject *self, PyObject *args) { ! return posix_1str(args, "et:rmdir", rmdir); } --- 1630,1638 ---- posix_rmdir(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_1str(args, "et:rmdir", rmdir, "U:rmdir", _wrmdir); ! #else ! return posix_1str(args, "et:rmdir", rmdir, NULL, NULL); ! #endif } *************** *** 1325,1329 **** posix_stat(PyObject *self, PyObject *args) { ! return posix_do_stat(self, args, "et:stat", STAT); } --- 1645,1653 ---- posix_stat(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_do_stat(self, args, "et:stat", STAT, "U:stat", _wstati64); ! #else ! return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL); ! #endif } *************** *** 1377,1381 **** posix_unlink(PyObject *self, PyObject *args) { ! return posix_1str(args, "et:remove", unlink); } --- 1701,1709 ---- posix_unlink(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_1str(args, "et:remove", unlink, "U:remove", _wunlink); ! #else ! return posix_1str(args, "et:remove", unlink, NULL, NULL); ! #endif } *************** *** 4151,4157 **** { #ifdef HAVE_LSTAT ! return posix_do_stat(self, args, "et:lstat", lstat); #else /* !HAVE_LSTAT */ ! return posix_do_stat(self, args, "et:lstat", STAT); #endif /* !HAVE_LSTAT */ } --- 4479,4489 ---- { #ifdef HAVE_LSTAT ! return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL); #else /* !HAVE_LSTAT */ ! #ifdef MS_WINDOWS ! return posix_do_stat(self, args, "et:lstat", STAT, "u:lstat", _wstati64); ! #else ! return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL); ! #endif #endif /* !HAVE_LSTAT */ } *************** *** 4189,4193 **** posix_symlink(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:symlink", symlink); } #endif /* HAVE_SYMLINK */ --- 4521,4525 ---- posix_symlink(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:symlink", symlink, NULL, NULL); } #endif /* HAVE_SYMLINK */ *************** *** 4370,4373 **** --- 4702,4725 ---- int mode = 0777; int fd; + + #ifdef MS_WINDOWS + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, "Ui|i:mkdir", &po, &flag, &mode)) { + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE OK without thread + lock as it is a simple dereference. */ + fd = _wopen(PyUnicode_AS_UNICODE(po), flag, mode); + Py_END_ALLOW_THREADS + if (fd < 0) + return posix_error(); + return PyInt_FromLong((long)fd); + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif + if (!PyArg_ParseTuple(args, "eti|i", Py_FileSystemDefaultEncoding, &file, *************** *** 6342,6345 **** --- 6694,6698 ---- #ifdef HAVE_GETCWD {"getcwd", posix_getcwd, METH_VARARGS, posix_getcwd__doc__}, + {"getcwdu", posix_getcwdu, METH_VARARGS, posix_getcwdu__doc__}, #endif #ifdef HAVE_LINK From mhammond@users.sourceforge.net Thu Oct 3 08:24:51 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Thu, 03 Oct 2002 00:24:51 -0700 Subject: [Python-checkins] python/dist/src/Modules posixmodule.c,2.261,2.262 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv12496 Modified Files: posixmodule.c Log Message: Trivial fix to the pep277 checkin: ensure that exceptions always have a filename attribute (previously did only when string filenames were passed, but not when unicode) Index: posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.261 retrieving revision 2.262 diff -C2 -d -r2.261 -r2.262 *** posixmodule.c 3 Oct 2002 05:10:38 -0000 2.261 --- posixmodule.c 3 Oct 2002 07:24:48 -0000 2.262 *************** *** 561,565 **** Py_END_ALLOW_THREADS if (res < 0) ! return posix_error(); Py_INCREF(Py_None); return Py_None; --- 561,565 ---- Py_END_ALLOW_THREADS if (res < 0) ! return posix_error_with_unicode_filename(PyUnicode_AS_UNICODE(po)); Py_INCREF(Py_None); return Py_None; From mwh@users.sourceforge.net Thu Oct 3 10:42:04 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Thu, 03 Oct 2002 02:42:04 -0700 Subject: [Python-checkins] python/dist/src/Lib symbol.py,1.14,1.15 token.py,1.12,1.13 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv28019 Modified Files: symbol.py token.py Log Message: Updates to track Grammar changes. The patch to token.py loosens the regexp to allow "testlist1" to be snagged. Index: symbol.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/symbol.py,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** symbol.py 17 Oct 2001 13:13:04 -0000 1.14 --- symbol.py 3 Oct 2002 09:42:01 -0000 1.15 *************** *** 77,80 **** --- 77,82 ---- list_for = 320 list_if = 321 + testlist1 = 322 + encoding_decl = 323 #--end constants-- Index: token.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/token.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** token.py 13 Aug 2001 15:48:06 -0000 1.12 --- token.py 3 Oct 2002 09:42:01 -0000 1.13 *************** *** 99,103 **** fp.close() prog = re.compile( ! "#define[ \t][ \t]*([A-Z][A-Z_]*)[ \t][ \t]*([0-9][0-9]*)", re.IGNORECASE) tokens = {} --- 99,103 ---- fp.close() prog = re.compile( ! "#define[ \t][ \t]*([A-Z0-9][A-Z0-9_]*)[ \t][ \t]*([0-9][0-9]*)", re.IGNORECASE) tokens = {} From mwh@users.sourceforge.net Thu Oct 3 10:50:49 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Thu, 03 Oct 2002 02:50:49 -0700 Subject: [Python-checkins] python/dist/src/Python compile.c,2.263,2.264 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv607/Python Modified Files: compile.c Log Message: Clamp code objects' tp_compare result to [-1, 1]. Bugfix candidate. Index: compile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v retrieving revision 2.263 retrieving revision 2.264 diff -C2 -d -r2.263 -r2.264 *** compile.c 30 Aug 2002 13:09:51 -0000 2.263 --- compile.c 3 Oct 2002 09:50:47 -0000 2.264 *************** *** 197,205 **** if (cmp) return cmp; cmp = co->co_argcount - cp->co_argcount; ! if (cmp) return cmp; cmp = co->co_nlocals - cp->co_nlocals; ! if (cmp) return cmp; cmp = co->co_flags - cp->co_flags; ! if (cmp) return cmp; cmp = PyObject_Compare(co->co_code, cp->co_code); if (cmp) return cmp; --- 197,205 ---- if (cmp) return cmp; cmp = co->co_argcount - cp->co_argcount; ! if (cmp) return (cmp<0)?-1:1; cmp = co->co_nlocals - cp->co_nlocals; ! if (cmp) return (cmp<0)?-1:1; cmp = co->co_flags - cp->co_flags; ! if (cmp) return (cmp<0)?-1:1; cmp = PyObject_Compare(co->co_code, cp->co_code); if (cmp) return cmp; From mwh@users.sourceforge.net Thu Oct 3 10:53:13 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Thu, 03 Oct 2002 02:53:13 -0700 Subject: [Python-checkins] python/dist/src/Python ceval.c,2.337,2.338 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv1097/Python Modified Files: ceval.c Log Message: One last tweak to the tracing machinery: this actually computes what I intended all along. Before instr_lb tended to be too high. I don't think this actually makes any difference, given what the compiler produces, but it makes me a bit happier. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.337 retrieving revision 2.338 diff -C2 -d -r2.337 -r2.338 *** ceval.c 2 Oct 2002 13:13:46 -0000 2.337 --- ceval.c 3 Oct 2002 09:53:11 -0000 2.338 *************** *** 2967,2973 **** --- 2967,2975 ---- break; addr += *p++; + if (*p) *instr_lb = addr; line += *p++; --size; } + if (addr == frame->f_lasti) { frame->f_lineno = line; *************** *** 2975,2979 **** PyTrace_LINE, Py_None); } ! *instr_lb = addr; if (size > 0) { while (--size >= 0) { --- 2977,2981 ---- PyTrace_LINE, Py_None); } ! if (size > 0) { while (--size >= 0) { From neal@metaslash.com Thu Oct 3 14:02:11 2002 From: neal@metaslash.com (Neal Norwitz) Date: Thu, 3 Oct 2002 09:02:11 -0400 Subject: [Python-checkins] python/dist/src/Python errors.c,2.71,2.72 In-Reply-To: References: Message-ID: <20021003130211.GA27448@epoch.metaslash.com> On Wed, Oct 02, 2002 at 10:10:41PM -0700, mhammond@users.sourceforge.net wrote: > > PyObject * > + PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) > + { > + PyObject *name = filename ? PyString_FromString(filename) : NULL; > + PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); > + Py_DECREF(name); Should be Py_XDECREF(). > --- 441,467 ---- > const char *filename) > { > ! PyObject *name = filename ? PyString_FromString(filename) : NULL; > ! PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( > ! PyExc_WindowsError, > ! ierr, name); > ! Py_XDECREF(result); > ! return result; Should be DECREFing name, right? > + > + #ifdef Py_WIN_WIDE_FILENAMES > + PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename( > + int ierr, > + const Py_UNICODE *filename) > + { > + PyObject *name = filename ? > + PyUnicode_FromUnicode(filename, wcslen(filename)) : > + NULL; > + PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( > + PyExc_WindowsError, > + ierr, name); > + Py_XDECREF(result); > + return result; Should be DECREFing name here too? Neal From montanaro@users.sourceforge.net Thu Oct 3 15:56:11 2002 From: montanaro@users.sourceforge.net (montanaro@users.sourceforge.net) Date: Thu, 03 Oct 2002 07:56:11 -0700 Subject: [Python-checkins] python/dist/src/Lib ConfigParser.py,1.38.10.4,1.38.10.5 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv13419 Modified Files: Tag: release22-maint ConfigParser.py Log Message: Python 2.2 doesn't have basestring. Index: ConfigParser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ConfigParser.py,v retrieving revision 1.38.10.4 retrieving revision 1.38.10.5 diff -C2 -d -r1.38.10.4 -r1.38.10.5 *** ConfigParser.py 27 Sep 2002 16:34:30 -0000 1.38.10.4 --- ConfigParser.py 3 Oct 2002 14:56:08 -0000 1.38.10.5 *************** *** 223,227 **** filename may also be given. """ ! if isinstance(filenames, basestring): filenames = [filenames] for filename in filenames: --- 223,227 ---- filename may also be given. """ ! if isinstance(filenames, (str, unicode)): filenames = [filenames] for filename in filenames: From guido@python.org Thu Oct 3 16:17:29 2002 From: guido@python.org (Guido van Rossum) Date: Thu, 03 Oct 2002 11:17:29 -0400 Subject: [Python-checkins] python/dist/src/Lib ConfigParser.py,1.38.10.4,1.38.10.5 In-Reply-To: Your message of "Thu, 03 Oct 2002 07:56:11 PDT." References: Message-ID: <200210031517.g93FHTU20390@odiug.zope.com> > Index: ConfigParser.py > =================================================================== > RCS file: /cvsroot/python/python/dist/src/Lib/ConfigParser.py,v > retrieving revision 1.38.10.4 > retrieving revision 1.38.10.5 > diff -C2 -d -r1.38.10.4 -r1.38.10.5 > *** ConfigParser.py 27 Sep 2002 16:34:30 -0000 1.38.10.4 > --- ConfigParser.py 3 Oct 2002 14:56:08 -0000 1.38.10.5 > *************** > *** 223,227 **** > filename may also be given. > """ > ! if isinstance(filenames, basestring): > filenames = [filenames] > for filename in filenames: > --- 223,227 ---- > filename may also be given. > """ > ! if isinstance(filenames, (str, unicode)): > filenames = [filenames] > for filename in filenames: The correct idiom for this is to use types.StringTypes. --Guido van Rossum (home page: http://www.python.org/~guido/) From montanaro@users.sourceforge.net Thu Oct 3 16:27:49 2002 From: montanaro@users.sourceforge.net (montanaro@users.sourceforge.net) Date: Thu, 03 Oct 2002 08:27:49 -0700 Subject: [Python-checkins] python/dist/src/Lib ConfigParser.py,1.38.10.5,1.38.10.6 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv2108 Modified Files: Tag: release22-maint ConfigParser.py Log Message: use types.StringTypes instead of (str, unicode) Index: ConfigParser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ConfigParser.py,v retrieving revision 1.38.10.5 retrieving revision 1.38.10.6 diff -C2 -d -r1.38.10.5 -r1.38.10.6 *** ConfigParser.py 3 Oct 2002 14:56:08 -0000 1.38.10.5 --- ConfigParser.py 3 Oct 2002 15:27:47 -0000 1.38.10.6 *************** *** 85,88 **** --- 85,89 ---- import re + import types __all__ = ["NoSectionError","DuplicateSectionError","NoOptionError", *************** *** 223,227 **** filename may also be given. """ ! if isinstance(filenames, (str, unicode)): filenames = [filenames] for filename in filenames: --- 224,228 ---- filename may also be given. """ ! if isinstance(filenames, types.StringTypes): filenames = [filenames] for filename in filenames: From neal@metaslash.com Thu Oct 3 23:36:52 2002 From: neal@metaslash.com (Neal Norwitz) Date: Thu, 3 Oct 2002 18:36:52 -0400 Subject: [Python-checkins] python/dist/src/Objects fileobject.c,2.168,2.169 In-Reply-To: References: Message-ID: <20021003223651.GD27448@epoch.metaslash.com> > --- 329,350 ---- > file_repr(PyFileObject *f) > { > ! if (PyUnicode_Check(f->f_name)) { > ! PyObject *ret = NULL; > ! PyObject *name; > ! name = PyUnicode_AsUnicodeEscapeString(f->f_name); Doesn't name need to be checked here for NULL? It's passed to PyString_AsString on the line below. > ! ret = PyString_FromFormat("<%s file u'%s', mode '%s' at %p>", > ! f->f_fp == NULL ? "closed" : "open", > ! PyString_AsString(name), > ! PyString_AsString(f->f_mode), > ! f); > ! Py_XDECREF(name); > ! return ret; > --- 1826,1856 ---- > } > > ! #ifdef Py_WIN_WIDE_FILENAMES > ! if (GetVersion() < 0x80000000) { /* On NT, so wide API available */ Did you mean 'no wide' instead of 'so wide'? Neal From neal@metaslash.com Fri Oct 4 00:07:26 2002 From: neal@metaslash.com (Neal Norwitz) Date: Thu, 3 Oct 2002 19:07:26 -0400 Subject: [Python-checkins] python/dist/src/Modules posixmodule.c,2.260,2.261 In-Reply-To: References: Message-ID: <20021003230726.GE27448@epoch.metaslash.com> > + static PyObject * > + posix_getcwdu(PyObject *self, PyObject *args) > + { > + char buf[1026]; > + char *res; > + if (!PyArg_ParseTuple(args, ":getcwd")) > + return NULL; Don't need to check args if posix_getcwdu is METH_NOARGS. > + if (v == NULL) { > + Py_DECREF(d); > + d = NULL; > + break; > + } > + if (PyList_Append(d, v) != 0) { > + Py_DECREF(v); > + Py_DECREF(d); > + d = NULL; > + break; > + } > + Py_DECREF(v); > + } while (FindNextFileW(hFindFile, &wFileData) == TRUE); > + > + if (FindClose(hFindFile) == FALSE) { > + Py_DECREF(d); Should be XDECREF? d will be set to NULL if an error occured. Not sure if FindClose() == FALSE if there's an error. This is around line 1307. > --- 1358,1365 ---- > } while (FindNextFile(hFindFile, &FileData) == TRUE); > > ! if (FindClose(hFindFile) == FALSE) { > ! Py_DECREF(d); Should be XDECREF? d could be set to NULL about 10 lines up (not in context). > *************** > *** 1235,1238 **** > --- 1526,1550 ---- > char *path = NULL; > int mode = 0777; > + > + #ifdef Py_WIN_WIDE_FILENAMES > + if (unicode_file_names()) { > + PyUnicodeObject *po; > + if (PyArg_ParseTuple(args, "U|i:mkdir", &po)) { Do you need another variable to capture i? (U|i) PyArg_ParseTuple() about line 1493 has U|: is the | useful? > *************** > *** 1377,1381 **** > posix_unlink(PyObject *self, PyObject *args) > { > ! return posix_1str(args, "et:remove", unlink); > } > > --- 1701,1709 ---- > posix_unlink(PyObject *self, PyObject *args) > { > ! #ifdef MS_WINDOWS > ! return posix_1str(args, "et:remove", unlink, "U:remove", _wunlink); > ! #else > ! return posix_1str(args, "et:remove", unlink, NULL, NULL); > ! #endif > } Should that be :remove or :unlink? > *************** > *** 4370,4373 **** > --- 4702,4725 ---- > int mode = 0777; > int fd; > + > + #ifdef MS_WINDOWS > + if (unicode_file_names()) { > + PyUnicodeObject *po; > + if (PyArg_ParseTuple(args, "Ui|i:mkdir", &po, &flag, &mode)) { Should be :open instead of :mkdir? > {"getcwd", posix_getcwd, METH_VARARGS, posix_getcwd__doc__}, > + {"getcwdu", posix_getcwdu, METH_VARARGS, posix_getcwdu__doc__}, Can be METH_NOARGS (same note as above). Same w/getcwd. Neal From mhammond@users.sourceforge.net Fri Oct 4 00:14:12 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Thu, 03 Oct 2002 16:14:12 -0700 Subject: [Python-checkins] python/dist/src/Lib/test/output test_pep277,NONE,1.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test/output In directory usw-pr-cvs1:/tmp/cvs-serv30020/output Added Files: test_pep277 Log Message: Tests for pep277 - Unicode file names on Windows NT. --- NEW FILE: test_pep277 --- test_pep277 u'F:\\src\\python-cvs\\Lib\\test\\@test\\Gr\xfc\xdf-\u66e8\u66e9\u66eb\\\xdf-\u66e8\u66e9\u66eb' ['???', '???', '??????', '????????????', '????G\xdf', 'Ge??-sa?', 'Gr\xfc\xdf-Gott', 'abc', 'ascii'] [u'Gr\xfc\xdf-Gott', u'abc', u'ascii', u'\u0393\u03b5\u03b9\u03ac-\u03c3\u03b1\u03c2', u'\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435', u'\u05d4\u05e9\u05e7\u05e6\u05e5\u05e1', u'\u306b\u307d\u3093', u'\u66e8\u05e9\u3093\u0434\u0393\xdf', u'\u66e8\u66e9\u66eb'] From mhammond@users.sourceforge.net Fri Oct 4 00:14:12 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Thu, 03 Oct 2002 16:14:12 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_pep277.py,NONE,1.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv30020 Added Files: test_pep277.py Log Message: Tests for pep277 - Unicode file names on Windows NT. --- NEW FILE: test_pep277.py --- # -*- coding: utf-8 -*- # Test the Unicode versions of normal file functions # open, os.open, os.stat. os.listdir, os.rename, os.remove, os.mkdir, os.chdir, os.rmdir import os, unittest from test.test_support import TESTFN, TestSkipped, TestFailed, run_suite try: from nt import _getfullpathname except ImportError: raise TestSkipped, "test works only on NT" filenames = [ "abc", unicode("ascii","utf-8"), unicode("Grüß-Gott","utf-8"), unicode("Γειά-σας","utf-8"), unicode("Здравствуйте","utf-8"), unicode("にぽん","utf-8"), unicode("השקצץס","utf-8"), unicode("曨曩曫","utf-8"), unicode("曨שんдΓß","utf-8"), ] class UnicodeFileTests(unittest.TestCase): def setUp(self): self.files = [os.path.join(TESTFN, f) for f in filenames] try: os.mkdir(TESTFN) except OSError: pass for name in self.files: f = open(name, 'w') f.write((name+'\n').encode("utf-8")) f.close() os.stat(name) def tearDown(self): for name in self.files: os.unlink(name) os.rmdir(TESTFN) def _apply_failure(self, fn, filename, expected_exception, check_fn_in_exception = True): try: fn(filename) raise TestFailed("Expected to fail calling '%s(%r)'" % (fn.__name__, filename)) except expected_exception, details: if check_fn_in_exception and details.filename != filename: raise TestFailed("Function '%s(%r) failed with " "bad filename in the exception: %r" % (fn.__name__, filename, details.filename)) def test_failures(self): # Pass non-existing Unicode filenames all over the place. for name in self.files: name = "not_" + name self._apply_failure(open, name, IOError) self._apply_failure(os.stat, name, OSError) self._apply_failure(os.chdir, name, OSError) self._apply_failure(os.rmdir, name, OSError) self._apply_failure(os.remove, name, OSError) # listdir may append a wildcard to the filename, so dont check self._apply_failure(os.listdir, name, OSError, False) def test_open(self): for name in self.files: f = open(name, 'w') f.write((name+'\n').encode("utf-8")) f.close() os.stat(name) def test_listdir(self): f1 = os.listdir(TESTFN) f1.sort() f2 = os.listdir(unicode(TESTFN,"mbcs")) f2.sort() print f1 print f2 def test_rename(self): for name in self.files: os.rename(name,"tmp") os.rename("tmp",name) def test_directory(self): dirname = unicode(os.path.join(TESTFN,"Grüß-曨曩曫"),"utf-8") filename = unicode("ß-曨曩曫","utf-8") oldwd = os.getcwd() os.mkdir(dirname) os.chdir(dirname) f = open(filename, 'w') f.write((filename + '\n').encode("utf-8")) f.close() print repr(_getfullpathname(filename)) os.remove(filename) os.chdir(oldwd) os.rmdir(dirname) def test_main(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(UnicodeFileTests)) run_suite(suite) if __name__ == "__main__": test_main() From mhammond@users.sourceforge.net Fri Oct 4 01:09:40 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Thu, 03 Oct 2002 17:09:40 -0700 Subject: [Python-checkins] python/dist/src/Python errors.c,2.72,2.73 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv14776 Modified Files: errors.c Log Message: Fix errors to pep277 checkin identified by Neal Norwitz. Index: errors.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/errors.c,v retrieving revision 2.72 retrieving revision 2.73 diff -C2 -d -r2.72 -r2.73 *** errors.c 3 Oct 2002 05:10:39 -0000 2.72 --- errors.c 4 Oct 2002 00:09:38 -0000 2.73 *************** *** 335,339 **** PyObject *name = filename ? PyString_FromString(filename) : NULL; PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); ! Py_DECREF(name); return result; } --- 335,339 ---- PyObject *name = filename ? PyString_FromString(filename) : NULL; PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); ! Py_XDECREF(name); return result; } *************** *** 445,449 **** PyExc_WindowsError, ierr, name); ! Py_XDECREF(result); return result; } --- 445,449 ---- PyExc_WindowsError, ierr, name); ! Py_XDECREF(name); return result; } *************** *** 460,464 **** PyExc_WindowsError, ierr, name); ! Py_XDECREF(result); return result; } --- 460,464 ---- PyExc_WindowsError, ierr, name); ! Py_XDECREF(name); return result; } From mhammond@users.sourceforge.net Fri Oct 4 01:13:05 2002 From: mhammond@users.sourceforge.net (mhammond@users.sourceforge.net) Date: Thu, 03 Oct 2002 17:13:05 -0700 Subject: [Python-checkins] python/dist/src/Python errors.c,2.73,2.74 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv15788 Modified Files: errors.c Log Message: Fix [ 616716 ] Bug in PyErr_SetExcFromWindows Ensure that even if FormatMessage fails we (a) don't crash, and (b) provide something useful. Bugfix candidate. Index: errors.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/errors.c,v retrieving revision 2.73 retrieving revision 2.74 diff -C2 -d -r2.73 -r2.74 *** errors.c 4 Oct 2002 00:09:38 -0000 2.73 --- errors.c 4 Oct 2002 00:13:02 -0000 2.74 *************** *** 270,273 **** --- 270,274 ---- #ifdef MS_WINDOWS char *s_buf = NULL; + char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */ #endif #ifdef EINTR *************** *** 307,314 **** 0, /* size not used */ NULL); /* no args */ ! s = s_buf; ! /* remove trailing cr/lf and dots */ ! while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) ! s[--len] = '\0'; } } --- 308,323 ---- 0, /* size not used */ NULL); /* no args */ ! if (len==0) { ! /* Only ever seen this in out-of-mem ! situations */ ! sprintf(s_small_buf, "Windows Error 0x%X", i); ! s = s_small_buf; ! s_buf = NULL; ! } else { ! s = s_buf; ! /* remove trailing cr/lf and dots */ ! while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) ! s[--len] = '\0'; ! } } } *************** *** 367,370 **** --- 376,381 ---- int len; char *s; + char *s_buf = NULL; /* Free via LocalFree */ + char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */ PyObject *v; DWORD err = (DWORD)ierr; *************** *** 379,388 **** MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ ! (LPTSTR) &s, 0, /* size not used */ NULL); /* no args */ ! /* remove trailing cr/lf and dots */ ! while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) ! s[--len] = '\0'; if (filenameObject != NULL) v = Py_BuildValue("(isO)", err, s, filenameObject); --- 390,407 ---- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ ! (LPTSTR) &s_buf, 0, /* size not used */ NULL); /* no args */ ! if (len==0) { ! /* Only seen this in out of mem situations */ ! sprintf(s_small_buf, "Windows Error 0x%X", err); ! s = s_small_buf; ! s_buf = NULL; ! } else { ! s = s_buf; ! /* remove trailing cr/lf and dots */ ! while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) ! s[--len] = '\0'; ! } if (filenameObject != NULL) v = Py_BuildValue("(isO)", err, s, filenameObject); *************** *** 393,397 **** Py_DECREF(v); } ! LocalFree(s); return NULL; } --- 412,416 ---- Py_DECREF(v); } ! LocalFree(s_buf); return NULL; } From loewis@users.sourceforge.net Fri Oct 4 08:21:26 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Fri, 04 Oct 2002 00:21:26 -0700 Subject: [Python-checkins] python/dist/src/Python thread_pthread.h,2.40,2.41 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv31341/Python Modified Files: thread_pthread.h Log Message: Patch #618347: Work around Solaris 2.6 pthread.h bug. Will backport to 2.2. Index: thread_pthread.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/thread_pthread.h,v retrieving revision 2.40 retrieving revision 2.41 diff -C2 -d -r2.40 -r2.41 *** thread_pthread.h 17 Mar 2002 17:19:00 -0000 2.40 --- thread_pthread.h 4 Oct 2002 07:21:24 -0000 2.41 *************** *** 4,12 **** #include #include ! #ifdef __APPLE__ #define destructor xxdestructor #endif #include ! #ifdef __APPLE__ #undef destructor #endif --- 4,12 ---- #include #include ! #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) #define destructor xxdestructor #endif #include ! #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) #undef destructor #endif From loewis@users.sourceforge.net Fri Oct 4 08:21:26 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Fri, 04 Oct 2002 00:21:26 -0700 Subject: [Python-checkins] python/dist/src configure,1.338,1.339 configure.in,1.349,1.350 pyconfig.h.in,1.49,1.50 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv31341 Modified Files: configure configure.in pyconfig.h.in Log Message: Patch #618347: Work around Solaris 2.6 pthread.h bug. Will backport to 2.2. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.338 retrieving revision 1.339 diff -C2 -d -r1.338 -r1.339 *** configure 30 Sep 2002 16:19:47 -0000 1.338 --- configure 4 Oct 2002 07:21:21 -0000 1.339 *************** *** 1,4 **** #! /bin/sh ! # From configure.in Revision: 1.348 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. --- 1,4 ---- #! /bin/sh ! # From configure.in Revision: 1.349 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. *************** *** 10886,10889 **** --- 10886,10900 ---- esac fi + + if test "$posix_threads" = yes -a \ + "$ac_sys_system" = "SunOS" -a \ + "$ac_sys_release" = "5.6"; then + + cat >>confdefs.h <<\_ACEOF + #define HAVE_PTHREAD_DESTRUCTOR 1 + _ACEOF + + fi + fi Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.349 retrieving revision 1.350 diff -C2 -d -r1.349 -r1.350 *** configure.in 30 Sep 2002 16:19:47 -0000 1.349 --- configure.in 4 Oct 2002 07:21:24 -0000 1.350 *************** *** 1327,1330 **** --- 1327,1338 ---- esac fi + + if test "$posix_threads" = yes -a \ + "$ac_sys_system" = "SunOS" -a \ + "$ac_sys_release" = "5.6"; then + AC_DEFINE(HAVE_PTHREAD_DESTRUCTOR, 1, + [Defined for Solaris 2.6 bug in pthread header.]) + fi + fi Index: pyconfig.h.in =================================================================== RCS file: /cvsroot/python/python/dist/src/pyconfig.h.in,v retrieving revision 1.49 retrieving revision 1.50 diff -C2 -d -r1.49 -r1.50 *** pyconfig.h.in 10 Sep 2002 09:16:13 -0000 1.49 --- pyconfig.h.in 4 Oct 2002 07:21:24 -0000 1.50 *************** *** 305,308 **** --- 305,311 ---- #undef HAVE_PTH + /* Defined for Solaris 2.6 bug in pthread header. */ + #undef HAVE_PTHREAD_DESTRUCTOR + /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H From lemburg@users.sourceforge.net Fri Oct 4 10:23:46 2002 From: lemburg@users.sourceforge.net (lemburg@users.sourceforge.net) Date: Fri, 04 Oct 2002 02:23:46 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils/command __init__.py,1.15,1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/distutils/command In directory usw-pr-cvs1:/tmp/cvs-serv28397 Modified Files: __init__.py Log Message: Pulling Mark Alexander's contribution from CVS. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/distutils/command/__init__.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** __init__.py 17 Apr 2002 20:30:09 -0000 1.15 --- __init__.py 4 Oct 2002 09:23:44 -0000 1.16 *************** *** 22,27 **** 'bdist_rpm', 'bdist_wininst', ! 'bdist_sdux', ! 'bdist_pkgtool', # Note: # bdist_packager is not included because it only provides --- 22,28 ---- 'bdist_rpm', 'bdist_wininst', ! # These two are reserved for future use: ! #'bdist_sdux', ! #'bdist_pkgtool', # Note: # bdist_packager is not included because it only provides From lemburg@users.sourceforge.net Fri Oct 4 10:25:20 2002 From: lemburg@users.sourceforge.net (lemburg@users.sourceforge.net) Date: Fri, 04 Oct 2002 02:25:20 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils/command bdist_packager.py,1.7,NONE bdist_pkgtool.py,1.8,NONE bdist_sdux.py,1.5,NONE Message-ID: Update of /cvsroot/python/python/dist/src/Lib/distutils/command In directory usw-pr-cvs1:/tmp/cvs-serv29817 Removed Files: bdist_packager.py bdist_pkgtool.py bdist_sdux.py Log Message: Pulling Mark Alexander's contribution from CVS. --- bdist_packager.py DELETED --- --- bdist_pkgtool.py DELETED --- --- bdist_sdux.py DELETED --- From lemburg@users.sourceforge.net Fri Oct 4 10:30:08 2002 From: lemburg@users.sourceforge.net (lemburg@users.sourceforge.net) Date: Fri, 04 Oct 2002 02:30:08 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils/command bdist.py,1.25,1.26 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/distutils/command In directory usw-pr-cvs1:/tmp/cvs-serv800/command Modified Files: bdist.py Log Message: Pulling Mark Alexander's contribution from CVS. Index: bdist.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/distutils/command/bdist.py,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** bdist.py 17 Apr 2002 20:30:10 -0000 1.25 --- bdist.py 4 Oct 2002 09:30:06 -0000 1.26 *************** *** 53,57 **** # The following commands do not take a format option from bdist ! no_format_option = ('bdist_rpm', 'bdist_sdux', 'bdist_pkgtool') # This won't do in reality: will need to distinguish RPM-ish Linux, --- 53,59 ---- # The following commands do not take a format option from bdist ! no_format_option = ('bdist_rpm', ! #'bdist_sdux', 'bdist_pkgtool' ! ) # This won't do in reality: will need to distinguish RPM-ish Linux, *************** *** 63,71 **** # Establish the preferred order (for the --help-formats option). format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar', ! 'wininst', 'zip', 'pkgtool', 'sdux'] # And the real information. format_command = { 'rpm': ('bdist_rpm', "RPM distribution"), ! 'zip': ('bdist_dumb', "ZIP file"), 'gztar': ('bdist_dumb', "gzip'ed tar file"), 'bztar': ('bdist_dumb', "bzip2'ed tar file"), 'ztar': ('bdist_dumb', "compressed tar file"), --- 65,76 ---- # Establish the preferred order (for the --help-formats option). format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar', ! 'wininst', 'zip', ! #'pkgtool', 'sdux' ! ] # And the real information. format_command = { 'rpm': ('bdist_rpm', "RPM distribution"), ! 'zip': ('bdist_dumb', "ZIP file"), ! 'gztar': ('bdist_dumb', "gzip'ed tar file"), 'bztar': ('bdist_dumb', "bzip2'ed tar file"), 'ztar': ('bdist_dumb', "compressed tar file"), *************** *** 74,80 **** "Windows executable installer"), 'zip': ('bdist_dumb', "ZIP file"), ! 'pkgtool': ('bdist_pkgtool', ! "Solaris pkgtool distribution"), ! 'sdux': ('bdist_sdux', "HP-UX swinstall depot"), } --- 79,85 ---- "Windows executable installer"), 'zip': ('bdist_dumb', "ZIP file"), ! #'pkgtool': ('bdist_pkgtool', ! # "Solaris pkgtool distribution"), ! #'sdux': ('bdist_sdux', "HP-UX swinstall depot"), } From loewis@users.sourceforge.net Fri Oct 4 11:16:31 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Fri, 04 Oct 2002 03:16:31 -0700 Subject: [Python-checkins] python/dist/src configure,1.279.6.12,1.279.6.13 configure.in,1.288.6.12,1.288.6.13 pyconfig.h.in,1.20.8.1,1.20.8.2 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv28942 Modified Files: Tag: release22-maint configure configure.in pyconfig.h.in Log Message: Patch #618347: Work around Solaris pthread.h bug. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.279.6.12 retrieving revision 1.279.6.13 diff -C2 -d -r1.279.6.12 -r1.279.6.13 *** configure 30 Sep 2002 16:17:54 -0000 1.279.6.12 --- configure 4 Oct 2002 10:16:24 -0000 1.279.6.13 *************** *** 4383,4391 **** esac fi fi # Check for enable-ipv6 echo $ac_n "checking if --enable-ipv6 is specified""... $ac_c" 1>&6 ! echo "configure:4390: checking if --enable-ipv6 is specified" >&5 # Check whether --enable-ipv6 or --disable-ipv6 was given. if test "${enable_ipv6+set}" = set; then --- 4383,4401 ---- [...2375 lines suppressed...] if eval "test \"`echo '$''{'ac_cv_type_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 7577,7581 **** SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7580: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then --- 7587,7591 ---- SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7590: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.288.6.12 retrieving revision 1.288.6.13 diff -C2 -d -r1.288.6.12 -r1.288.6.13 *** configure.in 30 Sep 2002 16:16:11 -0000 1.288.6.12 --- configure.in 4 Oct 2002 10:16:27 -0000 1.288.6.13 *************** *** 1171,1174 **** --- 1171,1182 ---- esac fi + + if test "$posix_threads" = yes -a \ + "$ac_sys_system" = "SunOS" -a \ + "$ac_sys_release" = "5.6"; then + AC_DEFINE(HAVE_PTHREAD_DESTRUCTOR, 1, + [Defined for Solaris 2.6 bug in pthread header.]) + fi + fi Index: pyconfig.h.in =================================================================== RCS file: /cvsroot/python/python/dist/src/pyconfig.h.in,v retrieving revision 1.20.8.1 retrieving revision 1.20.8.2 diff -C2 -d -r1.20.8.1 -r1.20.8.2 *** pyconfig.h.in 30 Sep 2002 10:10:22 -0000 1.20.8.1 --- pyconfig.h.in 4 Oct 2002 10:16:27 -0000 1.20.8.2 *************** *** 751,754 **** --- 751,758 ---- #undef HAVE_LIBIEEE + /* Defined for Solaris 2.6 bug in pthread header. */ + #undef HAVE_PTHREAD_DESTRUCTOR + + #ifdef __CYGWIN__ #ifdef USE_DL_IMPORT From loewis@users.sourceforge.net Fri Oct 4 11:16:29 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Fri, 04 Oct 2002 03:16:29 -0700 Subject: [Python-checkins] python/dist/src/Python thread_pthread.h,2.36.8.1,2.36.8.2 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv28942/Python Modified Files: Tag: release22-maint thread_pthread.h Log Message: Patch #618347: Work around Solaris pthread.h bug. Index: thread_pthread.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/thread_pthread.h,v retrieving revision 2.36.8.1 retrieving revision 2.36.8.2 diff -C2 -d -r2.36.8.1 -r2.36.8.2 *** thread_pthread.h 23 Feb 2002 08:43:03 -0000 2.36.8.1 --- thread_pthread.h 4 Oct 2002 10:16:27 -0000 2.36.8.2 *************** *** 4,12 **** #include #include ! #ifdef __APPLE__ #define destructor xxdestructor #endif #include ! #ifdef __APPLE__ #undef destructor #endif --- 4,12 ---- #include #include ! #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) #define destructor xxdestructor #endif #include ! #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) #undef destructor #endif From loewis@users.sourceforge.net Fri Oct 4 11:22:04 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Fri, 04 Oct 2002 03:22:04 -0700 Subject: [Python-checkins] python/dist/src configure,1.339,1.340 configure.in,1.350,1.351 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv29982 Modified Files: configure configure.in Log Message: Disable LFS if Solaris/gcc bug is detected. Fixes #618095. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.339 retrieving revision 1.340 diff -C2 -d -r1.339 -r1.340 *** configure 4 Oct 2002 07:21:21 -0000 1.339 --- configure 4 Oct 2002 10:21:59 -0000 1.340 *************** *** 1,4 **** #! /bin/sh ! # From configure.in Revision: 1.349 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. --- 1,4 ---- #! /bin/sh ! # From configure.in Revision: 1.350 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. *************** *** 4424,4427 **** --- 4424,4485 ---- fi + # Enabling LFS on Solaris (2.6 to 9) with gcc 2.95 triggers a bug in + # the system headers: If _XOPEN_SOURCE and _LARGEFILE_SOURCE are + # defined, but the compiler does not support pragma redefine_extname, + # and _LARGEFILE64_SOURCE is not defined, the headers refer to 64-bit + # structures (such as rlimit64) without declaring them. As a + # work-around, disable LFS on such configurations + + use_lfs=yes + echo "$as_me:$LINENO: checking Solaris LFS bug" >&5 + echo $ECHO_N "checking Solaris LFS bug... $ECHO_C" >&6 + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" + #include "confdefs.h" + + #define _LARGEFILE_SOURCE 1 + #define _FILE_OFFSET_BITS 64 + #include + + #ifdef F77_DUMMY_MAIN + # ifdef __cplusplus + extern "C" + # endif + int F77_DUMMY_MAIN() { return 1; } + #endif + int + main () + { + struct rlimit foo; + ; + return 0; + } + _ACEOF + rm -f conftest.$ac_objext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + sol_lfs_bug=no + else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + sol_lfs_bug=yes + fi + rm -f conftest.$ac_objext conftest.$ac_ext + echo "$as_me:$LINENO: result: $sol_lfs_bug" >&5 + echo "${ECHO_T}$sol_lfs_bug" >&6 + if test "$sol_lfs_bug" = "yes"; then + use_lfs=no + fi + + if test "$use_lfs" = "yes"; then # Two defines needed to enable largefile support on various platforms # These may affect some typedefs *************** *** 4436,4439 **** --- 4494,4498 ---- _ACEOF + fi # Add some code to confdefs.h so that the test for off_t works on SCO Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.350 retrieving revision 1.351 diff -C2 -d -r1.350 -r1.351 *** configure.in 4 Oct 2002 07:21:24 -0000 1.350 --- configure.in 4 Oct 2002 10:22:02 -0000 1.351 *************** *** 655,658 **** --- 655,678 ---- fi + # Enabling LFS on Solaris (2.6 to 9) with gcc 2.95 triggers a bug in + # the system headers: If _XOPEN_SOURCE and _LARGEFILE_SOURCE are + # defined, but the compiler does not support pragma redefine_extname, + # and _LARGEFILE64_SOURCE is not defined, the headers refer to 64-bit + # structures (such as rlimit64) without declaring them. As a + # work-around, disable LFS on such configurations + + use_lfs=yes + AC_MSG_CHECKING(Solaris LFS bug) + AC_TRY_COMPILE([ + #define _LARGEFILE_SOURCE 1 + #define _FILE_OFFSET_BITS 64 + #include + ],struct rlimit foo;,sol_lfs_bug=no,sol_lfs_bug=yes) + AC_MSG_RESULT($sol_lfs_bug) + if test "$sol_lfs_bug" = "yes"; then + use_lfs=no + fi + + if test "$use_lfs" = "yes"; then # Two defines needed to enable largefile support on various platforms # These may affect some typedefs *************** *** 661,664 **** --- 681,685 ---- AC_DEFINE(_FILE_OFFSET_BITS, 64, [This must be set to 64 on some systems to enable large file support.]) + fi # Add some code to confdefs.h so that the test for off_t works on SCO From lemburg@users.sourceforge.net Fri Oct 4 12:45:40 2002 From: lemburg@users.sourceforge.net (lemburg@users.sourceforge.net) Date: Fri, 04 Oct 2002 04:45:40 -0700 Subject: [Python-checkins] python/dist/src/Lib/encodings __init__.py,1.11,1.12 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/encodings In directory usw-pr-cvs1:/tmp/cvs-serv20044/Lib/encodings Modified Files: __init__.py Log Message: Extending the encoding name normalization to handle more non-alphanumeric characters. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/encodings/__init__.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** __init__.py 8 Aug 2002 20:19:18 -0000 1.11 --- __init__.py 4 Oct 2002 11:45:38 -0000 1.12 *************** *** 4,10 **** directory. ! Codec modules must have names corresponding to standard lower-case ! encoding names with hyphens mapped to underscores, e.g. 'utf-8' is ! implemented by the module 'utf_8.py'. Each codec module must export the following interface: --- 4,10 ---- directory. ! Codec modules must have names corresponding to normalized encoding ! names as defined in the normalize_encoding() function below, e.g. ! 'utf-8' must be implemented by the module 'utf_8.py'. Each codec module must export the following interface: *************** *** 19,25 **** * getaliases() -> sequence of encoding name strings to use as aliases ! Alias names returned by getaliases() must be standard encoding ! names as defined above (lower-case, hyphens converted to ! underscores). Written by Marc-Andre Lemburg (mal@lemburg.com). --- 19,24 ---- * getaliases() -> sequence of encoding name strings to use as aliases ! Alias names returned by getaliases() must be normalized encoding ! names as defined by normalize_encoding(). Written by Marc-Andre Lemburg (mal@lemburg.com). *************** *** 29,37 **** """#" ! import codecs,exceptions _cache = {} _unknown = '--unknown--' _import_tail = ['*'] class CodecRegistryError(exceptions.LookupError, --- 28,37 ---- """#" ! import codecs, exceptions, re _cache = {} _unknown = '--unknown--' _import_tail = ['*'] + _norm_encoding_RE = re.compile('[^a-zA-Z0-9.]') class CodecRegistryError(exceptions.LookupError, *************** *** 39,42 **** --- 39,54 ---- pass + def normalize_encoding(encoding): + + """ Normalize an encoding name. + + Normalization works as follows: all non-alphanumeric + characters except the dot used for Python package names are + collapsed and replaced with a single underscore, e.g. ' -;#' + becomes '_'. + + """ + return '_'.join(_norm_encoding_RE.split(encoding)) + def search_function(encoding): *************** *** 52,56 **** # default import module lookup scheme with the alias name. # ! modname = encoding.replace('-', '_') try: mod = __import__('encodings.' + modname, --- 64,68 ---- # default import module lookup scheme with the alias name. # ! modname = normalize_encoding(encoding) try: mod = __import__('encodings.' + modname, From lemburg@users.sourceforge.net Fri Oct 4 12:51:41 2002 From: lemburg@users.sourceforge.net (lemburg@users.sourceforge.net) Date: Fri, 04 Oct 2002 04:51:41 -0700 Subject: [Python-checkins] python/dist/src/Lib/encodings aliases.py,1.15,1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/encodings In directory usw-pr-cvs1:/tmp/cvs-serv22095/Lib/encodings Modified Files: aliases.py Log Message: Adapt lookup names to new more general encoding name normalization scheme. Index: aliases.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/encodings/aliases.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** aliases.py 26 Sep 2002 20:08:23 -0000 1.15 --- aliases.py 4 Oct 2002 11:51:39 -0000 1.16 *************** *** 33,37 **** 'ibm367' : 'ascii', 'iso646_us' : 'ascii', ! 'iso_646.irv:1991' : 'ascii', 'iso_ir_6' : 'ascii', 'us' : 'ascii', --- 33,37 ---- 'ibm367' : 'ascii', 'iso646_us' : 'ascii', ! 'iso_646.irv_1991' : 'ascii', 'iso_ir_6' : 'ascii', 'us' : 'ascii', *************** *** 172,176 **** 'csisolatin6' : 'iso8859_10', 'iso_8859_10' : 'iso8859_10', ! 'iso_8859_10:1992' : 'iso8859_10', 'iso_ir_157' : 'iso8859_10', 'l6' : 'iso8859_10', --- 172,176 ---- 'csisolatin6' : 'iso8859_10', 'iso_8859_10' : 'iso8859_10', ! 'iso_8859_10_1992' : 'iso8859_10', 'iso_ir_157' : 'iso8859_10', 'l6' : 'iso8859_10', *************** *** 182,186 **** # iso8859_14 codec 'iso_8859_14' : 'iso8859_14', ! 'iso_8859_14:1998' : 'iso8859_14', 'iso_celtic' : 'iso8859_14', 'iso_ir_199' : 'iso8859_14', --- 182,186 ---- # iso8859_14 codec 'iso_8859_14' : 'iso8859_14', ! 'iso_8859_14_1998' : 'iso8859_14', 'iso_celtic' : 'iso8859_14', 'iso_ir_199' : 'iso8859_14', *************** *** 194,198 **** 'csisolatin2' : 'iso8859_2', 'iso_8859_2' : 'iso8859_2', ! 'iso_8859_2:1987' : 'iso8859_2', 'iso_ir_101' : 'iso8859_2', 'l2' : 'iso8859_2', --- 194,198 ---- 'csisolatin2' : 'iso8859_2', 'iso_8859_2' : 'iso8859_2', ! 'iso_8859_2_1987' : 'iso8859_2', 'iso_ir_101' : 'iso8859_2', 'l2' : 'iso8859_2', *************** *** 202,206 **** 'csisolatin3' : 'iso8859_3', 'iso_8859_3' : 'iso8859_3', ! 'iso_8859_3:1988' : 'iso8859_3', 'iso_ir_109' : 'iso8859_3', 'l3' : 'iso8859_3', --- 202,206 ---- 'csisolatin3' : 'iso8859_3', 'iso_8859_3' : 'iso8859_3', ! 'iso_8859_3_1988' : 'iso8859_3', 'iso_ir_109' : 'iso8859_3', 'l3' : 'iso8859_3', *************** *** 210,214 **** 'csisolatin4' : 'iso8859_4', 'iso_8859_4' : 'iso8859_4', ! 'iso_8859_4:1988' : 'iso8859_4', 'iso_ir_110' : 'iso8859_4', 'l4' : 'iso8859_4', --- 210,214 ---- 'csisolatin4' : 'iso8859_4', 'iso_8859_4' : 'iso8859_4', ! 'iso_8859_4_1988' : 'iso8859_4', 'iso_ir_110' : 'iso8859_4', 'l4' : 'iso8859_4', *************** *** 219,223 **** 'cyrillic' : 'iso8859_5', 'iso_8859_5' : 'iso8859_5', ! 'iso_8859_5:1988' : 'iso8859_5', 'iso_ir_144' : 'iso8859_5', --- 219,223 ---- 'cyrillic' : 'iso8859_5', 'iso_8859_5' : 'iso8859_5', ! 'iso_8859_5_1988' : 'iso8859_5', 'iso_ir_144' : 'iso8859_5', *************** *** 228,232 **** 'ecma_114' : 'iso8859_6', 'iso_8859_6' : 'iso8859_6', ! 'iso_8859_6:1987' : 'iso8859_6', 'iso_ir_127' : 'iso8859_6', --- 228,232 ---- 'ecma_114' : 'iso8859_6', 'iso_8859_6' : 'iso8859_6', ! 'iso_8859_6_1987' : 'iso8859_6', 'iso_ir_127' : 'iso8859_6', *************** *** 238,242 **** 'greek8' : 'iso8859_7', 'iso_8859_7' : 'iso8859_7', ! 'iso_8859_7:1987' : 'iso8859_7', 'iso_ir_126' : 'iso8859_7', --- 238,242 ---- 'greek8' : 'iso8859_7', 'iso_8859_7' : 'iso8859_7', ! 'iso_8859_7_1987' : 'iso8859_7', 'iso_ir_126' : 'iso8859_7', *************** *** 245,249 **** 'hebrew' : 'iso8859_8', 'iso_8859_8' : 'iso8859_8', ! 'iso_8859_8:1988' : 'iso8859_8', 'iso_ir_138' : 'iso8859_8', --- 245,249 ---- 'hebrew' : 'iso8859_8', 'iso_8859_8' : 'iso8859_8', ! 'iso_8859_8_1988' : 'iso8859_8', 'iso_ir_138' : 'iso8859_8', *************** *** 251,255 **** 'csisolatin5' : 'iso8859_9', 'iso_8859_9' : 'iso8859_9', ! 'iso_8859_9:1989' : 'iso8859_9', 'iso_ir_148' : 'iso8859_9', 'l5' : 'iso8859_9', --- 251,255 ---- 'csisolatin5' : 'iso8859_9', 'iso_8859_9' : 'iso8859_9', ! 'iso_8859_9_1989' : 'iso8859_9', 'iso_ir_148' : 'iso8859_9', 'l5' : 'iso8859_9', *************** *** 270,274 **** 'iso8859' : 'latin_1', 'iso_8859_1' : 'latin_1', ! 'iso_8859_1:1987' : 'latin_1', 'iso_ir_100' : 'latin_1', 'l1' : 'latin_1', --- 270,274 ---- 'iso8859' : 'latin_1', 'iso_8859_1' : 'latin_1', ! 'iso_8859_1_1987' : 'latin_1', 'iso_ir_100' : 'latin_1', 'l1' : 'latin_1', *************** *** 329,334 **** 'utf' : 'utf_8', 'utf8' : 'utf_8', ! 'utf8@ucs2' : 'utf_8', ! 'utf8@ucs4' : 'utf_8', # uu_codec codec --- 329,334 ---- 'utf' : 'utf_8', 'utf8' : 'utf_8', ! 'utf8_ucs2' : 'utf_8', ! 'utf8_ucs4' : 'utf_8', # uu_codec codec From lemburg@users.sourceforge.net Fri Oct 4 12:55:24 2002 From: lemburg@users.sourceforge.net (lemburg@users.sourceforge.net) Date: Fri, 04 Oct 2002 04:55:24 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.491,1.492 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv23167/Misc Modified Files: NEWS Log Message: News item about the new encoding normalization scheme. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.491 retrieving revision 1.492 diff -C2 -d -r1.491 -r1.492 *** NEWS 1 Oct 2002 18:18:58 -0000 1.491 --- NEWS 4 Oct 2002 11:55:21 -0000 1.492 *************** *** 341,344 **** --- 341,350 ---- ------- + - Encoding name normalization was generalized to not only + replace hyphens with underscores, but also all other non-alphanumeric + characters (with the exception of the dot which is used for Python + package names during lookup). The aliases.py mapping was updated + to the new standard. + - mimetypes has two new functions: guess_all_extensions() which returns a list of all known extensions for a mime type, and From lemburg@users.sourceforge.net Fri Oct 4 12:58:27 2002 From: lemburg@users.sourceforge.net (lemburg@users.sourceforge.net) Date: Fri, 04 Oct 2002 04:58:27 -0700 Subject: [Python-checkins] python/dist/src/Lib/encodings aliases.py,1.16,1.17 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/encodings In directory usw-pr-cvs1:/tmp/cvs-serv23918/Lib/encodings Modified Files: aliases.py Log Message: Fix doc-string. Index: aliases.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/encodings/aliases.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** aliases.py 4 Oct 2002 11:51:39 -0000 1.16 --- aliases.py 4 Oct 2002 11:58:24 -0000 1.17 *************** *** 4,10 **** map encodings names to module names. ! Note that the search function converts the encoding names to lower ! case and replaces hyphens with underscores *before* performing the ! lookup. Contents: --- 4,10 ---- map encodings names to module names. ! Note that the search function normalizes the encoding names before ! doing the lookup, so the mapping will have to map normalized ! encoding names to module names. Contents: From nnorwitz@users.sourceforge.net Fri Oct 4 13:35:19 2002 From: nnorwitz@users.sourceforge.net (nnorwitz@users.sourceforge.net) Date: Fri, 04 Oct 2002 05:35:19 -0700 Subject: [Python-checkins] python/dist/src/Include cStringIO.h,2.15,2.15.18.1 descrobject.h,2.8,2.8.8.1 iterobject.h,1.3,1.3.20.1 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv3044/Include Modified Files: Tag: release22-maint cStringIO.h descrobject.h iterobject.h Log Message: Backport patch (also pointed out in SF #607253): date: 2002/03/30 08:57:12; author: loewis; Patch #536908: Add missing #include guards/extern "C". Index: cStringIO.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/cStringIO.h,v retrieving revision 2.15 retrieving revision 2.15.18.1 diff -C2 -d -r2.15 -r2.15.18.1 *** cStringIO.h 9 Jun 2001 07:59:43 -0000 2.15 --- cStringIO.h 4 Oct 2002 12:35:17 -0000 2.15.18.1 *************** *** 1,4 **** --- 1,7 ---- #ifndef CSTRINGIO_INCLUDED #define CSTRINGIO_INCLUDED + #ifdef __cplusplus + extern "C" { + #endif /* *************** *** 129,131 **** --- 132,137 ---- PycStringIO=(struct PycStringIO_CAPI*)xxxPyCObject_Import("cStringIO", "cStringIO_CAPI") + #ifdef __cplusplus + } + #endif #endif /* CSTRINGIO_INCLUDED */ Index: descrobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/descrobject.h,v retrieving revision 2.8 retrieving revision 2.8.8.1 diff -C2 -d -r2.8 -r2.8.8.1 *** descrobject.h 22 Oct 2001 00:43:43 -0000 2.8 --- descrobject.h 4 Oct 2002 12:35:17 -0000 2.8.8.1 *************** *** 1,3 **** --- 1,8 ---- /* Descriptors */ + #ifndef Py_DESCROBJECT_H + #define Py_DESCROBJECT_H + #ifdef __cplusplus + extern "C" { + #endif typedef PyObject *(*getter)(PyObject *, void *); *************** *** 79,80 **** --- 84,90 ---- extern DL_IMPORT(PyTypeObject) PyProperty_Type; + #ifdef __cplusplus + } + #endif + #endif /* !Py_DESCROBJECT_H */ + Index: iterobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/iterobject.h,v retrieving revision 1.3 retrieving revision 1.3.20.1 diff -C2 -d -r1.3 -r1.3.20.1 *** iterobject.h 23 Apr 2001 14:08:49 -0000 1.3 --- iterobject.h 4 Oct 2002 12:35:17 -0000 1.3.20.1 *************** *** 1,3 **** --- 1,8 ---- + #ifndef Py_ITEROBJECT_H + #define Py_ITEROBJECT_H /* Iterators (the basic kind, over a sequence) */ + #ifdef __cplusplus + extern "C" { + #endif extern DL_IMPORT(PyTypeObject) PySeqIter_Type; *************** *** 12,13 **** --- 17,23 ---- extern DL_IMPORT(PyObject *) PyCallIter_New(PyObject *, PyObject *); + #ifdef __cplusplus + } + #endif + #endif /* !Py_ITEROBJECT_H */ + From nnorwitz@users.sourceforge.net Fri Oct 4 13:43:05 2002 From: nnorwitz@users.sourceforge.net (nnorwitz@users.sourceforge.net) Date: Fri, 04 Oct 2002 05:43:05 -0700 Subject: [Python-checkins] python/dist/src/Include complexobject.h,2.10,2.11 cStringIO.h,2.18,2.19 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv5162/Include Modified Files: complexobject.h cStringIO.h Log Message: SF # 607253, header file problems by Ralf W. Grosse-Kunstleve Don't pollute the namespace when protecting against multiple header inclusion. Prefix with Py_ and use standard naming convention Py_FILENAME_H. Index: complexobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/complexobject.h,v retrieving revision 2.10 retrieving revision 2.11 diff -C2 -d -r2.10 -r2.11 *** complexobject.h 12 Aug 2002 07:21:56 -0000 2.10 --- complexobject.h 4 Oct 2002 12:43:02 -0000 2.11 *************** *** 1,6 **** /* Complex number structure */ ! #ifndef COMPLEXOBJECT_H ! #define COMPLEXOBJECT_H #ifdef __cplusplus extern "C" { --- 1,6 ---- /* Complex number structure */ ! #ifndef Py_COMPLEXOBJECT_H ! #define Py_COMPLEXOBJECT_H #ifdef __cplusplus extern "C" { *************** *** 56,58 **** } #endif ! #endif /* !COMPLEXOBJECT_H */ --- 56,58 ---- } #endif ! #endif /* !Py_COMPLEXOBJECT_H */ Index: cStringIO.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/cStringIO.h,v retrieving revision 2.18 retrieving revision 2.19 diff -C2 -d -r2.18 -r2.19 *** cStringIO.h 5 Aug 2002 18:20:01 -0000 2.18 --- cStringIO.h 4 Oct 2002 12:43:02 -0000 2.19 *************** *** 1,4 **** ! #ifndef CSTRINGIO_INCLUDED ! #define CSTRINGIO_INCLUDED #ifdef __cplusplus extern "C" { --- 1,4 ---- ! #ifndef Py_CSTRINGIO_H ! #define Py_CSTRINGIO_H #ifdef __cplusplus extern "C" { *************** *** 61,63 **** } #endif ! #endif /* CSTRINGIO_INCLUDED */ --- 61,63 ---- } #endif ! #endif /* !Py_CSTRINGIO_H */ From nnorwitz@users.sourceforge.net Fri Oct 4 13:50:14 2002 From: nnorwitz@users.sourceforge.net (nnorwitz@users.sourceforge.net) Date: Fri, 04 Oct 2002 05:50:14 -0700 Subject: [Python-checkins] python/dist/src/Include complexobject.h,2.9,2.9.12.1 cStringIO.h,2.15.18.1,2.15.18.2 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv7686/Include Modified Files: Tag: release22-maint complexobject.h cStringIO.h Log Message: Backport last checkin: SF # 607253, header file problems, reported by Ralf W. Grosse-Kunstleve Don't pollute the namespace when protecting against multiple header inclusion. Prefix with Py_ and use standard naming convention Py_FILENAME_H. Index: complexobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/complexobject.h,v retrieving revision 2.9 retrieving revision 2.9.12.1 diff -C2 -d -r2.9 -r2.9.12.1 *** complexobject.h 12 Sep 2001 19:12:48 -0000 2.9 --- complexobject.h 4 Oct 2002 12:50:11 -0000 2.9.12.1 *************** *** 1,6 **** /* Complex number structure */ ! #ifndef COMPLEXOBJECT_H ! #define COMPLEXOBJECT_H #ifdef __cplusplus extern "C" { --- 1,6 ---- /* Complex number structure */ ! #ifndef Py_COMPLEXOBJECT_H ! #define Py_COMPLEXOBJECT_H #ifdef __cplusplus extern "C" { *************** *** 56,58 **** } #endif ! #endif /* !COMPLEXOBJECT_H */ --- 56,58 ---- } #endif ! #endif /* !Py_COMPLEXOBJECT_H */ Index: cStringIO.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/cStringIO.h,v retrieving revision 2.15.18.1 retrieving revision 2.15.18.2 diff -C2 -d -r2.15.18.1 -r2.15.18.2 *** cStringIO.h 4 Oct 2002 12:35:17 -0000 2.15.18.1 --- cStringIO.h 4 Oct 2002 12:50:12 -0000 2.15.18.2 *************** *** 1,4 **** ! #ifndef CSTRINGIO_INCLUDED ! #define CSTRINGIO_INCLUDED #ifdef __cplusplus extern "C" { --- 1,4 ---- ! #ifndef Py_CSTRINGIO_H ! #define Py_CSTRINGIO_H #ifdef __cplusplus extern "C" { *************** *** 135,137 **** } #endif ! #endif /* CSTRINGIO_INCLUDED */ --- 135,137 ---- } #endif ! #endif /* !Py_CSTRINGIO_H */ From lemburg@users.sourceforge.net Fri Oct 4 16:57:05 2002 From: lemburg@users.sourceforge.net (lemburg@users.sourceforge.net) Date: Fri, 04 Oct 2002 08:57:05 -0700 Subject: [Python-checkins] python/dist/src/Lib/encodings aliases.py,1.17,1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/encodings In directory usw-pr-cvs1:/tmp/cvs-serv8657/Lib/encodings Modified Files: aliases.py Log Message: Remove unneeded alias. Index: aliases.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/encodings/aliases.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** aliases.py 4 Oct 2002 11:58:24 -0000 1.17 --- aliases.py 4 Oct 2002 15:57:03 -0000 1.18 *************** *** 28,32 **** 'ansi_x3.4_1968' : 'ascii', 'ansi_x3.4_1986' : 'ascii', - 'ansi_x3_4_1968' : 'ascii', 'cp367' : 'ascii', 'csascii' : 'ascii', --- 28,31 ---- From lemburg@users.sourceforge.net Fri Oct 4 17:31:00 2002 From: lemburg@users.sourceforge.net (lemburg@users.sourceforge.net) Date: Fri, 04 Oct 2002 09:31:00 -0700 Subject: [Python-checkins] python/dist/src/Lib/encodings aliases.py,1.18,1.19 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/encodings In directory usw-pr-cvs1:/tmp/cvs-serv21695/Lib/encodings Modified Files: aliases.py Log Message: Undo the removal. Guido mentioned that the encoding name is in active by some email headers. Index: aliases.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/encodings/aliases.py,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** aliases.py 4 Oct 2002 15:57:03 -0000 1.18 --- aliases.py 4 Oct 2002 16:30:42 -0000 1.19 *************** *** 27,30 **** --- 27,31 ---- '646' : 'ascii', 'ansi_x3.4_1968' : 'ascii', + 'ansi_x3_4_1968' : 'ascii', # some email headers use this non-standard name 'ansi_x3.4_1986' : 'ascii', 'cp367' : 'ascii', From barry@users.sourceforge.net Fri Oct 4 18:24:26 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Fri, 04 Oct 2002 10:24:26 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_email_codecs.py,NONE,1.5.2.1 regrtest.py,1.70.4.2,1.70.4.3 test_email.py,1.24.4.2,1.24.4.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv11766/Lib/test Modified Files: Tag: release22-maint regrtest.py test_email.py Added Files: Tag: release22-maint test_email_codecs.py Log Message: Backporting of email 2.4 from Python 2.3. Many newly added modules, some updated modules, updated documentation, and updated tests. Note that Lib/test/regrtest.py added test_email_codecs to the expected skips for all platforms. Also note that test_email_codecs.py differs slightly from its Python 2.3 counterpart due to the difference in package location for TestSkipped. --- NEW FILE: test_email_codecs.py --- # Copyright (C) 2002 Python Software Foundation # email package unit tests for (optional) Asian codecs import unittest # The specific tests now live in Lib/email/test from email.test.test_email_codecs import suite if __name__ == '__main__': unittest.main(defaultTest='suite') Index: regrtest.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/regrtest.py,v retrieving revision 1.70.4.2 retrieving revision 1.70.4.3 diff -C2 -d -r1.70.4.2 -r1.70.4.3 *** regrtest.py 30 Sep 2002 16:16:12 -0000 1.70.4.2 --- regrtest.py 4 Oct 2002 17:24:24 -0000 1.70.4.3 *************** *** 485,488 **** --- 485,489 ---- test_dbm test_dl + test_email_codecs test_fcntl test_fork1 *************** *** 512,515 **** --- 513,517 ---- test_curses test_dl + test_email_codecs test_gl test_imgfile *************** *** 535,538 **** --- 537,541 ---- test_dbm test_dl + test_email_codecs test_fcntl test_fork1 *************** *** 568,571 **** --- 571,575 ---- test_cl test_dl + test_email_codecs test_gl test_imgfile *************** *** 592,595 **** --- 596,600 ---- test_cl test_dl + test_email_codecs test_gl test_imgfile *************** *** 617,620 **** --- 622,626 ---- test_cl test_dl + test_email_codecs test_fork1 test_gettext *************** *** 653,656 **** --- 659,663 ---- test_dbm test_dl + test_email_codecs test_fcntl test_fork1 *************** *** 691,694 **** --- 698,702 ---- test_curses test_dl + test_email_codecs test_gdbm test_gl Index: test_email.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_email.py,v retrieving revision 1.24.4.2 retrieving revision 1.24.4.3 diff -C2 -d -r1.24.4.2 -r1.24.4.3 *** test_email.py 22 Mar 2002 16:19:30 -0000 1.24.4.2 --- test_email.py 4 Oct 2002 17:24:24 -0000 1.24.4.3 *************** *** 2,1132 **** # email package unit tests - import os - import time import unittest ! import base64 ! from cStringIO import StringIO ! from types import StringType ! ! import email [...1112 lines suppressed...] - def test_main(): - from test_support import run_suite - run_suite(suite()) - if __name__ == '__main__': ! test_main() --- 2,11 ---- # email package unit tests import unittest ! # The specific tests now live in Lib/email/test ! from email.test.test_email import suite if __name__ == '__main__': ! unittest.main(defaultTest='suite') From barry@users.sourceforge.net Fri Oct 4 18:24:26 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Fri, 04 Oct 2002 10:24:26 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib email-dir.py,NONE,1.1.2.1 email-mime.py,NONE,1.1.2.1 email-simple.py,NONE,1.1.2.1 email-unpack.py,NONE,1.1.2.1 emailcharsets.tex,NONE,1.1.2.1 emailheaders.tex,NONE,1.2.2.1 emailmimebase.tex,NONE,1.2.2.1 email.tex,1.9.6.2,1.9.6.3 emailencoders.tex,1.2,1.2.12.1 emailexc.tex,1.2,1.2.12.1 emailgenerator.tex,1.3,1.3.8.1 emailiter.tex,1.2,1.2.12.1 emailmessage.tex,1.4,1.4.8.1 emailparser.tex,1.4.10.1,1.4.10.2 emailutil.tex,1.5.8.1,1.5.8.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv11766/Doc/lib Modified Files: Tag: release22-maint email.tex emailencoders.tex emailexc.tex emailgenerator.tex emailiter.tex emailmessage.tex emailparser.tex emailutil.tex Added Files: Tag: release22-maint email-dir.py email-mime.py email-simple.py email-unpack.py emailcharsets.tex emailheaders.tex emailmimebase.tex Log Message: Backporting of email 2.4 from Python 2.3. Many newly added modules, some updated modules, updated documentation, and updated tests. Note that Lib/test/regrtest.py added test_email_codecs to the expected skips for all platforms. Also note that test_email_codecs.py differs slightly from its Python 2.3 counterpart due to the difference in package location for TestSkipped. --- NEW FILE: email-dir.py --- #!/usr/bin/env python """Send the contents of a directory as a MIME message. Usage: dirmail [options] from to [to ...]* Options: -h / --help Print this message and exit. -d directory --directory=directory Mail the contents of the specified directory, otherwise use the current directory. Only the regular files in the directory are sent, and we don't recurse to subdirectories. `from' is the email address of the sender of the message. `to' is the email address of the recipient of the message, and multiple recipients may be given. The email is sent by forwarding to your local SMTP server, which then does the normal delivery process. Your local machine must be running an SMTP server. """ import sys import os import getopt import smtplib # For guessing MIME type based on file name extension import mimetypes from email import Encoders from email.Message import Message from email.MIMEAudio import MIMEAudio from email.MIMEMultipart import MIMEMultipart from email.MIMEImage import MIMEImage from email.MIMEText import MIMEText COMMASPACE = ', ' def usage(code, msg=''): print >> sys.stderr, __doc__ if msg: print >> sys.stderr, msg sys.exit(code) def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) except getopt.error, msg: usage(1, msg) dir = os.curdir for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-d', '--directory'): dir = arg if len(args) < 2: usage(1) sender = args[0] recips = args[1:] # Create the enclosing (outer) message outer = MIMEMultipart() outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) outer['To'] = COMMASPACE.join(recips) outer['From'] = sender outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' # To guarantee the message ends with a newline outer.epilogue = '' for filename in os.listdir(dir): path = os.path.join(dir, filename) if not os.path.isfile(path): continue # Guess the content type based on the file's extension. Encoding # will be ignored, although we should check for simple things like # gzip'd or compressed files. ctype, encoding = mimetypes.guess_type(path) if ctype is None or encoding is not None: # No guess could be made, or the file is encoded (compressed), so # use a generic bag-of-bits type. ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) if maintype == 'text': fp = open(path) # Note: we should handle calculating the charset msg = MIMEText(fp.read(), _subtype=subtype) fp.close() elif maintype == 'image': fp = open(path, 'rb') msg = MIMEImage(fp.read(), _subtype=subtype) fp.close() elif maintype == 'audio': fp = open(path, 'rb') msg = MIMEAudio(fp.read(), _subtype=subtype) fp.close() else: fp = open(path, 'rb') msg = MIMEBase(maintype, subtype) msg.set_payload(fp.read()) fp.close() # Encode the payload using Base64 Encoders.encode_base64(msg) # Set the filename parameter msg.add_header('Content-Disposition', 'attachment', filename=filename) outer.attach(msg) # Now send the message s = smtplib.SMTP() s.connect() s.sendmail(sender, recips, outer.as_string()) s.close() if __name__ == '__main__': main() --- NEW FILE: email-mime.py --- # Import smtplib for the actual sending function import smtplib # Here are the email pacakge modules we'll need from email.MIMEImage import MIMEImage from email.MIMEMultipart import MIMEMultipart COMMASPACE = ', ' # Create the container (outer) email message. msg = MIMEMultipart() msg['Subject'] = 'Our family reunion' # me == the sender's email address # family = the list of all recipients' email addresses msg['From'] = me msg['To'] = COMMASPACE.join(family) msg.preamble = 'Our family reunion' # Guarantees the message ends in a newline msg.epilogue = '' # Assume we know that the image files are all in PNG format for file in pngfiles: # Open the files in binary mode. Let the MIMEImage class automatically # guess the specific image type. fp = open(file, 'rb') img = MIMEImage(fp.read()) fp.close() msg.attach(img) # Send the email via our own SMTP server. s = smtplib.SMTP() s.connect() s.sendmail(me, family, msg.as_string()) s.close() --- NEW FILE: email-simple.py --- # Import smtplib for the actual sending function import smtplib # Import the email modules we'll need from email.MIMEText import MIMEText # Open a plain text file for reading. For this example, assume that # the text file contains only ASCII characters. fp = open(textfile, 'rb') # Create a text/plain message msg = MIMEText(fp.read()) fp.close() # me == the sender's email address # you == the recipient's email address msg['Subject'] = 'The contents of %s' % textfile msg['From'] = me msg['To'] = you # Send the message via our own SMTP server, but don't include the # envelope header. s = smtplib.SMTP() s.connect() s.sendmail(me, [you], msg.as_string()) s.close() --- NEW FILE: email-unpack.py --- #!/usr/bin/env python """Unpack a MIME message into a directory of files. Usage: unpackmail [options] msgfile Options: -h / --help Print this message and exit. -d directory --directory=directory Unpack the MIME message into the named directory, which will be created if it doesn't already exist. msgfile is the path to the file containing the MIME message. """ import sys import os import getopt import errno import mimetypes import email def usage(code, msg=''): print >> sys.stderr, __doc__ if msg: print >> sys.stderr, msg sys.exit(code) def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) except getopt.error, msg: usage(1, msg) dir = os.curdir for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-d', '--directory'): dir = arg try: msgfile = args[0] except IndexError: usage(1) try: os.mkdir(dir) except OSError, e: # Ignore directory exists error if e.errno <> errno.EEXIST: raise fp = open(msgfile) msg = email.message_from_file(fp) fp.close() counter = 1 for part in msg.walk(): # multipart/* are just containers if part.get_content_maintype() == 'multipart': continue # Applications should really sanitize the given filename so that an # email message can't be used to overwrite important files filename = part.get_filename() if not filename: ext = mimetypes.guess_extension(part.get_type()) if not ext: # Use a generic bag-of-bits extension ext = '.bin' filename = 'part-%03d%s' % (counter, ext) counter += 1 fp = open(os.path.join(dir, filename), 'wb') fp.write(part.get_payload(decode=1)) fp.close() if __name__ == '__main__': main() --- NEW FILE: emailcharsets.tex --- \declaremodule{standard}{email.Charset} \modulesynopsis{Character Sets} This module provides a class \class{Charset} for representing character sets and character set conversions in email messages, as well as a character set registry and several convenience methods for manipulating this registry. Instances of \class{Charset} are used in several other modules within the \module{email} package. \versionadded{2.2.2} \begin{classdesc}{Charset}{\optional{input_charset}} Map character sets to their email properties. This class provides information about the requirements imposed on email for a specific character set. It also provides convenience routines for converting between character sets, given the availability of the applicable codecs. Given a character set, it will do its best to provide information on how to use that character set in an email message in an RFC-compliant way. Certain character sets must be encoded with quoted-printable or base64 when used in email headers or bodies. Certain character sets must be converted outright, and are not allowed in email. Optional \var{input_charset} is as described below. After being alias normalized it is also used as a lookup into the registry of character sets to find out the header encoding, body encoding, and output conversion codec to be used for the character set. For example, if \var{input_charset} is \code{iso-8859-1}, then headers and bodies will be encoded using quoted-printable and no output conversion codec is necessary. If \var{input_charset} is \code{euc-jp}, then headers will be encoded with base64, bodies will not be encoded, but output text will be converted from the \code{euc-jp} character set to the \code{iso-2022-jp} character set. \end{classdesc} \class{Charset} instances have the following data attributes: \begin{datadesc}{input_charset} The initial character set specified. Common aliases are converted to their \emph{official} email names (e.g. \code{latin_1} is converted to \code{iso-8859-1}). Defaults to 7-bit \code{us-ascii}. \end{datadesc} \begin{datadesc}{header_encoding} If the character set must be encoded before it can be used in an email header, this attribute will be set to \code{Charset.QP} (for quoted-printable), \code{Charset.BASE64} (for base64 encoding), or \code{Charset.SHORTEST} for the shortest of QP or BASE64 encoding. Otherwise, it will be \code{None}. \end{datadesc} \begin{datadesc}{body_encoding} Same as \var{header_encoding}, but describes the encoding for the mail message's body, which indeed may be different than the header encoding. \code{Charset.SHORTEST} is not allowed for \var{body_encoding}. \end{datadesc} \begin{datadesc}{output_charset} Some character sets must be converted before they can be used in email headers or bodies. If the \var{input_charset} is one of them, this attribute will contain the name of the character set output will be converted to. Otherwise, it will be \code{None}. \end{datadesc} \begin{datadesc}{input_codec} The name of the Python codec used to convert the \var{input_charset} to Unicode. If no conversion codec is necessary, this attribute will be \code{None}. \end{datadesc} \begin{datadesc}{output_codec} The name of the Python codec used to convert Unicode to the \var{output_charset}. If no conversion codec is necessary, this attribute will have the same value as the \var{input_codec}. \end{datadesc} \class{Charset} instances also have the following methods: \begin{methoddesc}[Charset]{get_body_encoding}{} Return the content transfer encoding used for body encoding. This is either the string \samp{quoted-printable} or \samp{base64} depending on the encoding used, or it is a function, in which case you should call the function with a single argument, the Message object being encoded. The function should then set the \mailheader{Content-Transfer-Encoding} header itself to whatever is appropriate. Returns the string \samp{quoted-printable} if \var{body_encoding} is \code{QP}, returns the string \samp{base64} if \var{body_encoding} is \code{BASE64}, and returns the string \samp{7bit} otherwise. \end{methoddesc} \begin{methoddesc}{convert}{s} Convert the string \var{s} from the \var{input_codec} to the \var{output_codec}. \end{methoddesc} \begin{methoddesc}{to_splittable}{s} Convert a possibly multibyte string to a safely splittable format. \var{s} is the string to split. Uses the \var{input_codec} to try and convert the string to Unicode, so it can be safely split on character boundaries (even for multibyte characters). Returns the string as-is if it isn't known how to convert \var{s} to Unicode with the \var{input_charset}. Characters that could not be converted to Unicode will be replaced with the Unicode replacement character \character{U+FFFD}. \end{methoddesc} \begin{methoddesc}{from_splittable}{ustr\optional{, to_output}} Convert a splittable string back into an encoded string. \var{ustr} is a Unicode string to ``unsplit''. This method uses the proper codec to try and convert the string from Unicode back into an encoded format. Return the string as-is if it is not Unicode, or if it could not be converted from Unicode. Characters that could not be converted from Unicode will be replaced with an appropriate character (usually \character{?}). If \var{to_output} is \code{True} (the default), uses \var{output_codec} to convert to an encoded format. If \var{to_output} is \code{False}, it uses \var{input_codec}. \end{methoddesc} \begin{methoddesc}{get_output_charset}{} Return the output character set. This is the \var{output_charset} attribute if that is not \code{None}, otherwise it is \var{input_charset}. \end{methoddesc} \begin{methoddesc}{encoded_header_len}{} Return the length of the encoded header string, properly calculating for quoted-printable or base64 encoding. \end{methoddesc} \begin{methoddesc}{header_encode}{s\optional{, convert}} Header-encode the string \var{s}. If \var{convert} is \code{True}, the string will be converted from the input charset to the output charset automatically. This is not useful for multibyte character sets, which have line length issues (multibyte characters must be split on a character, not a byte boundary); use the higher-level \class{Header} class to deal with these issues (see \refmodule{email.Header}). \var{convert} defaults to \code{False}. The type of encoding (base64 or quoted-printable) will be based on the \var{header_encoding} attribute. \end{methoddesc} \begin{methoddesc}{body_encode}{s\optional{, convert}} Body-encode the string \var{s}. If \var{convert} is \code{True} (the default), the string will be converted from the input charset to output charset automatically. Unlike \method{header_encode()}, there are no issues with byte boundaries and multibyte charsets in email bodies, so this is usually pretty safe. The type of encoding (base64 or quoted-printable) will be based on the \var{body_encoding} attribute. \end{methoddesc} The \class{Charset} class also provides a number of methods to support standard operations and built-in functions. \begin{methoddesc}[Charset]{__str__}{} Returns \var{input_charset} as a string coerced to lower case. \end{methoddesc} \begin{methoddesc}[Charset]{__eq__}{other} This method allows you to compare two \class{Charset} instances for equality. \end{methoddesc} \begin{methoddesc}[Header]{__ne__}{other} This method allows you to compare two \class{Charset} instances for inequality. \end{methoddesc} The \module{email.Charset} module also provides the following functions for adding new entries to the global character set, alias, and codec registries: \begin{funcdesc}{add_charset}{charset\optional{, header_enc\optional{, body_enc\optional{, output_charset}}}} Add character properties to the global registry. \var{charset} is the input character set, and must be the canonical name of a character set. Optional \var{header_enc} and \var{body_enc} is either \code{Charset.QP} for quoted-printable, \code{Charset.BASE64} for base64 encoding, \code{Charset.SHORTEST} for the shortest of quoted-printable or base64 encoding, or \code{None} for no encoding. \code{SHORTEST} is only valid for \var{header_enc}. The default is \code{None} for no encoding. Optional \var{output_charset} is the character set that the output should be in. Conversions will proceed from input charset, to Unicode, to the output charset when the method \method{Charset.convert()} is called. The default is to output in the same character set as the input. Both \var{input_charset} and \var{output_charset} must have Unicode codec entries in the module's character set-to-codec mapping; use \function{add_codec()} to add codecs the module does not know about. See the \refmodule{codecs} module's documentation for more information. The global character set registry is kept in the module global dictionary \code{CHARSETS}. \end{funcdesc} \begin{funcdesc}{add_alias}{alias, canonical} Add a character set alias. \var{alias} is the alias name, e.g. \code{latin-1}. \var{canonical} is the character set's canonical name, e.g. \code{iso-8859-1}. The global charset alias registry is kept in the module global dictionary \code{ALIASES}. \end{funcdesc} \begin{funcdesc}{add_codec}{charset, codecname} Add a codec that map characters in the given character set to and from Unicode. \var{charset} is the canonical name of a character set. \var{codecname} is the name of a Python codec, as appropriate for the second argument to the \function{unicode()} built-in, or to the \method{encode()} method of a Unicode string. \end{funcdesc} --- NEW FILE: emailheaders.tex --- \declaremodule{standard}{email.Header} \modulesynopsis{Representing non-ASCII headers} \rfc{2822} is the base standard that describes the format of email messages. It derives from the older \rfc{822} standard which came into widespread use at a time when most email was composed of \ASCII{} characters only. \rfc{2822} is a specification written assuming email contains only 7-bit \ASCII{} characters. Of course, as email has been deployed worldwide, it has become internationalized, such that language specific character sets can now be used in email messages. The base standard still requires email messages to be transfered using only 7-bit \ASCII{} characters, so a slew of RFCs have been written describing how to encode email containing non-\ASCII{} characters into \rfc{2822}-compliant format. These RFCs include \rfc{2045}, \rfc{2046}, \rfc{2047}, and \rfc{2231}. The \module{email} package supports these standards in its \module{email.Header} and \module{email.Charset} modules. If you want to include non-\ASCII{} characters in your email headers, say in the \mailheader{Subject} or \mailheader{To} fields, you should use the \class{Header} class and assign the field in the \class{Message} object to an instance of \class{Header} instead of using a string for the header value. For example: \begin{verbatim} >>> from email.Message import Message >>> from email.Header import Header >>> msg = Message() >>> h = Header('p\xf6stal', 'iso-8859-1') >>> msg['Subject'] = h >>> print msg.as_string() Subject: =?iso-8859-1?q?p=F6stal?= \end{verbatim} Notice here how we wanted the \mailheader{Subject} field to contain a non-\ASCII{} character? We did this by creating a \class{Header} instance and passing in the character set that the byte string was encoded in. When the subsequent \class{Message} instance was flattened, the \mailheader{Subject} field was properly \rfc{2047} encoded. MIME-aware mail readers would show this header using the embedded ISO-8859-1 character. \versionadded{2.2.2} Here is the \class{Header} class description: \begin{classdesc}{Header}{\optional{s\optional{, charset\optional{, maxlinelen\optional{, header_name\optional{, continuation_ws}}}}}} Create a MIME-compliant header that can contain strings in different character sets. Optional \var{s} is the initial header value. If \code{None} (the default), the initial header value is not set. You can later append to the header with \method{append()} method calls. \var{s} may be a byte string or a Unicode string, but see the \method{append()} documentation for semantics. Optional \var{charset} serves two purposes: it has the same meaning as the \var{charset} argument to the \method{append()} method. It also sets the default character set for all subsequent \method{append()} calls that omit the \var{charset} argument. If \var{charset} is not provided in the constructor (the default), the \code{us-ascii} character set is used both as \var{s}'s initial charset and as the default for subsequent \method{append()} calls. The maximum line length can be specified explicit via \var{maxlinelen}. For splitting the first line to a shorter value (to account for the field header which isn't included in \var{s}, e.g. \mailheader{Subject}) pass in the name of the field in \var{header_name}. The default \var{maxlinelen} is 76, and the default value for \var{header_name} is \code{None}, meaning it is not taken into account for the first line of a long, split header. Optional \var{continuation_ws} must be \rfc{2822}-compliant folding whitespace, and is usually either a space or a hard tab character. This character will be prepended to continuation lines. \end{classdesc} \begin{methoddesc}[Header]{append}{s\optional{, charset}} Append the string \var{s} to the MIME header. Optional \var{charset}, if given, should be a \class{Charset} instance (see \refmodule{email.Charset}) or the name of a character set, which will be converted to a \class{Charset} instance. A value of \code{None} (the default) means that the \var{charset} given in the constructor is used. \var{s} may be a byte string or a Unicode string. If it is a byte string (i.e. \code{isinstance(s, str)} is true), then \var{charset} is the encoding of that byte string, and a \exception{UnicodeError} will be raised if the string cannot be decoded with that character set. If \var{s} is a Unicode string, then \var{charset} is a hint specifying the character set of the characters in the string. In this case, when producing an \rfc{2822}-compliant header using \rfc{2047} rules, the Unicode string will be encoded using the following charsets in order: \code{us-ascii}, the \var{charset} hint, \code{utf-8}. The first character set to not provoke a \exception{UnicodeError} is used. \end{methoddesc} \begin{methoddesc}[Header]{encode}{} Encode a message header into an RFC-compliant format, possibly wrapping long lines and encapsulating non-\ASCII{} parts in base64 or quoted-printable encodings. \end{methoddesc} The \class{Header} class also provides a number of methods to support standard operators and built-in functions. \begin{methoddesc}[Header]{__str__}{} A synonym for \method{Header.encode()}. Useful for \code{str(aHeader)}. \end{methoddesc} \begin{methoddesc}[Header]{__unicode__}{} A helper for the built-in \function{unicode()} function. Returns the header as a Unicode string. \end{methoddesc} \begin{methoddesc}[Header]{__eq__}{other} This method allows you to compare two \class{Header} instances for equality. \end{methoddesc} \begin{methoddesc}[Header]{__ne__}{other} This method allows you to compare two \class{Header} instances for inequality. \end{methoddesc} The \module{email.Header} module also provides the following convenient functions. \begin{funcdesc}{decode_header}{header} Decode a message header value without converting the character set. The header value is in \var{header}. This function returns a list of \code{(decoded_string, charset)} pairs containing each of the decoded parts of the header. \var{charset} is \code{None} for non-encoded parts of the header, otherwise a lower case string containing the name of the character set specified in the encoded string. Here's an example: \begin{verbatim} >>> from email.Header import decode_header >>> decode_header('=?iso-8859-1?q?p=F6stal?=') [('p\\xf6stal', 'iso-8859-1')] \end{verbatim} \end{funcdesc} \begin{funcdesc}{make_header}{decoded_seq\optional{, maxlinelen\optional{, header_name\optional{, continuation_ws}}}} Create a \class{Header} instance from a sequence of pairs as returned by \function{decode_header()}. \function{decode_header()} takes a header value string and returns a sequence of pairs of the format \code{(decoded_string, charset)} where \var{charset} is the name of the character set. This function takes one of those sequence of pairs and returns a \class{Header} instance. Optional \var{maxlinelen}, \var{header_name}, and \var{continuation_ws} are as in the \class{Header} constructor. \end{funcdesc} --- NEW FILE: emailmimebase.tex --- Ordinarily, you get a message object structure by passing a file or some text to a parser, which parses the text and returns the root message object. However you can also build a complete message structure from scratch, or even individual \class{Message} objects by hand. In fact, you can also take an existing structure and add new \class{Message} objects, move them around, etc. This makes a very convenient interface for slicing-and-dicing MIME messages. You can create a new object structure by creating \class{Message} instances, adding attachments and all the appropriate headers manually. For MIME messages though, the \module{email} package provides some convenient subclasses to make things easier. Each of these classes should be imported from a module with the same name as the class, from within the \module{email} package. E.g.: \begin{verbatim} import email.MIMEImage.MIMEImage \end{verbatim} or \begin{verbatim} from email.MIMEText import MIMEText \end{verbatim} Here are the classes: \begin{classdesc}{MIMEBase}{_maintype, _subtype, **_params} This is the base class for all the MIME-specific subclasses of \class{Message}. Ordinarily you won't create instances specifically of \class{MIMEBase}, although you could. \class{MIMEBase} is provided primarily as a convenient base class for more specific MIME-aware subclasses. \var{_maintype} is the \mailheader{Content-Type} major type (e.g. \mimetype{text} or \mimetype{image}), and \var{_subtype} is the \mailheader{Content-Type} minor type (e.g. \mimetype{plain} or \mimetype{gif}). \var{_params} is a parameter key/value dictionary and is passed directly to \method{Message.add_header()}. The \class{MIMEBase} class always adds a \mailheader{Content-Type} header (based on \var{_maintype}, \var{_subtype}, and \var{_params}), and a \mailheader{MIME-Version} header (always set to \code{1.0}). \end{classdesc} \begin{classdesc}{MIMENonMultipart}{} A subclass of \class{MIMEBase}, this is an intermediate base class for MIME messages that are not \mimetype{multipart}. The primary purpose of this class is to prevent the use of the \method{attach()} method, which only makes sense for \mimetype{multipart} messages. If \method{attach()} is called, a \exception{MultipartConversionError} exception is raised. \versionadded{2.2.2} \end{classdesc} \begin{classdesc}{MIMEMultipart}{\optional{subtype\optional{, boundary\optional{, _subparts\optional{, _params}}}}} A subclass of \class{MIMEBase}, this is an intermediate base class for MIME messages that are \mimetype{multipart}. Optional \var{_subtype} defaults to \mimetype{mixed}, but can be used to specify the subtype of the message. A \mailheader{Content-Type} header of \mimetype{multipart/}\var{_subtype} will be added to the message object. A \mailheader{MIME-Version} header will also be added. Optional \var{boundary} is the multipart boundary string. When \code{None} (the default), the boundary is calculated when needed. \var{_subparts} is a sequence of initial subparts for the payload. It must be possible to convert this sequence to a list. You can always attach new subparts to the message by using the \method{Message.attach()} method. Additional parameters for the \mailheader{Content-Type} header are taken from the keyword arguments, or passed into the \var{_params} argument, which is a keyword dictionary. \versionadded{2.2.2} \end{classdesc} \begin{classdesc}{MIMEAudio}{_audiodata\optional{, _subtype\optional{, _encoder\optional{, **_params}}}} A subclass of \class{MIMENonMultipart}, the \class{MIMEAudio} class is used to create MIME message objects of major type \mimetype{audio}. \var{_audiodata} is a string containing the raw audio data. If this data can be decoded by the standard Python module \refmodule{sndhdr}, then the subtype will be automatically included in the \mailheader{Content-Type} header. Otherwise you can explicitly specify the audio subtype via the \var{_subtype} parameter. If the minor type could not be guessed and \var{_subtype} was not given, then \exception{TypeError} is raised. Optional \var{_encoder} is a callable (i.e. function) which will perform the actual encoding of the audio data for transport. This callable takes one argument, which is the \class{MIMEAudio} instance. It should use \method{get_payload()} and \method{set_payload()} to change the payload to encoded form. It should also add any \mailheader{Content-Transfer-Encoding} or other headers to the message object as necessary. The default encoding is base64. See the \refmodule{email.Encoders} module for a list of the built-in encoders. \var{_params} are passed straight through to the base class constructor. \end{classdesc} \begin{classdesc}{MIMEImage}{_imagedata\optional{, _subtype\optional{, _encoder\optional{, **_params}}}} A subclass of \class{MIMENonMultipart}, the \class{MIMEImage} class is used to create MIME message objects of major type \mimetype{image}. \var{_imagedata} is a string containing the raw image data. If this data can be decoded by the standard Python module \refmodule{imghdr}, then the subtype will be automatically included in the \mailheader{Content-Type} header. Otherwise you can explicitly specify the image subtype via the \var{_subtype} parameter. If the minor type could not be guessed and \var{_subtype} was not given, then \exception{TypeError} is raised. Optional \var{_encoder} is a callable (i.e. function) which will perform the actual encoding of the image data for transport. This callable takes one argument, which is the \class{MIMEImage} instance. It should use \method{get_payload()} and \method{set_payload()} to change the payload to encoded form. It should also add any \mailheader{Content-Transfer-Encoding} or other headers to the message object as necessary. The default encoding is base64. See the \refmodule{email.Encoders} module for a list of the built-in encoders. \var{_params} are passed straight through to the \class{MIMEBase} constructor. \end{classdesc} \begin{classdesc}{MIMEMessage}{_msg\optional{, _subtype}} A subclass of \class{MIMENonMultipart}, the \class{MIMEMessage} class is used to create MIME objects of main type \mimetype{message}. \var{_msg} is used as the payload, and must be an instance of class \class{Message} (or a subclass thereof), otherwise a \exception{TypeError} is raised. Optional \var{_subtype} sets the subtype of the message; it defaults to \mimetype{rfc822}. \end{classdesc} \begin{classdesc}{MIMEText}{_text\optional{, _subtype\optional{, _charset\optional{, _encoder}}}} A subclass of \class{MIMENonMultipart}, the \class{MIMEText} class is used to create MIME objects of major type \mimetype{text}. \var{_text} is the string for the payload. \var{_subtype} is the minor type and defaults to \mimetype{plain}. \var{_charset} is the character set of the text and is passed as a parameter to the \class{MIMENonMultipart} constructor; it defaults to \code{us-ascii}. No guessing or encoding is performed on the text data, but a newline is appended to \var{_text} if it doesn't already end with a newline. \deprecated{2.2.2}{The \var{_encoding} argument has been deprecated. Encoding now happens implicitly based on the \var{_charset} argument.} \end{classdesc} Index: email.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/email.tex,v retrieving revision 1.9.6.2 retrieving revision 1.9.6.3 diff -C2 -d -r1.9.6.2 -r1.9.6.3 *** email.tex 26 Jun 2002 07:52:41 -0000 1.9.6.2 --- email.tex 4 Oct 2002 17:24:23 -0000 1.9.6.3 *************** *** 1,3 **** ! % Copyright (C) 2001 Python Software Foundation % Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! % Copyright (C) 2001,2002 Python Software Foundation % Author: barry@zope.com (Barry Warsaw) *************** *** 20,30 **** \module{mimecntl}. It is specifically \emph{not} designed to do any sending of email messages to SMTP (\rfc{2821}) servers; that is the ! function of the \refmodule{smtplib} module\footnote{For this reason, ! line endings in the \module{email} package are always native line ! endings. The \module{smtplib} module is responsible for converting ! from native line endings to \rfc{2821} line endings, just as your mail ! server would be responsible for converting from \rfc{2821} line ! endings to native line endings when it stores messages in a local ! mailbox.}. The primary distinguishing feature of the \module{email} package is --- 20,27 ---- \module{mimecntl}. It is specifically \emph{not} designed to do any sending of email messages to SMTP (\rfc{2821}) servers; that is the ! function of the \refmodule{smtplib} module. The \module{email} ! package attempts to be as RFC-compliant as possible, supporting in ! addition to \rfc{2822}, such MIME-related RFCs as ! \rfc{2045}-\rfc{2047}, and \rfc{2231}. The primary distinguishing feature of the \module{email} package is *************** *** 43,54 **** \module{email} package. The ordering follows a progression that should be common in applications: an email message is read as flat ! text from a file or other source, the text is parsed to produce an ! object model representation of the email message, this model is ! manipulated, and finally the model is rendered back into ! flat text. ! It is perfectly feasible to create the object model out of whole cloth ! --- i.e. completely from scratch. From there, a similar progression ! can be taken as above. Also included are detailed specifications of all the classes and --- 40,50 ---- \module{email} package. The ordering follows a progression that should be common in applications: an email message is read as flat ! text from a file or other source, the text is parsed to produce the ! object structure of the email message, this structure is manipulated, ! and finally rendered back into flat text. ! It is perfectly feasible to create the object structure out of whole ! cloth --- i.e. completely from scratch. From there, a similar ! progression can be taken as above. Also included are detailed specifications of all the classes and *************** *** 56,61 **** classes you might encounter while using the \module{email} package, some auxiliary utilities, and a few examples. For users of the older ! \module{mimelib} package, from which the \module{email} package is ! descended, a section on differences and porting is provided. \begin{seealso} --- 52,57 ---- classes you might encounter while using the \module{email} package, some auxiliary utilities, and a few examples. For users of the older ! \module{mimelib} package, or previous versions of the \module{email} ! package, a section on differences and porting is provided. \begin{seealso} *************** *** 73,215 **** \subsection{Creating email and MIME objects from scratch} ! Ordinarily, you get a message object tree by passing some text to a ! parser, which parses the text and returns the root of the message ! object tree. However you can also build a complete object tree from ! scratch, or even individual \class{Message} objects by hand. In fact, ! you can also take an existing tree and add new \class{Message} ! objects, move them around, etc. This makes a very convenient ! interface for slicing-and-dicing MIME messages. ! ! You can create a new object tree by creating \class{Message} ! instances, adding payloads and all the appropriate headers manually. ! For MIME messages though, the \module{email} package provides some ! convenient classes to make things easier. Each of these classes ! should be imported from a module with the same name as the class, from ! within the \module{email} package. E.g.: ! ! \begin{verbatim} ! import email.MIMEImage.MIMEImage ! \end{verbatim} ! ! or ! ! \begin{verbatim} ! from email.MIMEText import MIMEText ! \end{verbatim} ! ! Here are the classes: ! \begin{classdesc}{MIMEBase}{_maintype, _subtype, **_params} ! This is the base class for all the MIME-specific subclasses of ! \class{Message}. Ordinarily you won't create instances specifically ! of \class{MIMEBase}, although you could. \class{MIMEBase} is provided ! primarily as a convenient base class for more specific MIME-aware ! subclasses. ! \var{_maintype} is the \mailheader{Content-Type} major type ! (e.g. \mimetype{text} or \mimetype{image}), and \var{_subtype} is the ! \mailheader{Content-Type} minor type ! (e.g. \mimetype{plain} or \mimetype{gif}). \var{_params} is a parameter ! key/value dictionary and is passed directly to ! \method{Message.add_header()}. ! The \class{MIMEBase} class always adds a \mailheader{Content-Type} header ! (based on \var{_maintype}, \var{_subtype}, and \var{_params}), and a ! \mailheader{MIME-Version} header (always set to \code{1.0}). ! \end{classdesc} ! \begin{classdesc}{MIMEAudio}{_audiodata\optional{, _subtype\optional{, ! _encoder\optional{, **_params}}}} ! A subclass of \class{MIMEBase}, the \class{MIMEAudio} class is used to ! create MIME message objects of major type \mimetype{audio}. ! \var{_audiodata} is a string containing the raw audio data. If this ! data can be decoded by the standard Python module \refmodule{sndhdr}, ! then the subtype will be automatically included in the ! \mailheader{Content-Type} header. Otherwise you can explicitly specify the ! audio subtype via the \var{_subtype} parameter. If the minor type could ! not be guessed and \var{_subtype} was not given, then \exception{TypeError} ! is raised. ! Optional \var{_encoder} is a callable (i.e. function) which will ! perform the actual encoding of the audio data for transport. This ! callable takes one argument, which is the \class{MIMEAudio} instance. ! It should use \method{get_payload()} and \method{set_payload()} to ! change the payload to encoded form. It should also add any ! \mailheader{Content-Transfer-Encoding} or other headers to the message ! object as necessary. The default encoding is \emph{Base64}. See the ! \refmodule{email.Encoders} module for a list of the built-in encoders. ! \var{_params} are passed straight through to the \class{MIMEBase} ! constructor. ! \end{classdesc} ! \begin{classdesc}{MIMEImage}{_imagedata\optional{, _subtype\optional{, ! _encoder\optional{, **_params}}}} ! A subclass of \class{MIMEBase}, the \class{MIMEImage} class is used to ! create MIME message objects of major type \mimetype{image}. ! \var{_imagedata} is a string containing the raw image data. If this ! data can be decoded by the standard Python module \refmodule{imghdr}, ! then the subtype will be automatically included in the ! \mailheader{Content-Type} header. Otherwise you can explicitly specify the ! image subtype via the \var{_subtype} parameter. If the minor type could ! not be guessed and \var{_subtype} was not given, then \exception{TypeError} ! is raised. ! Optional \var{_encoder} is a callable (i.e. function) which will ! perform the actual encoding of the image data for transport. This ! callable takes one argument, which is the \class{MIMEImage} instance. ! It should use \method{get_payload()} and \method{set_payload()} to ! change the payload to encoded form. It should also add any ! \mailheader{Content-Transfer-Encoding} or other headers to the message ! object as necessary. The default encoding is \emph{Base64}. See the ! \refmodule{email.Encoders} module for a list of the built-in encoders. ! \var{_params} are passed straight through to the \class{MIMEBase} ! constructor. ! \end{classdesc} ! \begin{classdesc}{MIMEText}{_text\optional{, _subtype\optional{, ! _charset\optional{, _encoder}}}} ! A subclass of \class{MIMEBase}, the \class{MIMEText} class is used to ! create MIME objects of major type \mimetype{text}. \var{_text} is the ! string for the payload. \var{_subtype} is the minor type and defaults ! to \mimetype{plain}. \var{_charset} is the character set of the text and is ! passed as a parameter to the \class{MIMEBase} constructor; it defaults ! to \code{us-ascii}. No guessing or encoding is performed on the text ! data, but a newline is appended to \var{_text} if it doesn't already ! end with a newline. ! The \var{_encoding} argument is as with the \class{MIMEImage} class ! constructor, except that the default encoding for \class{MIMEText} ! objects is one that doesn't actually modify the payload, but does set ! the \mailheader{Content-Transfer-Encoding} header to \code{7bit} or ! \code{8bit} as appropriate. ! \end{classdesc} ! \begin{classdesc}{MIMEMessage}{_msg\optional{, _subtype}} ! A subclass of \class{MIMEBase}, the \class{MIMEMessage} class is used to ! create MIME objects of main type \mimetype{message}. \var{_msg} is used as ! the payload, and must be an instance of class \class{Message} (or a ! subclass thereof), otherwise a \exception{TypeError} is raised. ! Optional \var{_subtype} sets the subtype of the message; it defaults ! to \mimetype{rfc822}. ! \end{classdesc} ! \subsection{Encoders} ! \input{emailencoders} ! \subsection{Exception classes} ! \input{emailexc} ! \subsection{Miscellaneous utilities} ! \input{emailutil} ! \subsection{Iterators} ! \input{emailiter} \subsection{Differences from \module{mimelib}} --- 69,172 ---- \subsection{Creating email and MIME objects from scratch} + \input{emailmimebase} ! \subsection{Internationalized headers} ! \input{emailheaders} ! \subsection{Representing character sets} ! \input{emailcharsets} ! \subsection{Encoders} ! \input{emailencoders} ! \subsection{Exception classes} ! \input{emailexc} ! \subsection{Miscellaneous utilities} ! \input{emailutil} ! \subsection{Iterators} ! \input{emailiter} ! \subsection{Differences from \module{email} v1 (up to Python 2.2.1)} ! Version 1 of the \module{email} package was bundled with Python ! releases up to Python 2.2.1. Version 2 was developed for the Python ! 2.3 release, and backported to Python 2.2.2. It was also available as ! a separate distutils based package. \module{email} version 2 is ! almost entirely backward compatible with version 1, with the ! following differences: ! \begin{itemize} ! \item The \module{email.Header} and \module{email.Charset} modules ! have been added. ! \item The pickle format for \class{Message} instances has changed. ! Since this was never (and still isn't) formally defined, this ! isn't considered a backward incompatibility. However if your ! application pickles and unpickles \class{Message} instances, be ! aware that in \module{email} version 2, \class{Message} ! instances now have private variables \var{_charset} and ! \var{_default_type}. ! \item Several methods in the \class{Message} class have been ! deprecated, or their signatures changed. Also, many new methods ! have been added. See the documentation for the \class{Message} ! class for details. The changes should be completely backward ! compatible. ! \item The object structure has changed in the face of ! \mimetype{message/rfc822} content types. In \module{email} ! version 1, such a type would be represented by a scalar payload, ! i.e. the container message's \method{is_multipart()} returned ! false, \method{get_payload()} was not a list object, but a single ! \class{Message} instance. ! This structure was inconsistent with the rest of the package, so ! the object representation for \mimetype{message/rfc822} content ! types was changed. In \module{email} version 2, the container ! \emph{does} return \code{True} from \method{is_multipart()}, and ! \method{get_payload()} returns a list containing a single ! \class{Message} item. ! Note that this is one place that backward compatibility could ! not be completely maintained. However, if you're already ! testing the return type of \method{get_payload()}, you should be ! fine. You just need to make sure your code doesn't do a ! \method{set_payload()} with a \class{Message} instance on a ! container with a content type of \mimetype{message/rfc822}. ! \item The \class{Parser} constructor's \var{strict} argument was ! added, and its \method{parse()} and \method{parsestr()} methods ! grew a \var{headersonly} argument. The \var{strict} flag was ! also added to functions \function{email.message_from_file()} ! and \function{email.message_from_string()}. ! \item \method{Generator.__call__()} is deprecated; use ! \method{Generator.flatten()} instead. The \class{Generator} ! class has also grown the \method{clone()} method. ! \item The \class{DecodedGenerator} class in the ! \module{email.Generator} module was added. ! \item The intermediate base classes \class{MIMENonMultipart} and ! \class{MIMEMultipart} have been added, and interposed in the ! class hierarchy for most of the other MIME-related derived ! classes. ! \item The \var{_encoder} argument to the \class{MIMEText} constructor ! has been deprecated. Encoding now happens implicitly based ! on the \var{_charset} argument. ! \item The following functions in the \module{email.Utils} module have ! been deprecated: \function{dump_address_pairs()}, ! \function{decode()}, and \function{encode()}. The following ! functions have been added to the module: ! \function{make_msgid()}, \function{decode_rfc2231()}, ! \function{encode_rfc2231()}, and \function{decode_params()}. ! \item The non-public function \function{email.Iterators._structure()} ! was added. ! \end{itemize} \subsection{Differences from \module{mimelib}} *************** *** 223,227 **** have also changed. For the most part, any functionality available in \module{mimelib} is still available in the \refmodule{email} package, ! albeit often in a different way. Here is a brief description of the differences between the --- 180,186 ---- have also changed. For the most part, any functionality available in \module{mimelib} is still available in the \refmodule{email} package, ! albeit often in a different way. Backward compatibility between ! the \module{mimelib} package and the \module{email} package was not a ! priority. Here is a brief description of the differences between the *************** *** 236,241 **** --- 195,202 ---- \item \function{messageFromString()} has been renamed to \function{message_from_string()}. + \item \function{messageFromFile()} has been renamed to \function{message_from_file()}. + \end{itemize} *************** *** 244,258 **** --- 205,227 ---- \begin{itemize} \item The method \method{asString()} was renamed to \method{as_string()}. + \item The method \method{ismultipart()} was renamed to \method{is_multipart()}. + \item The \method{get_payload()} method has grown a \var{decode} optional argument. + \item The method \method{getall()} was renamed to \method{get_all()}. + \item The method \method{addheader()} was renamed to \method{add_header()}. + \item The method \method{gettype()} was renamed to \method{get_type()}. + \item The method\method{getmaintype()} was renamed to \method{get_main_type()}. + \item The method \method{getsubtype()} was renamed to \method{get_subtype()}. + \item The method \method{getparams()} was renamed to \method{get_params()}. *************** *** 261,280 **** --- 230,257 ---- the key/value pairs of the parameters, split on the \character{=} sign. + \item The method \method{getparam()} was renamed to \method{get_param()}. + \item The method \method{getcharsets()} was renamed to \method{get_charsets()}. + \item The method \method{getfilename()} was renamed to \method{get_filename()}. + \item The method \method{getboundary()} was renamed to \method{get_boundary()}. + \item The method \method{setboundary()} was renamed to \method{set_boundary()}. + \item The method \method{getdecodedpayload()} was removed. To get similar functionality, pass the value 1 to the \var{decode} flag of the {get_payload()} method. + \item The method \method{getpayloadastext()} was removed. Similar functionality is supported by the \class{DecodedGenerator} class in the \refmodule{email.Generator} module. + \item The method \method{getbodyastext()} was removed. You can get similar functionality by creating an iterator with *************** *** 303,312 **** --- 280,292 ---- and \var{_minor} have changed to \var{_maintype} and \var{_subtype} respectively. + \item The \code{Image} class/module has been renamed to \code{MIMEImage}. The \var{_minor} argument has been renamed to \var{_subtype}. + \item The \code{Text} class/module has been renamed to \code{MIMEText}. The \var{_minor} argument has been renamed to \var{_subtype}. + \item The \code{MessageRFC822} class/module has been renamed to \code{MIMEMessage}. Note that an earlier version of *************** *** 337,408 **** First, let's see how to create and send a simple text message: ! \begin{verbatim} ! # Import smtplib for the actual sending function ! import smtplib ! ! # Here are the email pacakge modules we'll need ! from email import Encoders ! from email.MIMEText import MIMEText ! ! # Open a plain text file for reading ! fp = open(textfile) ! # Create a text/plain message, using Quoted-Printable encoding for non-ASCII ! # characters. ! msg = MIMEText(fp.read(), _encoder=Encoders.encode_quopri) ! fp.close() ! ! # me == the sender's email address ! # you == the recipient's email address ! msg['Subject'] = 'The contents of %s' % textfile ! msg['From'] = me ! msg['To'] = you ! ! # Send the message via our own SMTP server. Use msg.as_string() with ! # unixfrom=0 so as not to confuse SMTP. ! s = smtplib.SMTP() ! s.connect() ! s.sendmail(me, [you], msg.as_string(0)) ! s.close() ! \end{verbatim} Here's an example of how to send a MIME message containing a bunch of ! family pictures: ! ! \begin{verbatim} ! # Import smtplib for the actual sending function ! import smtplib ! ! # Here are the email pacakge modules we'll need ! from email.MIMEImage import MIMEImage ! from email.MIMEBase import MIMEBase ! ! COMMASPACE = ', ' ! ! # Create the container (outer) email message. ! # me == the sender's email address ! # family = the list of all recipients' email addresses ! msg = MIMEBase('multipart', 'mixed') ! msg['Subject'] = 'Our family reunion' ! msg['From'] = me ! msg['To'] = COMMASPACE.join(family) ! msg.preamble = 'Our family reunion' ! # Guarantees the message ends in a newline ! msg.epilogue = '' ! ! # Assume we know that the image files are all in PNG format ! for file in pngfiles: ! # Open the files in binary mode. Let the MIMEIMage class automatically ! # guess the specific image type. ! fp = open(file, 'rb') ! img = MIMEImage(fp.read()) ! fp.close() ! msg.attach(img) ! # Send the email via our own SMTP server. ! s = smtplib.SMTP() ! s.connect() ! s.sendmail(me, family, msg.as_string(unixfrom=0)) ! s.close() ! \end{verbatim} Here's an example\footnote{Thanks to Matthew Dixon Cowles for the --- 317,326 ---- First, let's see how to create and send a simple text message: ! \verbatiminput{email-simple.py} Here's an example of how to send a MIME message containing a bunch of ! family pictures that may be residing in a directory: ! \verbatiminput{email-mime.py} Here's an example\footnote{Thanks to Matthew Dixon Cowles for the *************** *** 410,629 **** of a directory as an email message: ! \begin{verbatim} ! #!/usr/bin/env python ! ! """Send the contents of a directory as a MIME message. ! ! Usage: dirmail [options] from to [to ...]* ! ! Options: ! -h / --help ! Print this message and exit. ! ! -d directory ! --directory=directory ! Mail the contents of the specified directory, otherwise use the ! current directory. Only the regular files in the directory are sent, ! and we don't recurse to subdirectories. ! ! `from' is the email address of the sender of the message. ! ! `to' is the email address of the recipient of the message, and multiple ! recipients may be given. ! ! The email is sent by forwarding to your local SMTP server, which then does the ! normal delivery process. Your local machine must be running an SMTP server. ! """ ! ! import sys ! import os ! import getopt ! import smtplib ! # For guessing MIME type based on file name extension ! import mimetypes ! ! from email import Encoders ! from email.Message import Message ! from email.MIMEAudio import MIMEAudio ! from email.MIMEBase import MIMEBase ! from email.MIMEImage import MIMEImage ! from email.MIMEText import MIMEText ! ! COMMASPACE = ', ' ! ! ! def usage(code, msg=''): ! print >> sys.stderr, __doc__ ! if msg: ! print >> sys.stderr, msg ! sys.exit(code) ! ! ! def main(): ! try: ! opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) ! except getopt.error, msg: ! usage(1, msg) ! ! dir = os.curdir ! for opt, arg in opts: ! if opt in ('-h', '--help'): ! usage(0) ! elif opt in ('-d', '--directory'): ! dir = arg ! ! if len(args) < 2: ! usage(1) ! ! sender = args[0] ! recips = args[1:] ! ! # Create the enclosing (outer) message ! outer = MIMEBase('multipart', 'mixed') ! outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) ! outer['To'] = COMMASPACE.join(recips) ! outer['From'] = sender ! outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' ! # To guarantee the message ends with a newline ! outer.epilogue = '' ! ! for filename in os.listdir(dir): ! path = os.path.join(dir, filename) ! if not os.path.isfile(path): ! continue ! # Guess the Content-Type: based on the file's extension. Encoding ! # will be ignored, although we should check for simple things like ! # gzip'd or compressed files ! ctype, encoding = mimetypes.guess_type(path) ! if ctype is None or encoding is not None: ! # No guess could be made, or the file is encoded (compressed), so ! # use a generic bag-of-bits type. ! ctype = 'application/octet-stream' ! maintype, subtype = ctype.split('/', 1) ! if maintype == 'text': ! fp = open(path) ! # Note: we should handle calculating the charset ! msg = MIMEText(fp.read(), _subtype=subtype) ! fp.close() ! elif maintype == 'image': ! fp = open(path, 'rb') ! msg = MIMEImage(fp.read(), _subtype=subtype) ! fp.close() ! elif maintype == 'audio': ! fp = open(path, 'rb') ! msg = MIMEAudio(fp.read(), _subtype=subtype) ! fp.close() ! else: ! fp = open(path, 'rb') ! msg = MIMEBase(maintype, subtype) ! msg.add_payload(fp.read()) ! fp.close() ! # Encode the payload using Base64 ! Encoders.encode_base64(msg) ! # Set the filename parameter ! msg.add_header('Content-Disposition', 'attachment', filename=filename) ! outer.attach(msg) ! ! fp = open('/tmp/debug.pck', 'w') ! import cPickle ! cPickle.dump(outer, fp) ! fp.close() ! # Now send the message ! s = smtplib.SMTP() ! s.connect() ! s.sendmail(sender, recips, outer.as_string(0)) ! s.close() ! ! ! if __name__ == '__main__': ! main() ! \end{verbatim} And finally, here's an example of how to unpack a MIME message like the one above, into a directory of files: ! \begin{verbatim} ! #!/usr/bin/env python ! ! """Unpack a MIME message into a directory of files. ! ! Usage: unpackmail [options] msgfile ! ! Options: ! -h / --help ! Print this message and exit. ! ! -d directory ! --directory=directory ! Unpack the MIME message into the named directory, which will be ! created if it doesn't already exist. ! ! msgfile is the path to the file containing the MIME message. ! """ ! ! import sys ! import os ! import getopt ! import errno ! import mimetypes ! import email ! ! ! def usage(code, msg=''): ! print >> sys.stderr, __doc__ ! if msg: ! print >> sys.stderr, msg ! sys.exit(code) ! ! ! def main(): ! try: ! opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) ! except getopt.error, msg: ! usage(1, msg) ! ! dir = os.curdir ! for opt, arg in opts: ! if opt in ('-h', '--help'): ! usage(0) ! elif opt in ('-d', '--directory'): ! dir = arg ! ! try: ! msgfile = args[0] ! except IndexError: ! usage(1) ! ! try: ! os.mkdir(dir) ! except OSError, e: ! # Ignore directory exists error ! if e.errno <> errno.EEXIST: raise ! ! fp = open(msgfile) ! msg = email.message_from_file(fp) ! fp.close() ! ! counter = 1 ! for part in msg.walk(): ! # multipart/* are just containers ! if part.get_main_type() == 'multipart': ! continue ! # Applications should really sanitize the given filename so that an ! # email message can't be used to overwrite important files ! filename = part.get_filename() ! if not filename: ! ext = mimetypes.guess_extension(part.get_type()) ! if not ext: ! # Use a generic bag-of-bits extension ! ext = '.bin' ! filename = 'part-%03d%s' % (counter, ext) ! counter += 1 ! fp = open(os.path.join(dir, filename), 'wb') ! fp.write(part.get_payload(decode=1)) ! fp.close() ! ! ! if __name__ == '__main__': ! main() ! \end{verbatim} --- 328,335 ---- of a directory as an email message: ! \verbatiminput{email-dir.py} And finally, here's an example of how to unpack a MIME message like the one above, into a directory of files: ! \verbatiminput{email-unpack.py} Index: emailencoders.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailencoders.tex,v retrieving revision 1.2 retrieving revision 1.2.12.1 diff -C2 -d -r1.2 -r1.2.12.1 *** emailencoders.tex 26 Sep 2001 22:21:52 -0000 1.2 --- emailencoders.tex 4 Oct 2002 17:24:23 -0000 1.2.12.1 *************** *** 18,23 **** \begin{funcdesc}{encode_quopri}{msg} ! Encodes the payload into \emph{Quoted-Printable} form and sets the ! \code{Content-Transfer-Encoding:} header to \code{quoted-printable}\footnote{Note that encoding with \method{encode_quopri()} also encodes all tabs and space characters in --- 18,23 ---- \begin{funcdesc}{encode_quopri}{msg} ! Encodes the payload into quoted-printable form and sets the ! \mailheader{Content-Transfer-Encoding} header to \code{quoted-printable}\footnote{Note that encoding with \method{encode_quopri()} also encodes all tabs and space characters in *************** *** 28,36 **** \begin{funcdesc}{encode_base64}{msg} ! Encodes the payload into \emph{Base64} form and sets the \mailheader{Content-Transfer-Encoding} header to \code{base64}. This is a good encoding to use when most of your payload is unprintable data since it is a more compact form than ! Quoted-Printable. The drawback of Base64 encoding is that it renders the text non-human readable. \end{funcdesc} --- 28,36 ---- \begin{funcdesc}{encode_base64}{msg} ! Encodes the payload into base64 form and sets the \mailheader{Content-Transfer-Encoding} header to \code{base64}. This is a good encoding to use when most of your payload is unprintable data since it is a more compact form than ! quoted-printable. The drawback of base64 encoding is that it renders the text non-human readable. \end{funcdesc} Index: emailexc.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailexc.tex,v retrieving revision 1.2 retrieving revision 1.2.12.1 diff -C2 -d -r1.2 -r1.2.12.1 *** emailexc.tex 26 Sep 2001 22:21:52 -0000 1.2 --- emailexc.tex 4 Oct 2002 17:24:23 -0000 1.2.12.1 *************** *** 22,26 **** \method{Parser.parsestr()} methods. ! Situations where it can be raised include finding a \emph{Unix-From} header after the first \rfc{2822} header of the message, finding a continuation line before the first \rfc{2822} header is found, or finding --- 22,26 ---- \method{Parser.parsestr()} methods. ! Situations where it can be raised include finding an envelope header after the first \rfc{2822} header of the message, finding a continuation line before the first \rfc{2822} header is found, or finding *************** *** 36,40 **** Situations where it can be raised include not being able to find the ! starting or terminating boundary in a \mimetype{multipart/*} message. \end{excclassdesc} --- 36,41 ---- Situations where it can be raised include not being able to find the ! starting or terminating boundary in a \mimetype{multipart/*} message ! when strict parsing is used. \end{excclassdesc} *************** *** 46,48 **** --- 47,54 ---- multiply inherits from \exception{MessageError} and the built-in \exception{TypeError}. + + Since \method{Message.add_payload()} is deprecated, this exception is + rarely raised in practice. However the exception may also be raised + if the \method{attach()} method is called on an instance of a class + derived from \class{MIMENonMultipart} (e.g. \class{MIMEImage}). \end{excclassdesc} Index: emailgenerator.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailgenerator.tex,v retrieving revision 1.3 retrieving revision 1.3.8.1 diff -C2 -d -r1.3 -r1.3.8.1 *** emailgenerator.tex 5 Nov 2001 01:55:03 -0000 1.3 --- emailgenerator.tex 4 Oct 2002 17:24:23 -0000 1.3.8.1 *************** *** 1,10 **** \declaremodule{standard}{email.Generator} ! \modulesynopsis{Generate flat text email messages from a message object tree.} One of the most common tasks is to generate the flat text of the email ! message represented by a message object tree. You will need to do this if you want to send your message via the \refmodule{smtplib} module or the \refmodule{nntplib} module, or print the message on the ! console. Taking a message object tree and producing a flat text document is the job of the \class{Generator} class. --- 1,10 ---- \declaremodule{standard}{email.Generator} ! \modulesynopsis{Generate flat text email messages from a message structure.} One of the most common tasks is to generate the flat text of the email ! message represented by a message object structure. You will need to do this if you want to send your message via the \refmodule{smtplib} module or the \refmodule{nntplib} module, or print the message on the ! console. Taking a message object structure and producing a flat text document is the job of the \class{Generator} class. *************** *** 14,21 **** generate most email in a standards-compliant way, should handle MIME and non-MIME email messages just fine, and is designed so that the ! transformation from flat text, to an object tree via the ! \class{Parser} class, ! and back to flat text, is idempotent (the input is identical to the ! output). Here are the public methods of the \class{Generator} class: --- 14,20 ---- generate most email in a standards-compliant way, should handle MIME and non-MIME email messages just fine, and is designed so that the ! transformation from flat text, to a message structure via the ! \class{Parser} class, and back to flat text, is idempotent (the input ! is identical to the output). Here are the public methods of the \class{Generator} class: *************** *** 26,39 **** object called \var{outfp} for an argument. \var{outfp} must support the \method{write()} method and be usable as the output file in a ! Python 2.0 extended print statement. ! Optional \var{mangle_from_} is a flag that, when true, puts a \samp{>} ! character in front of any line in the body that starts exactly as ! \samp{From } (i.e. \code{From} followed by a space at the front of the ! line). This is the only guaranteed portable way to avoid having such ! lines be mistaken for \emph{Unix-From} headers (see \ulink{WHY THE CONTENT-LENGTH FORMAT IS BAD} {http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html} ! for details). Optional \var{maxheaderlen} specifies the longest length for a --- 25,40 ---- object called \var{outfp} for an argument. \var{outfp} must support the \method{write()} method and be usable as the output file in a ! Python extended print statement. ! Optional \var{mangle_from_} is a flag that, when \code{True}, puts a ! \samp{>} character in front of any line in the body that starts exactly as ! \samp{From }, i.e. \code{From} followed by a space at the beginning of the ! line. This is the only guaranteed portable way to avoid having such ! lines be mistaken for a Unix mailbox format envelope header separator (see \ulink{WHY THE CONTENT-LENGTH FORMAT IS BAD} {http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html} ! for details). \var{mangle_from_} defaults to \code{True}, but you ! might want to set this to \code{False} if you are not writing Unix ! mailbox format files. Optional \var{maxheaderlen} specifies the longest length for a *************** *** 48,65 **** The other public \class{Generator} methods are: ! \begin{methoddesc}[Generator]{__call__}{msg\optional{, unixfrom}} ! Print the textual representation of the message object tree rooted at \var{msg} to the output file specified when the \class{Generator} ! instance was created. Sub-objects are visited depth-first and the resulting text will be properly MIME encoded. Optional \var{unixfrom} is a flag that forces the printing of the ! \emph{Unix-From} (a.k.a. envelope header or \code{From_} header) ! delimiter before the first \rfc{2822} header of the root message ! object. If the root object has no \emph{Unix-From} header, a standard ! one is crafted. By default, this is set to 0 to inhibit the printing ! of the \emph{Unix-From} delimiter. ! Note that for sub-objects, no \emph{Unix-From} header is ever printed. \end{methoddesc} --- 49,74 ---- The other public \class{Generator} methods are: ! \begin{methoddesc}[Generator]{flatten}{msg\optional{, unixfrom}} ! Print the textual representation of the message object structure rooted at \var{msg} to the output file specified when the \class{Generator} ! instance was created. Subparts are visited depth-first and the resulting text will be properly MIME encoded. Optional \var{unixfrom} is a flag that forces the printing of the ! envelope header delimiter before the first \rfc{2822} header of the ! root message object. If the root object has no envelope header, a ! standard one is crafted. By default, this is set to \code{False} to ! inhibit the printing of the envelope delimiter. ! Note that for subparts, no envelope header is ever printed. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Generator]{clone}{fp} ! Return an independent clone of this \class{Generator} instance with ! the exact same options. ! ! \versionadded{2.2.2} \end{methoddesc} *************** *** 75,76 **** --- 84,141 ---- simplify the generation of a formatted string representation of a message object. For more detail, see \refmodule{email.Message}. + + The \module{email.Generator} module also provides a derived class, + called \class{DecodedGenerator} which is like the \class{Generator} + base class, except that non-\mimetype{text} parts are substituted with + a format string representing the part. + + \begin{classdesc}{DecodedGenerator}{outfp\optional{, mangle_from_\optional{, + maxheaderlen\optional{, fmt}}}} + + This class, derived from \class{Generator} walks through all the + subparts of a message. If the subpart is of main type + \mimetype{text}, then it prints the decoded payload of the subpart. + Optional \var{_mangle_from_} and \var{maxheaderlen} are as with the + \class{Generator} base class. + + If the subpart is not of main type \mimetype{text}, optional \var{fmt} + is a format string that is used instead of the message payload. + \var{fmt} is expanded with the following keywords, \samp{\%(keyword)s} + format: + + \begin{itemize} + \item \code{type} -- Full MIME type of the non-\mimetype{text} part + + \item \code{maintype} -- Main MIME type of the non-\mimetype{text} part + + \item \code{subtype} -- Sub-MIME type of the non-\mimetype{text} part + + \item \code{filename} -- Filename of the non-\mimetype{text} part + + \item \code{description} -- Description associated with the + non-\mimetype{text} part + + \item \code{encoding} -- Content transfer encoding of the + non-\mimetype{text} part + + \end{itemize} + + The default value for \var{fmt} is \code{None}, meaning + + \begin{verbatim} + [Non-text (%(type)s) part of message omitted, filename %(filename)s] + \end{verbatim} + + \versionadded{2.2.2} + \end{classdesc} + + \subsubsection{Deprecated methods} + + The following methods are deprecated in \module{email} version 2. + They are documented here for completeness. + + \begin{methoddesc}[Generator]{__call__}{msg\optional{, unixfrom}} + This method is identical to the \method{flatten()} method. + + \deprecated{2.2.2}{Use the \method{flatten()} method instead.} + \end{methoddesc} Index: emailiter.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailiter.tex,v retrieving revision 1.2 retrieving revision 1.2.12.1 diff -C2 -d -r1.2 -r1.2.12.1 *** emailiter.tex 26 Sep 2001 22:21:52 -0000 1.2 --- emailiter.tex 4 Oct 2002 17:24:23 -0000 1.2.12.1 *************** *** 30,31 **** --- 30,63 ---- \end{funcdesc} + The following function has been added as a useful debugging tool. It + should \emph{not} be considered part of the supported public interface + for the package. + + \begin{funcdesc}{_structure}{msg\optional{, fp\optional{, level}}} + Prints an indented representation of the content types of the + message object structure. For example: + + \begin{verbatim} + >>> msg = email.message_from_file(somefile) + >>> _structure(msg) + multipart/mixed + text/plain + text/plain + multipart/digest + message/rfc822 + text/plain + message/rfc822 + text/plain + message/rfc822 + text/plain + message/rfc822 + text/plain + message/rfc822 + text/plain + text/plain + \end{verbatim} + + Optional \var{fp} is a file-like object to print the output to. It + must be suitable for Python's extended print statement. \var{level} + is used internally. + \end{funcdesc} Index: emailmessage.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailmessage.tex,v retrieving revision 1.4 retrieving revision 1.4.8.1 diff -C2 -d -r1.4 -r1.4.8.1 *** emailmessage.tex 5 Nov 2001 01:55:03 -0000 1.4 --- emailmessage.tex 4 Oct 2002 17:24:23 -0000 1.4.8.1 *************** *** 13,22 **** Headers are stored and returned in case-preserving form but are ! matched case-insensitively. There may also be a single ! \emph{Unix-From} header, also known as the envelope header or the \code{From_} header. The payload is either a string in the case of ! simple message objects, a list of \class{Message} objects for ! multipart MIME documents, or a single \class{Message} instance for ! \mimetype{message/rfc822} type objects. \class{Message} objects provide a mapping style interface for --- 13,22 ---- Headers are stored and returned in case-preserving form but are ! matched case-insensitively. There may also be a single envelope ! header, also known as the \emph{Unix-From} header or the \code{From_} header. The payload is either a string in the case of ! simple message objects or a list of \class{Message} objects for ! MIME container documents (e.g. \mimetype{multipart/*} and ! \mimetype{message/rfc822}). \class{Message} objects provide a mapping style interface for *************** *** 34,129 **** \begin{methoddesc}[Message]{as_string}{\optional{unixfrom}} ! Return the entire formatted message as a string. Optional ! \var{unixfrom}, when true, specifies to include the \emph{Unix-From} ! envelope header; it defaults to 0. \end{methoddesc} ! \begin{methoddesc}[Message]{__str__()}{} ! Equivalent to \method{aMessage.as_string(unixfrom=1)}. \end{methoddesc} \begin{methoddesc}[Message]{is_multipart}{} ! Return 1 if the message's payload is a list of sub-\class{Message} ! objects, otherwise return 0. When \method{is_multipart()} returns 0, ! the payload should either be a string object, or a single ! \class{Message} instance. \end{methoddesc} \begin{methoddesc}[Message]{set_unixfrom}{unixfrom} ! Set the \emph{Unix-From} (a.k.a envelope header or \code{From_} ! header) to \var{unixfrom}, which should be a string. \end{methoddesc} \begin{methoddesc}[Message]{get_unixfrom}{} ! Return the \emph{Unix-From} header. Defaults to \code{None} if the ! \emph{Unix-From} header was never set. ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{add_payload}{payload} ! Add \var{payload} to the message object's existing payload. If, prior ! to calling this method, the object's payload was \code{None} ! (i.e. never before set), then after this method is called, the payload ! will be the argument \var{payload}. ! ! If the object's payload was already a list ! (i.e. \method{is_multipart()} returns 1), then \var{payload} is ! appended to the end of the existing payload list. ! ! For any other type of existing payload, \method{add_payload()} will ! transform the new payload into a list consisting of the old payload ! and \var{payload}, but only if the document is already a MIME ! multipart document. This condition is satisfied if the message's ! \mailheader{Content-Type} header's main type is either ! \mimetype{multipart}, or there is no \mailheader{Content-Type} ! header. In any other situation, ! \exception{MultipartConversionError} is raised. \end{methoddesc} \begin{methoddesc}[Message]{attach}{payload} ! Synonymous with \method{add_payload()}. \end{methoddesc} \begin{methoddesc}[Message]{get_payload}{\optional{i\optional{, decode}}} ! Return the current payload, which will be a list of \class{Message} ! objects when \method{is_multipart()} returns 1, or a scalar (either a ! string or a single \class{Message} instance) when ! \method{is_multipart()} returns 0. ! With optional \var{i}, \method{get_payload()} will return the \var{i}-th element of the payload, counting from zero, if ! \method{is_multipart()} returns 1. An \exception{IndexError} will be raised ! if \var{i} is less than 0 or greater than or equal to the number of ! items in the payload. If the payload is scalar ! (i.e. \method{is_multipart()} returns 0) and \var{i} is given, a \exception{TypeError} is raised. Optional \var{decode} is a flag indicating whether the payload should be decoded or not, according to the \mailheader{Content-Transfer-Encoding} header. ! When true and the message is not a multipart, the payload will be decoded if this header's value is \samp{quoted-printable} or \samp{base64}. If some other encoding is used, or \mailheader{Content-Transfer-Encoding} header is missing, the payload is returned as-is (undecoded). If the message is ! a multipart and the \var{decode} flag is true, then \code{None} is ! returned. \end{methoddesc} ! \begin{methoddesc}[Message]{set_payload}{payload} Set the entire message object's payload to \var{payload}. It is the ! client's responsibility to ensure the payload invariants. \end{methoddesc} The following methods implement a mapping-like interface for accessing ! the message object's \rfc{2822} headers. Note that there are some semantic differences between these methods and a normal mapping (i.e. dictionary) interface. For example, in a dictionary there are no duplicate keys, but here there may be duplicate message headers. Also, in dictionaries there is no guaranteed order to the keys returned by ! \method{keys()}, but in a \class{Message} object, there is an explicit ! order. These semantic differences are intentional and are biased ! toward maximal convenience. ! Note that in all cases, any optional \emph{Unix-From} header the message ! may have is not included in the mapping interface. \begin{methoddesc}[Message]{__len__}{} --- 34,147 ---- \begin{methoddesc}[Message]{as_string}{\optional{unixfrom}} ! Return the entire message flatten as a string. When optional ! \var{unixfrom} is \code{True}, the envelope header is included in the ! returned string. \var{unixfrom} defaults to \code{False}. \end{methoddesc} ! \begin{methoddesc}[Message]{__str__}{} ! Equivalent to \method{as_string(unixfrom=True)}. \end{methoddesc} \begin{methoddesc}[Message]{is_multipart}{} ! Return \code{True} if the message's payload is a list of ! sub-\class{Message} objects, otherwise return \code{False}. When ! \method{is_multipart()} returns False, the payload should be a string ! object. \end{methoddesc} \begin{methoddesc}[Message]{set_unixfrom}{unixfrom} ! Set the message's envelope header to \var{unixfrom}, which should be a string. \end{methoddesc} \begin{methoddesc}[Message]{get_unixfrom}{} ! Return the message's envelope header. Defaults to \code{None} if the ! envelope header was never set. \end{methoddesc} \begin{methoddesc}[Message]{attach}{payload} ! Add the given \var{payload} to the current payload, which must be ! \code{None} or a list of \class{Message} objects before the call. ! After the call, the payload will always be a list of \class{Message} ! objects. If you want to set the payload to a scalar object (e.g. a ! string), use \method{set_payload()} instead. \end{methoddesc} \begin{methoddesc}[Message]{get_payload}{\optional{i\optional{, decode}}} ! Return a reference the current payload, which will be a list of ! \class{Message} objects when \method{is_multipart()} is \code{True}, or a ! string when \method{is_multipart()} is \code{False}. If the ! payload is a list and you mutate the list object, you modify the ! message's payload in place. ! With optional argument \var{i}, \method{get_payload()} will return the \var{i}-th element of the payload, counting from zero, if ! \method{is_multipart()} is \code{True}. An \exception{IndexError} ! will be raised if \var{i} is less than 0 or greater than or equal to ! the number of items in the payload. If the payload is a string ! (i.e. \method{is_multipart()} is \code{False}) and \var{i} is given, a \exception{TypeError} is raised. Optional \var{decode} is a flag indicating whether the payload should be decoded or not, according to the \mailheader{Content-Transfer-Encoding} header. ! When \code{True} and the message is not a multipart, the payload will be decoded if this header's value is \samp{quoted-printable} or \samp{base64}. If some other encoding is used, or \mailheader{Content-Transfer-Encoding} header is missing, the payload is returned as-is (undecoded). If the message is ! a multipart and the \var{decode} flag is \code{True}, then \code{None} is ! returned. The default for \var{decode} is \code{False}. \end{methoddesc} ! \begin{methoddesc}[Message]{set_payload}{payload\optional{, charset}} Set the entire message object's payload to \var{payload}. It is the ! client's responsibility to ensure the payload invariants. Optional ! \var{charset} sets the message's default character set; see ! \method{set_charset()} for details. ! ! \versionchanged[\var{charset} argument added]{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{set_charset}{charset} ! Set the character set of the payload to \var{charset}, which can ! either be a \class{Charset} instance (see \refmodule{email.Charset}), a ! string naming a character set, ! or \code{None}. If it is a string, it will be converted to a ! \class{Charset} instance. If \var{charset} is \code{None}, the ! \code{charset} parameter will be removed from the ! \mailheader{Content-Type} header. Anything else will generate a ! \exception{TypeError}. ! ! The message will be assumed to be of type \mimetype{text/*} encoded with ! \code{charset.input_charset}. It will be converted to ! \code{charset.output_charset} ! and encoded properly, if needed, when generating the plain text ! representation of the message. MIME headers ! (\mailheader{MIME-Version}, \mailheader{Content-Type}, ! \mailheader{Content-Transfer-Encoding}) will be added as needed. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{get_charset}{} ! Return the \class{Charset} instance associated with the message's payload. ! \versionadded{2.2.2} \end{methoddesc} The following methods implement a mapping-like interface for accessing ! the message's \rfc{2822} headers. Note that there are some semantic differences between these methods and a normal mapping (i.e. dictionary) interface. For example, in a dictionary there are no duplicate keys, but here there may be duplicate message headers. Also, in dictionaries there is no guaranteed order to the keys returned by ! \method{keys()}, but in a \class{Message} object, headers are always ! returned in the order they appeared in the original message, or were ! added to the message later. Any header deleted and then re-added are ! always appended to the end of the header list. ! These semantic differences are intentional and are biased toward ! maximal convenience. ! ! Note that in all cases, any envelope header present in the message is ! not included in the mapping interface. \begin{methoddesc}[Message]{__len__}{} *************** *** 162,167 **** with the same name. If you want to ensure that the new header is the only one present in the message with field name ! \var{name}, first use \method{__delitem__()} to delete all named ! fields, e.g.: \begin{verbatim} --- 180,184 ---- with the same name. If you want to ensure that the new header is the only one present in the message with field name ! \var{name}, delete the field first, e.g.: \begin{verbatim} *************** *** 178,207 **** \begin{methoddesc}[Message]{has_key}{name} ! Return 1 if the message contains a header field named \var{name}, ! otherwise return 0. \end{methoddesc} \begin{methoddesc}[Message]{keys}{} ! Return a list of all the message's header field names. These keys ! will be sorted in the order in which they were added to the message ! via \method{__setitem__()}, and may contain duplicates. Any fields ! deleted and then subsequently re-added are always appended to the end ! of the header list. \end{methoddesc} \begin{methoddesc}[Message]{values}{} ! Return a list of all the message's field values. These will be sorted ! in the order in which they were added to the message via ! \method{__setitem__()}, and may contain duplicates. Any fields ! deleted and then subsequently re-added are always appended to the end ! of the header list. \end{methoddesc} \begin{methoddesc}[Message]{items}{} ! Return a list of 2-tuples containing all the message's field headers and ! values. These will be sorted in the order in which they were added to ! the message via \method{__setitem__()}, and may contain duplicates. ! Any fields deleted and then subsequently re-added are always appended ! to the end of the header list. \end{methoddesc} --- 195,213 ---- \begin{methoddesc}[Message]{has_key}{name} ! Return true if the message contains a header field named \var{name}, ! otherwise return false. \end{methoddesc} \begin{methoddesc}[Message]{keys}{} ! Return a list of all the message's header field names. \end{methoddesc} \begin{methoddesc}[Message]{values}{} ! Return a list of all the message's field values. \end{methoddesc} \begin{methoddesc}[Message]{items}{} ! Return a list of 2-tuples containing all the message's field headers ! and values. \end{methoddesc} *************** *** 215,224 **** \begin{methoddesc}[Message]{get_all}{name\optional{, failobj}} ! Return a list of all the values for the field named \var{name}. These ! will be sorted in the order in which they were added to the message ! via \method{__setitem__()}. Any fields ! deleted and then subsequently re-added are always appended to the end ! of the list. ! If there are no such named headers in the message, \var{failobj} is returned (defaults to \code{None}). --- 221,225 ---- \begin{methoddesc}[Message]{get_all}{name\optional{, failobj}} ! Return a list of all the values for the field named \var{name}. If there are no such named headers in the message, \var{failobj} is returned (defaults to \code{None}). *************** *** 228,233 **** Extended header setting. This method is similar to \method{__setitem__()} except that additional header parameters can be ! provided as keyword arguments. \var{_name} is the header to set and ! \var{_value} is the \emph{primary} value for the header. For each item in the keyword argument dictionary \var{_params}, the --- 229,234 ---- Extended header setting. This method is similar to \method{__setitem__()} except that additional header parameters can be ! provided as keyword arguments. \var{_name} is the header field to add ! and \var{_value} is the \emph{primary} value for the header. For each item in the keyword argument dictionary \var{_params}, the *************** *** 250,276 **** \end{methoddesc} ! \begin{methoddesc}[Message]{get_type}{\optional{failobj}} ! Return the message's content type, as a string of the form ! \mimetype{maintype/subtype} as taken from the ! \mailheader{Content-Type} header. ! The returned string is coerced to lowercase. ! If there is no \mailheader{Content-Type} header in the message, ! \var{failobj} is returned (defaults to \code{None}). \end{methoddesc} ! \begin{methoddesc}[Message]{get_main_type}{\optional{failobj}} ! Return the message's \emph{main} content type. This essentially returns the ! \var{maintype} part of the string returned by \method{get_type()}, with the ! same semantics for \var{failobj}. \end{methoddesc} ! \begin{methoddesc}[Message]{get_subtype}{\optional{failobj}} ! Return the message's sub-content type. This essentially returns the ! \var{subtype} part of the string returned by \method{get_type()}, with the ! same semantics for \var{failobj}. \end{methoddesc} ! \begin{methoddesc}[Message]{get_params}{\optional{failobj\optional{, header}}} Return the message's \mailheader{Content-Type} parameters, as a list. The elements of the returned list are 2-tuples of key/value pairs, as --- 251,315 ---- \end{methoddesc} ! \begin{methoddesc}[Message]{replace_header}{_name, _value} ! Replace a header. Replace the first header found in the message that ! matches \var{_name}, retaining header order and field name case. If ! no matching header was found, a \exception{KeyError} is raised. ! \versionadded{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Message]{get_content_type}{} ! Return the message's content type. The returned string is coerced to ! lower case of the form \mimetype{maintype/subtype}. If there was no ! \mailheader{Content-Type} header in the message the default type as ! given by \method{get_default_type()} will be returned. Since ! according to \rfc{2045}, messages always have a default type, ! \method{get_content_type()} will always return a value. ! ! \rfc{2045} defines a message's default type to be ! \mimetype{text/plain} unless it appears inside a ! \mimetype{multipart/digest} container, in which case it would be ! \mimetype{message/rfc822}. If the \mailheader{Content-Type} header ! has an invalid type specification, \rfc{2045} mandates that the ! default type be \mimetype{text/plain}. ! ! \versionadded{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Message]{get_content_maintype}{} ! Return the message's main content type. This is the ! \mimetype{maintype} part of the string returned by ! \method{get_content_type()}. ! ! \versionadded{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Message]{get_content_subtype}{} ! Return the message's sub-content type. This is the \mimetype{subtype} ! part of the string returned by \method{get_content_type()}. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{get_default_type}{} ! Return the default content type. Most messages have a default content ! type of \mimetype{text/plain}, except for messages that are subparts ! of \mimetype{multipart/digest} containers. Such subparts have a ! default content type of \mimetype{message/rfc822}. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{set_default_type}{ctype} ! Set the default content type. \var{ctype} should either be ! \mimetype{text/plain} or \mimetype{message/rfc822}, although this is ! not enforced. The default content type is not stored in the ! \mailheader{Content-Type} header. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{get_params}{\optional{failobj\optional{, ! header\optional{, unquote}}}} Return the message's \mailheader{Content-Type} parameters, as a list. The elements of the returned list are 2-tuples of key/value pairs, as *************** *** 278,290 **** \character{=} is the key, while the right hand side is the value. If there is no \character{=} sign in the parameter the value is the empty ! string. The value is always unquoted with \method{Utils.unquote()}. Optional \var{failobj} is the object to return if there is no \mailheader{Content-Type} header. Optional \var{header} is the header to search instead of \mailheader{Content-Type}. \end{methoddesc} \begin{methoddesc}[Message]{get_param}{param\optional{, ! failobj\optional{, header}}} Return the value of the \mailheader{Content-Type} header's parameter \var{param} as a string. If the message has no \mailheader{Content-Type} --- 317,332 ---- \character{=} is the key, while the right hand side is the value. If there is no \character{=} sign in the parameter the value is the empty ! string, otherwise the value is as described in \method{get_param()} and is ! unquoted if optional \var{unquote} is \code{True} (the default). Optional \var{failobj} is the object to return if there is no \mailheader{Content-Type} header. Optional \var{header} is the header to search instead of \mailheader{Content-Type}. + + \versionchanged[\var{unquote} argument added]{2.2.2} \end{methoddesc} \begin{methoddesc}[Message]{get_param}{param\optional{, ! failobj\optional{, header\optional{, unquote}}}} Return the value of the \mailheader{Content-Type} header's parameter \var{param} as a string. If the message has no \mailheader{Content-Type} *************** *** 294,311 **** Optional \var{header} if given, specifies the message header to use instead of \mailheader{Content-Type}. \end{methoddesc} ! \begin{methoddesc}[Message]{get_charsets}{\optional{failobj}} ! Return a list containing the character set names in the message. If ! the message is a \mimetype{multipart}, then the list will contain one ! element for each subpart in the payload, otherwise, it will be a list ! of length 1. ! Each item in the list will be a string which is the value of the ! \code{charset} parameter in the \mailheader{Content-Type} header for the ! represented subpart. However, if the subpart has no ! \mailheader{Content-Type} header, no \code{charset} parameter, or is not of ! the \mimetype{text} main MIME type, then that item in the returned list ! will be \var{failobj}. \end{methoddesc} --- 336,413 ---- Optional \var{header} if given, specifies the message header to use instead of \mailheader{Content-Type}. + + Parameter keys are always compared case insensitively. The return + value can either be a string, or a 3-tuple if the parameter was + \rfc{2231} encoded. When it's a 3-tuple, the elements of the value are of + the form \code{(CHARSET, LANGUAGE, VALUE)}, where \code{LANGUAGE} may + be the empty string. Your application should be prepared to deal with + 3-tuple return values, which it can convert to a Unicode string like + so: + + \begin{verbatim} + param = msg.get_param('foo') + if isinstance(param, tuple): + param = unicode(param[2], param[0]) + \end{verbatim} + + In any case, the parameter value (either the returned string, or the + \code{VALUE} item in the 3-tuple) is always unquoted, unless + \var{unquote} is set to \code{False}. + + \versionchanged[\var{unquote} argument added, and 3-tuple return value + possible]{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Message]{set_param}{param, value\optional{, ! header\optional{, requote\optional{, charset\optional{, language}}}}} ! Set a parameter in the \mailheader{Content-Type} header. If the ! parameter already exists in the header, its value will be replaced ! with \var{value}. If the \mailheader{Content-Type} header as not yet ! been defined for this message, it will be set to \mimetype{text/plain} ! and the new parameter value will be appended as per \rfc{2045}. ! ! Optional \var{header} specifies an alternative header to ! \mailheader{Content-Type}, and all parameters will be quoted as ! necessary unless optional \var{requote} is \code{False} (the default ! is \code{True}). ! ! If optional \var{charset} is specified, the parameter will be encoded ! according to \rfc{2231}. Optional \var{language} specifies the RFC ! 2231 language, defaulting to the empty string. Both \var{charset} and ! \var{language} should be strings. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{del_param}{param\optional{, header\optional{, ! requote}}} ! Remove the given parameter completely from the ! \mailheader{Content-Type} header. The header will be re-written in ! place without the parameter or its value. All values will be quoted ! as necessary unless \var{requote} is \code{False} (the default is ! \code{True}). Optional \var{header} specifies an alternative to ! \mailheader{Content-Type}. ! ! \versionadded{2.2.2} ! \end{methoddesc} ! ! \begin{methoddesc}[Message]{set_type}{type\optional{, header}\optional{, ! requote}} ! Set the main type and subtype for the \mailheader{Content-Type} ! header. \var{type} must be a string in the form ! \mimetype{maintype/subtype}, otherwise a \exception{ValueError} is ! raised. ! ! This method replaces the \mailheader{Content-Type} header, keeping all ! the parameters in place. If \var{requote} is \code{False}, this ! leaves the existing header's quoting as is, otherwise the parameters ! will be quoted (the default). ! ! An alternative header can be specified in the \var{header} argument. ! When the \mailheader{Content-Type} header is set a ! \mailheader{MIME-Version} header is also added. ! ! \versionadded{2.2.2} \end{methoddesc} *************** *** 327,335 **** \begin{methoddesc}[Message]{set_boundary}{boundary} ! Set the \code{boundary} parameter of the \mailheader{Content-Type} header ! to \var{boundary}. \method{set_boundary()} will always quote ! \var{boundary} so you should not quote it yourself. A ! \exception{HeaderParseError} is raised if the message object has no ! \mailheader{Content-Type} header. Note that using this method is subtly different than deleting the old --- 429,436 ---- \begin{methoddesc}[Message]{set_boundary}{boundary} ! Set the \code{boundary} parameter of the \mailheader{Content-Type} ! header to \var{boundary}. \method{set_boundary()} will always quote ! \var{boundary} if necessary. A \exception{HeaderParseError} is raised ! if the message object has no \mailheader{Content-Type} header. Note that using this method is subtly different than deleting the old *************** *** 341,357 **** \end{methoddesc} \begin{methoddesc}[Message]{walk}{} The \method{walk()} method is an all-purpose generator which can be used to iterate over all the parts and subparts of a message object tree, in depth-first traversal order. You will typically use ! \method{walk()} as the iterator in a \code{for ... in} loop; each iteration returns the next subpart. ! Here's an example that prints the MIME type of every part of a message ! object tree: \begin{verbatim} >>> for part in msg.walk(): ! >>> print part.get_type('text/plain') multipart/report text/plain --- 442,484 ---- \end{methoddesc} + \begin{methoddesc}[Message]{get_content_charset}{\optional{failobj}} + Return the \code{charset} parameter of the \mailheader{Content-Type} + header. If there is no \mailheader{Content-Type} header, or if that + header has no \code{charset} parameter, \var{failobj} is returned. + + Note that this method differs from \method{get_charset()} which + returns the \class{Charset} instance for the default encoding of the + message body. + + \versionadded{2.2.2} + \end{methoddesc} + + \begin{methoddesc}[Message]{get_charsets}{\optional{failobj}} + Return a list containing the character set names in the message. If + the message is a \mimetype{multipart}, then the list will contain one + element for each subpart in the payload, otherwise, it will be a list + of length 1. + + Each item in the list will be a string which is the value of the + \code{charset} parameter in the \mailheader{Content-Type} header for the + represented subpart. However, if the subpart has no + \mailheader{Content-Type} header, no \code{charset} parameter, or is not of + the \mimetype{text} main MIME type, then that item in the returned list + will be \var{failobj}. + \end{methoddesc} + \begin{methoddesc}[Message]{walk}{} The \method{walk()} method is an all-purpose generator which can be used to iterate over all the parts and subparts of a message object tree, in depth-first traversal order. You will typically use ! \method{walk()} as the iterator in a \code{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: \begin{verbatim} >>> for part in msg.walk(): ! >>> print part.get_content_type() multipart/report text/plain *************** *** 381,385 **** is writing out the plain text representation of a MIME message, and it finds the message has a \var{preamble} attribute, it will write this ! text in the area between the headers and the first boundary. Note that if the message object has no preamble, the --- 508,513 ---- is writing out the plain text representation of a MIME message, and it finds the message has a \var{preamble} attribute, it will write this ! text in the area between the headers and the first boundary. See ! \refmodule{email.Parser} and \refmodule{email.Generator} for details. Note that if the message object has no preamble, the *************** *** 402,403 **** --- 530,587 ---- set the \var{epilogue} to the empty string. \end{datadesc} + + \subsubsection{Deprecated methods} + + The following methods are deprecated in \module{email} version 2. + They are documented here for completeness. + + \begin{methoddesc}[Message]{add_payload}{payload} + Add \var{payload} to the message object's existing payload. If, prior + to calling this method, the object's payload was \code{None} + (i.e. never before set), then after this method is called, the payload + will be the argument \var{payload}. + + If the object's payload was already a list + (i.e. \method{is_multipart()} returns 1), then \var{payload} is + appended to the end of the existing payload list. + + For any other type of existing payload, \method{add_payload()} will + transform the new payload into a list consisting of the old payload + and \var{payload}, but only if the document is already a MIME + multipart document. This condition is satisfied if the message's + \mailheader{Content-Type} header's main type is either + \mimetype{multipart}, or there is no \mailheader{Content-Type} + header. In any other situation, + \exception{MultipartConversionError} is raised. + + \deprecated{2.2.2}{Use the \method{attach()} method instead.} + \end{methoddesc} + + \begin{methoddesc}[Message]{get_type}{\optional{failobj}} + Return the message's content type, as a string of the form + \mimetype{maintype/subtype} as taken from the + \mailheader{Content-Type} header. + The returned string is coerced to lowercase. + + If there is no \mailheader{Content-Type} header in the message, + \var{failobj} is returned (defaults to \code{None}). + + \deprecated{2.2.2}{Use the \method{get_content_type()} method instead.} + \end{methoddesc} + + \begin{methoddesc}[Message]{get_main_type}{\optional{failobj}} + Return the message's \emph{main} content type. This essentially returns the + \var{maintype} part of the string returned by \method{get_type()}, with the + same semantics for \var{failobj}. + + \deprecated{2.2.2}{Use the \method{get_content_maintype()} method instead.} + \end{methoddesc} + + \begin{methoddesc}[Message]{get_subtype}{\optional{failobj}} + Return the message's sub-content type. This essentially returns the + \var{subtype} part of the string returned by \method{get_type()}, with the + same semantics for \var{failobj}. + + \deprecated{2.2.2}{Use the \method{get_content_subtype()} method instead.} + \end{methoddesc} + Index: emailparser.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailparser.tex,v retrieving revision 1.4.10.1 retrieving revision 1.4.10.2 diff -C2 -d -r1.4.10.1 -r1.4.10.2 *** emailparser.tex 22 Feb 2002 21:26:49 -0000 1.4.10.1 --- emailparser.tex 4 Oct 2002 17:24:23 -0000 1.4.10.2 *************** *** 1,9 **** \declaremodule{standard}{email.Parser} \modulesynopsis{Parse flat text email messages to produce a message ! object tree.} ! Message object trees can be created in one of two ways: they can be created from whole cloth by instantiating \class{Message} objects and ! stringing them together via \method{add_payload()} and \method{set_payload()} calls, or they can be created by parsing a flat text representation of the email message. --- 1,9 ---- \declaremodule{standard}{email.Parser} \modulesynopsis{Parse flat text email messages to produce a message ! object structure.} ! Message object structures can be created in one of two ways: they can be created from whole cloth by instantiating \class{Message} objects and ! stringing them together via \method{attach()} and \method{set_payload()} calls, or they can be created by parsing a flat text representation of the email message. *************** *** 12,19 **** most email document structures, including MIME documents. You can pass the parser a string or a file object, and the parser will return ! to you the root \class{Message} instance of the object tree. For simple, non-MIME messages the payload of this root object will likely be a string containing the text of the message. For MIME ! messages, the root object will return true from its \method{is_multipart()} method, and the subparts can be accessed via the \method{get_payload()} and \method{walk()} methods. --- 12,19 ---- most email document structures, including MIME documents. You can pass the parser a string or a file object, and the parser will return ! to you the root \class{Message} instance of the object structure. For simple, non-MIME messages the payload of this root object will likely be a string containing the text of the message. For MIME ! messages, the root object will return \code{True} from its \method{is_multipart()} method, and the subparts can be accessed via the \method{get_payload()} and \method{walk()} methods. *************** *** 28,43 **** headers and the payload of the message. In the case of \mimetype{multipart} messages, it will recursively parse the body of ! the container message. The \module{email.Parser} module also provides ! a second class, called \class{HeaderParser} which can be used if ! you're only interested in the headers of the message. ! \class{HeaderParser} can be much faster in this situations, since it ! does not attempt to parse the message body, instead setting the ! payload to the raw body as a string. \class{HeaderParser} has the ! same API as the \class{Parser} class. \subsubsection{Parser class API} ! \begin{classdesc}{Parser}{\optional{_class}} ! The constructor for the \class{Parser} class takes a single optional argument \var{_class}. This must be a callable factory (such as a function or a class), and it is used whenever a sub-message object --- 28,47 ---- headers and the payload of the message. In the case of \mimetype{multipart} messages, it will recursively parse the body of ! the container message. Two modes of parsing are supported, ! \emph{strict} parsing, which will usually reject any non-RFC compliant ! message, and \emph{lax} parsing, which attempts to adjust for common ! MIME formatting problems. ! ! The \module{email.Parser} module also provides a second class, called ! \class{HeaderParser} which can be used if you're only interested in ! the headers of the message. \class{HeaderParser} can be much faster in ! these situations, since it does not attempt to parse the message body, ! instead setting the payload to the raw body as a string. ! \class{HeaderParser} has the same API as the \class{Parser} class. \subsubsection{Parser class API} ! \begin{classdesc}{Parser}{\optional{_class\optional{, strict}}} ! The constructor for the \class{Parser} class takes an optional argument \var{_class}. This must be a callable factory (such as a function or a class), and it is used whenever a sub-message object *************** *** 45,53 **** \refmodule{email.Message}). The factory will be called without arguments. \end{classdesc} The other public \class{Parser} methods are: ! \begin{methoddesc}[Parser]{parse}{fp} Read all the data from the file-like object \var{fp}, parse the resulting text, and return the root message object. \var{fp} must --- 49,71 ---- \refmodule{email.Message}). The factory will be called without arguments. + + The optional \var{strict} flag specifies whether strict or lax parsing + should be performed. Normally, when things like MIME terminating + boundaries are missing, or when messages contain other formatting + problems, the \class{Parser} will raise a + \exception{MessageParseError}. However, when lax parsing is enabled, + the \class{Parser} will attempt to work around such broken formatting + to produce a usable message structure (this doesn't mean + \exception{MessageParseError}s are never raised; some ill-formatted + messages just can't be parsed). The \var{strict} flag defaults to + \code{False} since lax parsing usually provides the most convenient + behavior. + + \versionchanged[The \var{strict} flag was added]{2.2.2} \end{classdesc} The other public \class{Parser} methods are: ! \begin{methoddesc}[Parser]{parse}{fp\optional{, headersonly}} Read all the data from the file-like object \var{fp}, parse the resulting text, and return the root message object. \var{fp} must *************** *** 56,86 **** The text contained in \var{fp} must be formatted as a block of \rfc{2822} ! style headers and header continuation lines, optionally preceeded by a ! \emph{Unix-From} header. The header block is terminated either by the end of the data or by a blank line. Following the header block is the body of the message (which may contain MIME-encoded subparts). \end{methoddesc} ! \begin{methoddesc}[Parser]{parsestr}{text} Similar to the \method{parse()} method, except it takes a string object instead of a file-like object. Calling this method on a string is exactly equivalent to wrapping \var{text} in a \class{StringIO} instance first and calling \method{parse()}. \end{methoddesc} ! Since creating a message object tree from a string or a file object is ! such a common task, two functions are provided as a convenience. They ! are available in the top-level \module{email} package namespace. ! \begin{funcdesc}{message_from_string}{s\optional{, _class}} ! Return a message object tree from a string. This is exactly ! equivalent to \code{Parser().parsestr(s)}. Optional \var{_class} is ! interpreted as with the \class{Parser} class constructor. \end{funcdesc} ! \begin{funcdesc}{message_from_file}{fp\optional{, _class}} ! Return a message object tree from an open file object. This is exactly ! equivalent to \code{Parser().parse(fp)}. Optional \var{_class} is ! interpreted as with the \class{Parser} class constructor. \end{funcdesc} --- 74,120 ---- The text contained in \var{fp} must be formatted as a block of \rfc{2822} ! style headers and header continuation lines, optionally preceded by a ! envelope header. The header block is terminated either by the end of the data or by a blank line. Following the header block is the body of the message (which may contain MIME-encoded subparts). + + Optional \var{headersonly} is as with the \method{parse()} method. + + \versionchanged[The \var{headersonly} flag was added]{2.2.2} \end{methoddesc} ! \begin{methoddesc}[Parser]{parsestr}{text\optional{, headersonly}} Similar to the \method{parse()} method, except it takes a string object instead of a file-like object. Calling this method on a string is exactly equivalent to wrapping \var{text} in a \class{StringIO} instance first and calling \method{parse()}. + + Optional \var{headersonly} is a flag specifying whether to stop + parsing after reading the headers or not. The default is \code{False}, + meaning it parses the entire contents of the file. + + \versionchanged[The \var{headersonly} flag was added]{2.2.2} \end{methoddesc} ! Since creating a message object structure from a string or a file ! object is such a common task, two functions are provided as a ! convenience. They are available in the top-level \module{email} ! package namespace. ! \begin{funcdesc}{message_from_string}{s\optional{, _class\optional{, strict}}} ! Return a message object structure from a string. This is exactly ! equivalent to \code{Parser().parsestr(s)}. Optional \var{_class} and ! \var{strict} are interpreted as with the \class{Parser} class constructor. ! ! \versionchanged[The \var{strict} flag was added]{2.2.2} \end{funcdesc} ! \begin{funcdesc}{message_from_file}{fp\optional{, _class\optional{, strict}}} ! Return a message object structure tree from an open file object. This ! is exactly equivalent to \code{Parser().parse(fp)}. Optional ! \var{_class} and \var{strict} are interpreted as with the ! \class{Parser} class constructor. ! ! \versionchanged[The \var{strict} flag was added]{2.2.2} \end{funcdesc} *************** *** 100,113 **** \item Most non-\mimetype{multipart} type messages are parsed as a single message object with a string payload. These objects will return ! 0 for \method{is_multipart()}. ! \item One exception is for \mimetype{message/delivery-status} type ! messages. Because the body of such messages consist of ! blocks of headers, \class{Parser} will create a non-multipart ! object containing non-multipart subobjects for each header ! block. ! \item Another exception is for \mimetype{message/*} types (more ! general than \mimetype{message/delivery-status}). These are ! typically \mimetype{message/rfc822} messages, represented as a ! non-multipart object containing a singleton payload which is ! another non-multipart \class{Message} instance. \end{itemize} --- 134,152 ---- \item Most non-\mimetype{multipart} type messages are parsed as a single message object with a string payload. These objects will return ! \code{False} for \method{is_multipart()}. Their ! \method{get_payload()} method will return a string object. ! ! \item All \mimetype{multipart} type messages will be parsed as a ! container message object with a list of sub-message objects for ! their payload. The outer container message will return ! \code{True} for \method{is_multipart()} and their ! \method{get_payload()} method will return the list of ! \class{Message} subparts. ! ! \item Most messages with a content type of \mimetype{message/*} ! (e.g. \mimetype{message/deliver-status} and ! \mimetype{message/rfc822}) will also be parsed as container ! object containing a list payload of length 1. Their ! \method{is_multipart()} method will return \code{True}. The ! single element in the list payload will be a sub-message object. \end{itemize} Index: emailutil.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailutil.tex,v retrieving revision 1.5.8.1 retrieving revision 1.5.8.2 diff -C2 -d -r1.5.8.1 -r1.5.8.2 *** emailutil.tex 23 Aug 2002 16:08:38 -0000 1.5.8.1 --- emailutil.tex 4 Oct 2002 17:24:23 -0000 1.5.8.2 *************** *** 7,11 **** \begin{funcdesc}{quote}{str} Return a new string with backslashes in \var{str} replaced by two ! backslashes and double quotes replaced by backslash-double quote. \end{funcdesc} --- 7,11 ---- \begin{funcdesc}{quote}{str} Return a new string with backslashes in \var{str} replaced by two ! backslashes, and double quotes replaced by backslash-double quote. \end{funcdesc} *************** *** 22,29 **** \emph{realname} and \emph{email address} parts. Returns a tuple of that information, unless the parse fails, in which case a 2-tuple of ! \code{(None, None)} is returned. \end{funcdesc} ! \begin{funcdesc}{dump_address_pair}{pair} The inverse of \method{parseaddr()}, this takes a 2-tuple of the form \code{(realname, email_address)} and returns the string value suitable --- 22,29 ---- \emph{realname} and \emph{email address} parts. Returns a tuple of that information, unless the parse fails, in which case a 2-tuple of ! \code{('', '')} is returned. \end{funcdesc} ! \begin{funcdesc}{formataddr}{pair} The inverse of \method{parseaddr()}, this takes a 2-tuple of the form \code{(realname, email_address)} and returns the string value suitable *************** *** 49,73 **** \end{funcdesc} - \begin{funcdesc}{decode}{s} - This method decodes a string according to the rules in \rfc{2047}. It - returns the decoded string as a Python unicode string. - \end{funcdesc} - - \begin{funcdesc}{encode}{s\optional{, charset\optional{, encoding}}} - This method encodes a string according to the rules in \rfc{2047}. It - is not actually the inverse of \function{decode()} since it doesn't - handle multiple character sets or multiple string parts needing - encoding. In fact, the input string \var{s} must already be encoded - in the \var{charset} character set (Python can't reliably guess what - character set a string might be encoded in). The default - \var{charset} is \samp{iso-8859-1}. - - \var{encoding} must be either the letter \character{q} for - Quoted-Printable or \character{b} for Base64 encoding. If - neither, a \exception{ValueError} is raised. Both the \var{charset} and - the \var{encoding} strings are case-insensitive, and coerced to lower - case in the returned string. - \end{funcdesc} - \begin{funcdesc}{parsedate}{date} Attempts to parse a date according to the rules in \rfc{2822}. --- 49,52 ---- *************** *** 107,111 **** \begin{funcdesc}{formatdate}{\optional{timeval\optional{, localtime}}} ! Returns a date string as per Internet standard \rfc{2822}, e.g.: \begin{verbatim} --- 86,90 ---- \begin{funcdesc}{formatdate}{\optional{timeval\optional{, localtime}}} ! Returns a date string as per \rfc{2822}, e.g.: \begin{verbatim} *************** *** 117,122 **** otherwise the current time is used. ! Optional \var{localtime} is a flag that when true, interprets \var{timeval}, and returns a date relative to the local timezone instead of UTC, properly taking daylight savings time into account. \end{funcdesc} --- 96,142 ---- otherwise the current time is used. ! Optional \var{localtime} is a flag that when \code{True}, interprets \var{timeval}, and returns a date relative to the local timezone instead of UTC, properly taking daylight savings time into account. + The default is \code{False} meaning UTC is used. + \end{funcdesc} + + \begin{funcdesc}{make_msgid}{\optional{idstring}} + Returns a string suitable for an \rfc{2822}-compliant + \mailheader{Message-ID} header. Optional \var{idstring} if given, is + a string used to strengthen the uniqueness of the message id. + \end{funcdesc} + + \begin{funcdesc}{decode_rfc2231}{s} + Decode the string \var{s} according to \rfc{2231}. + \end{funcdesc} + + \begin{funcdesc}{encode_rfc2231}{s\optional{, charset\optional{, language}}} + Encode the string \var{s} according to \rfc{2231}. Optional + \var{charset} and \var{language}, if given is the character set name + and language name to use. If neither is given, \var{s} is returned + as-is. If \var{charset} is given but \var{language} is not, the + string is encoded using the empty string for \var{language}. + \end{funcdesc} + + \begin{funcdesc}{decode_params}{params} + Decode parameters list according to \rfc{2231}. \var{params} is a + sequence of 2-tuples containing elements of the form + \code{(content-type, string-value)}. + \end{funcdesc} + + The following functions have been deprecated: + + \begin{funcdesc}{dump_address_pair}{pair} + \deprecated{2.2.2}{Use \function{formataddr()} instead.} + \end{funcdesc} + + \begin{funcdesc}{decode}{s} + \deprecated{2.2.2}{Use \method{Header.decode_header()} instead.} \end{funcdesc} + + + \begin{funcdesc}{encode}{s\optional{, charset\optional{, encoding}}} + \deprecated{2.2.2}{Use \method{Header.encode()} instead.} + \end{funcdesc} + From barry@users.sourceforge.net Fri Oct 4 18:24:26 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Fri, 04 Oct 2002 10:24:26 -0700 Subject: [Python-checkins] python/dist/src/Lib/email Charset.py,NONE,1.7.2.1 Header.py,NONE,1.13.2.1 MIMEMultipart.py,NONE,1.3.2.1 MIMENonMultipart.py,NONE,1.2.2.1 _compat21.py,NONE,1.4.2.1 _compat22.py,NONE,1.4.2.1 base64MIME.py,NONE,1.5.2.1 quopriMIME.py,NONE,1.4.2.1 Encoders.py,1.4,1.4.10.1 Errors.py,1.3,1.3.10.1 Generator.py,1.6.10.1,1.6.10.2 Iterators.py,1.5,1.5.10.1 MIMEAudio.py,1.2,1.2.6.1 MIMEBase.py,1.4,1.4.10.1 MIMEImage.py,1.3,1.3.10.1 MIMEMessage.py,1.3,1.3.10.1 MIMEText.py,1.3,1.3.10.1 Message.py,1.9,1.9.6.1 Parser.py,1.5.10.1,1.5.10.2 Utils.py,1.9,1.9.6.1 __init__.py,1.4,1.4.10.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv11766/Lib/email Modified Files: Tag: release22-maint Encoders.py Errors.py Generator.py Iterators.py MIMEAudio.py MIMEBase.py MIMEImage.py MIMEMessage.py MIMEText.py Message.py Parser.py Utils.py __init__.py Added Files: Tag: release22-maint Charset.py Header.py MIMEMultipart.py MIMENonMultipart.py _compat21.py _compat22.py base64MIME.py quopriMIME.py Log Message: Backporting of email 2.4 from Python 2.3. Many newly added modules, some updated modules, updated documentation, and updated tests. Note that Lib/test/regrtest.py added test_email_codecs to the expected skips for all platforms. Also note that test_email_codecs.py differs slightly from its Python 2.3 counterpart due to the difference in package location for TestSkipped. --- NEW FILE: Charset.py --- # Copyright (C) 2001,2002 Python Software Foundation # Author: che@debian.org (Ben Gertzfield), barry@zope.com (Barry Warsaw) from types import UnicodeType from email.Encoders import encode_7or8bit import email.base64MIME import email.quopriMIME def _isunicode(s): return isinstance(s, UnicodeType) # Python 2.2.1 and beyond has these symbols try: True, False except NameError: True = 1 False = 0 # Flags for types of header encodings QP = 1 # Quoted-Printable BASE64 = 2 # Base64 SHORTEST = 3 # the shorter of QP and base64, but only for headers # In "=?charset?q?hello_world?=", the =?, ?q?, and ?= add up to 7 MISC_LEN = 7 DEFAULT_CHARSET = 'us-ascii' # Defaults CHARSETS = { # input header enc body enc output conv 'iso-8859-1': (QP, QP, None), 'iso-8859-2': (QP, QP, None), 'us-ascii': (None, None, None), 'big5': (BASE64, BASE64, None), 'gb2312': (BASE64, BASE64, None), 'euc-jp': (BASE64, None, 'iso-2022-jp'), 'shift_jis': (BASE64, None, 'iso-2022-jp'), 'iso-2022-jp': (BASE64, None, None), 'koi8-r': (BASE64, BASE64, None), 'utf-8': (SHORTEST, BASE64, 'utf-8'), } # Aliases for other commonly-used names for character sets. Map # them to the real ones used in email. ALIASES = { 'latin_1': 'iso-8859-1', 'latin-1': 'iso-8859-1', 'ascii': 'us-ascii', } # Map charsets to their Unicode codec strings. Note that the Japanese # examples included below do not (yet) come with Python! They are available # from http://pseudo.grad.sccs.chukyo-u.ac.jp/~kajiyama/python/ # The Chinese and Korean codecs are available from SourceForge: # # http://sourceforge.net/projects/python-codecs/ # # although you'll need to check them out of cvs since they haven't been file # released yet. You might also try to use # # http://www.freshports.org/port-description.php3?port=6702 # # if you can get logged in. AFAICT, both the Chinese and Korean codecs are # fairly experimental at this point. CODEC_MAP = { 'euc-jp': 'japanese.euc-jp', 'iso-2022-jp': 'japanese.iso-2022-jp', 'shift_jis': 'japanese.shift_jis', 'gb2132': 'eucgb2312_cn', 'big5': 'big5_tw', 'utf-8': 'utf-8', # Hack: We don't want *any* conversion for stuff marked us-ascii, as all # sorts of garbage might be sent to us in the guise of 7-bit us-ascii. # Let that stuff pass through without conversion to/from Unicode. 'us-ascii': None, } # Convenience functions for extending the above mappings def add_charset(charset, header_enc=None, body_enc=None, output_charset=None): """Add character set properties to the global registry. charset is the input character set, and must be the canonical name of a character set. Optional header_enc and body_enc is either Charset.QP for quoted-printable, Charset.BASE64 for base64 encoding, Charset.SHORTEST for the shortest of qp or base64 encoding, or None for no encoding. SHORTEST is only valid for header_enc. It describes how message headers and message bodies in the input charset are to be encoded. Default is no encoding. Optional output_charset is the character set that the output should be in. Conversions will proceed from input charset, to Unicode, to the output charset when the method Charset.convert() is called. The default is to output in the same character set as the input. Both input_charset and output_charset must have Unicode codec entries in the module's charset-to-codec mapping; use add_codec(charset, codecname) to add codecs the module does not know about. See the codecs module's documentation for more information. """ if body_enc == SHORTEST: raise ValueError, 'SHORTEST not allowed for body_enc' CHARSETS[charset] = (header_enc, body_enc, output_charset) def add_alias(alias, canonical): """Add a character set alias. alias is the alias name, e.g. latin-1 canonical is the character set's canonical name, e.g. iso-8859-1 """ ALIASES[alias] = canonical def add_codec(charset, codecname): """Add a codec that map characters in the given charset to/from Unicode. charset is the canonical name of a character set. codecname is the name of a Python codec, as appropriate for the second argument to the unicode() built-in, or to the encode() method of a Unicode string. """ CODEC_MAP[charset] = codecname class Charset: """Map character sets to their email properties. This class provides information about the requirements imposed on email for a specific character set. It also provides convenience routines for converting between character sets, given the availability of the applicable codecs. Given a character set, it will do its best to provide information on how to use that character set in an email in an RFC-compliant way. Certain character sets must be encoded with quoted-printable or base64 when used in email headers or bodies. Certain character sets must be converted outright, and are not allowed in email. Instances of this module expose the following information about a character set: input_charset: The initial character set specified. Common aliases are converted to their `official' email names (e.g. latin_1 is converted to iso-8859-1). Defaults to 7-bit us-ascii. header_encoding: If the character set must be encoded before it can be used in an email header, this attribute will be set to Charset.QP (for quoted-printable), Charset.BASE64 (for base64 encoding), or Charset.SHORTEST for the shortest of QP or BASE64 encoding. Otherwise, it will be None. body_encoding: Same as header_encoding, but describes the encoding for the mail message's body, which indeed may be different than the header encoding. Charset.SHORTEST is not allowed for body_encoding. output_charset: Some character sets must be converted before the can be used in email headers or bodies. If the input_charset is one of them, this attribute will contain the name of the charset output will be converted to. Otherwise, it will be None. input_codec: The name of the Python codec used to convert the input_charset to Unicode. If no conversion codec is necessary, this attribute will be None. output_codec: The name of the Python codec used to convert Unicode to the output_charset. If no conversion codec is necessary, this attribute will have the same value as the input_codec. """ def __init__(self, input_charset=DEFAULT_CHARSET): # Set the input charset after filtering through the aliases self.input_charset = ALIASES.get(input_charset, input_charset) # We can try to guess which encoding and conversion to use by the # charset_map dictionary. Try that first, but let the user override # it. henc, benc, conv = CHARSETS.get(self.input_charset, (SHORTEST, SHORTEST, None)) # Set the attributes, allowing the arguments to override the default. self.header_encoding = henc self.body_encoding = benc self.output_charset = ALIASES.get(conv, conv) # Now set the codecs. If one isn't defined for input_charset, # guess and try a Unicode codec with the same name as input_codec. self.input_codec = CODEC_MAP.get(self.input_charset, self.input_charset) self.output_codec = CODEC_MAP.get(self.output_charset, self.input_codec) def __str__(self): return self.input_charset.lower() def __eq__(self, other): return str(self) == str(other).lower() def __ne__(self, other): return not self.__eq__(other) def get_body_encoding(self): """Return the content-transfer-encoding used for body encoding. This is either the string `quoted-printable' or `base64' depending on the encoding used, or it is a function in which case you should call the function with a single argument, the Message object being encoded. The function should then set the Content-Transfer-Encoding header itself to whatever is appropriate. Returns "quoted-printable" if self.body_encoding is QP. Returns "base64" if self.body_encoding is BASE64. Returns "7bit" otherwise. """ assert self.body_encoding <> SHORTEST if self.body_encoding == QP: return 'quoted-printable' elif self.body_encoding == BASE64: return 'base64' else: return encode_7or8bit def convert(self, s): """Convert a string from the input_codec to the output_codec.""" if self.input_codec <> self.output_codec: return unicode(s, self.input_codec).encode(self.output_codec) else: return s def to_splittable(self, s): """Convert a possibly multibyte string to a safely splittable format. Uses the input_codec to try and convert the string to Unicode, so it can be safely split on character boundaries (even for multibyte characters). Returns the string as-is if it isn't known how to convert it to Unicode with the input_charset. Characters that could not be converted to Unicode will be replaced with the Unicode replacement character U+FFFD. """ if _isunicode(s) or self.input_codec is None: return s try: return unicode(s, self.input_codec, 'replace') except LookupError: # Input codec not installed on system, so return the original # string unchanged. return s def from_splittable(self, ustr, to_output=True): """Convert a splittable string back into an encoded string. Uses the proper codec to try and convert the string from Unicode back into an encoded format. Return the string as-is if it is not Unicode, or if it could not be converted from Unicode. Characters that could not be converted from Unicode will be replaced with an appropriate character (usually '?'). If to_output is True (the default), uses output_codec to convert to an encoded format. If to_output is False, uses input_codec. """ if to_output: codec = self.output_codec else: codec = self.input_codec if not _isunicode(ustr) or codec is None: return ustr try: return ustr.encode(codec, 'replace') except LookupError: # Output codec not installed return ustr def get_output_charset(self): """Return the output character set. This is self.output_charset if that is not None, otherwise it is self.input_charset. """ return self.output_charset or self.input_charset def encoded_header_len(self, s): """Return the length of the encoded header string.""" cset = self.get_output_charset() # The len(s) of a 7bit encoding is len(s) if self.header_encoding == BASE64: return email.base64MIME.base64_len(s) + len(cset) + MISC_LEN elif self.header_encoding == QP: return email.quopriMIME.header_quopri_len(s) + len(cset) + MISC_LEN elif self.header_encoding == SHORTEST: lenb64 = email.base64MIME.base64_len(s) lenqp = email.quopriMIME.header_quopri_len(s) return min(lenb64, lenqp) + len(cset) + MISC_LEN else: return len(s) def header_encode(self, s, convert=False): """Header-encode a string, optionally converting it to output_charset. If convert is True, the string will be converted from the input charset to the output charset automatically. This is not useful for multibyte character sets, which have line length issues (multibyte characters must be split on a character, not a byte boundary); use the high-level Header class to deal with these issues. convert defaults to False. The type of encoding (base64 or quoted-printable) will be based on self.header_encoding. """ cset = self.get_output_charset() if convert: s = self.convert(s) # 7bit/8bit encodings return the string unchanged (modulo conversions) if self.header_encoding == BASE64: return email.base64MIME.header_encode(s, cset) elif self.header_encoding == QP: return email.quopriMIME.header_encode(s, cset) elif self.header_encoding == SHORTEST: lenb64 = email.base64MIME.base64_len(s) lenqp = email.quopriMIME.header_quopri_len(s) if lenb64 < lenqp: return email.base64MIME.header_encode(s, cset) else: return email.quopriMIME.header_encode(s, cset) else: return s def body_encode(self, s, convert=True): """Body-encode a string and convert it to output_charset. If convert is True (the default), the string will be converted from the input charset to output charset automatically. Unlike header_encode(), there are no issues with byte boundaries and multibyte charsets in email bodies, so this is usually pretty safe. The type of encoding (base64 or quoted-printable) will be based on self.body_encoding. """ if convert: s = self.convert(s) # 7bit/8bit encodings return the string unchanged (module conversions) if self.body_encoding is BASE64: return email.base64MIME.body_encode(s) elif self.header_encoding is QP: return email.quopriMIME.body_encode(s) else: return s --- NEW FILE: Header.py --- # Copyright (C) 2002 Python Software Foundation # Author: che@debian.org (Ben Gertzfield), barry@zope.com (Barry Warsaw) """Header encoding and decoding functionality.""" import re from types import StringType, UnicodeType import email.quopriMIME import email.base64MIME from email.Charset import Charset try: from email._compat22 import _floordiv except SyntaxError: # Python 2.1 spells integer division differently from email._compat21 import _floordiv try: True, False except NameError: True = 1 False = 0 CRLFSPACE = '\r\n ' CRLF = '\r\n' NL = '\n' SPACE8 = ' ' * 8 EMPTYSTRING = '' MAXLINELEN = 76 ENCODE = 1 DECODE = 2 USASCII = Charset('us-ascii') UTF8 = Charset('utf-8') # Match encoded-word strings in the form =?charset?q?Hello_World?= ecre = re.compile(r''' =\? # literal =? (?P[^?]*?) # non-greedy up to the next ? is the charset \? # literal ? (?P[qb]) # either a "q" or a "b", case insensitive \? # literal ? (?P.*?) # non-greedy up to the next ?= is the encoded string \?= # literal ?= ''', re.VERBOSE | re.IGNORECASE) # Helpers _max_append = email.quopriMIME._max_append def decode_header(header): """Decode a message header value without converting charset. Returns a list of (decoded_string, charset) pairs containing each of the decoded parts of the header. Charset is None for non-encoded parts of the header, otherwise a lower-case string containing the name of the character set specified in the encoded string. """ # If no encoding, just return the header header = str(header) if not ecre.search(header): return [(header, None)] decoded = [] dec = '' for line in header.splitlines(): # This line might not have an encoding in it if not ecre.search(line): decoded.append((line, None)) continue parts = ecre.split(line) while parts: unenc = parts.pop(0).strip() if unenc: # Should we continue a long line? if decoded and decoded[-1][1] is None: decoded[-1] = (decoded[-1][0] + dec, None) else: decoded.append((unenc, None)) if parts: charset, encoding = [s.lower() for s in parts[0:2]] encoded = parts[2] dec = '' if encoding == 'q': dec = email.quopriMIME.header_decode(encoded) elif encoding == 'b': dec = email.base64MIME.decode(encoded) else: dec = encoded if decoded and decoded[-1][1] == charset: decoded[-1] = (decoded[-1][0] + dec, decoded[-1][1]) else: decoded.append((dec, charset)) del parts[0:3] return decoded def make_header(decoded_seq, maxlinelen=None, header_name=None, continuation_ws=' '): """Create a Header from a sequence of pairs as returned by decode_header() decode_header() takes a header value string and returns a sequence of pairs of the format (decoded_string, charset) where charset is the string name of the character set. This function takes one of those sequence of pairs and returns a Header instance. Optional maxlinelen, header_name, and continuation_ws are as in the Header constructor. """ h = Header(maxlinelen=maxlinelen, header_name=header_name, continuation_ws=continuation_ws) for s, charset in decoded_seq: # None means us-ascii but we can simply pass it on to h.append() if charset is not None and not isinstance(charset, Charset): charset = Charset(charset) h.append(s, charset) return h class Header: def __init__(self, s=None, charset=None, maxlinelen=None, header_name=None, continuation_ws=' '): """Create a MIME-compliant header that can contain many character sets. Optional s is the initial header value. If None, the initial header value is not set. You can later append to the header with .append() method calls. s may be a byte string or a Unicode string, but see the .append() documentation for semantics. Optional charset serves two purposes: it has the same meaning as the charset argument to the .append() method. It also sets the default character set for all subsequent .append() calls that omit the charset argument. If charset is not provided in the constructor, the us-ascii charset is used both as s's initial charset and as the default for subsequent .append() calls. The maximum line length can be specified explicit via maxlinelen. For splitting the first line to a shorter value (to account for the field header which isn't included in s, e.g. `Subject') pass in the name of the field in header_name. The default maxlinelen is 76. continuation_ws must be RFC 2822 compliant folding whitespace (usually either a space or a hard tab) which will be prepended to continuation lines. """ if charset is None: charset = USASCII self._charset = charset self._continuation_ws = continuation_ws cws_expanded_len = len(continuation_ws.replace('\t', SPACE8)) # BAW: I believe `chunks' and `maxlinelen' should be non-public. self._chunks = [] if s is not None: self.append(s, charset) if maxlinelen is None: maxlinelen = MAXLINELEN if header_name is None: # We don't know anything about the field header so the first line # is the same length as subsequent lines. self._firstlinelen = maxlinelen else: # The first line should be shorter to take into account the field # header. Also subtract off 2 extra for the colon and space. self._firstlinelen = maxlinelen - len(header_name) - 2 # Second and subsequent lines should subtract off the length in # columns of the continuation whitespace prefix. self._maxlinelen = maxlinelen - cws_expanded_len def __str__(self): """A synonym for self.encode().""" return self.encode() def __unicode__(self): """Helper for the built-in unicode function.""" # charset item is a Charset instance so we need to stringify it. uchunks = [unicode(s, str(charset)) for s, charset in self._chunks] return u''.join(uchunks) # Rich comparison operators for equality only. BAW: does it make sense to # have or explicitly disable <, <=, >, >= operators? def __eq__(self, other): # other may be a Header or a string. Both are fine so coerce # ourselves to a string, swap the args and do another comparison. return other == self.encode() def __ne__(self, other): return not self == other def append(self, s, charset=None): """Append a string to the MIME header. Optional charset, if given, should be a Charset instance or the name of a character set (which will be converted to a Charset instance). A value of None (the default) means that the charset given in the constructor is used. s may be a byte string or a Unicode string. If it is a byte string (i.e. isinstance(s, StringType) is true), then charset is the encoding of that byte string, and a UnicodeError will be raised if the string cannot be decoded with that charset. If s is a Unicode string, then charset is a hint specifying the character set of the characters in the string. In this case, when producing an RFC 2822 compliant header using RFC 2047 rules, the Unicode string will be encoded using the following charsets in order: us-ascii, the charset hint, utf-8. The first character set not to provoke a UnicodeError is used. """ if charset is None: charset = self._charset elif not isinstance(charset, Charset): charset = Charset(charset) # Normalize and check the string if isinstance(s, StringType): # Possibly raise UnicodeError if it can't e encoded unicode(s, charset.get_output_charset()) elif isinstance(s, UnicodeType): # Convert Unicode to byte string for later concatenation for charset in USASCII, charset, UTF8: try: s = s.encode(charset.get_output_charset()) break except UnicodeError: pass else: assert False, 'Could not encode to utf-8' self._chunks.append((s, charset)) def _split(self, s, charset, firstline=False): # Split up a header safely for use with encode_chunks. BAW: this # appears to be a private convenience method. splittable = charset.to_splittable(s) encoded = charset.from_splittable(splittable) elen = charset.encoded_header_len(encoded) if elen <= self._maxlinelen: return [(encoded, charset)] # BAW: I'm not sure what the right test here is. What we're trying to # do is be faithful to RFC 2822's recommendation that ($2.2.3): # # "Note: Though structured field bodies are defined in such a way that # folding can take place between many of the lexical tokens (and even # within some of the lexical tokens), folding SHOULD be limited to # placing the CRLF at higher-level syntactic breaks." # # For now, I can only imagine doing this when the charset is us-ascii, # although it's possible that other charsets may also benefit from the # higher-level syntactic breaks. # elif charset == 'us-ascii': return self._ascii_split(s, charset, firstline) # BAW: should we use encoded? elif elen == len(s): # We can split on _maxlinelen boundaries because we know that the # encoding won't change the size of the string splitpnt = self._maxlinelen first = charset.from_splittable(splittable[:splitpnt], False) last = charset.from_splittable(splittable[splitpnt:], False) else: # Divide and conquer. halfway = _floordiv(len(splittable), 2) first = charset.from_splittable(splittable[:halfway], False) last = charset.from_splittable(splittable[halfway:], False) # Do the split return self._split(first, charset, firstline) + \ self._split(last, charset) def _ascii_split(self, s, charset, firstline): # Attempt to split the line at the highest-level syntactic break # possible. Note that we don't have a lot of smarts about field # syntax; we just try to break on semi-colons, then whitespace. rtn = [] lines = s.splitlines() while lines: line = lines.pop(0) if firstline: maxlinelen = self._firstlinelen firstline = False else: #line = line.lstrip() maxlinelen = self._maxlinelen # Short lines can remain unchanged if len(line.replace('\t', SPACE8)) <= maxlinelen: rtn.append(line) else: oldlen = len(line) # Try to break the line on semicolons, but if that doesn't # work, try to split on folding whitespace. while len(line) > maxlinelen: i = line.rfind(';', 0, maxlinelen) if i < 0: break rtn.append(line[:i] + ';') line = line[i+1:] # Is the remaining stuff still longer than maxlinelen? if len(line) <= maxlinelen: # Splitting on semis worked rtn.append(line) continue # Splitting on semis didn't finish the job. If it did any # work at all, stick the remaining junk on the front of the # `lines' sequence and let the next pass do its thing. if len(line) <> oldlen: lines.insert(0, line) continue # Otherwise, splitting on semis didn't help at all. parts = re.split(r'(\s+)', line) if len(parts) == 1 or (len(parts) == 3 and parts[0].endswith(':')): # This line can't be split on whitespace. There's now # little we can do to get this into maxlinelen. BAW: # We're still potentially breaking the RFC by possibly # allowing lines longer than the absolute maximum of 998 # characters. For now, let it slide. # # len(parts) will be 1 if this line has no `Field: ' # prefix, otherwise it will be len(3). rtn.append(line) continue # There is whitespace we can split on. first = parts.pop(0) sublines = [first] acc = len(first) while parts: len0 = len(parts[0]) len1 = len(parts[1]) if acc + len0 + len1 <= maxlinelen: sublines.append(parts.pop(0)) sublines.append(parts.pop(0)) acc += len0 + len1 else: # Split it here, but don't forget to ignore the # next whitespace-only part if first <> '': rtn.append(EMPTYSTRING.join(sublines)) del parts[0] first = parts.pop(0) sublines = [first] acc = len(first) rtn.append(EMPTYSTRING.join(sublines)) return [(chunk, charset) for chunk in rtn] def _encode_chunks(self): """MIME-encode a header with many different charsets and/or encodings. Given a list of pairs (string, charset), return a MIME-encoded string suitable for use in a header field. Each pair may have different charsets and/or encodings, and the resulting header will accurately reflect each setting. Each encoding can be email.Utils.QP (quoted-printable, for ASCII-like character sets like iso-8859-1), email.Utils.BASE64 (Base64, for non-ASCII like character sets like KOI8-R and iso-2022-jp), or None (no encoding). Each pair will be represented on a separate line; the resulting string will be in the format: "=?charset1?q?Mar=EDa_Gonz=E1lez_Alonso?=\n =?charset2?b?SvxyZ2VuIEL2aW5n?=" """ chunks = [] for header, charset in self._chunks: if charset is None or charset.header_encoding is None: # There's no encoding for this chunk's charsets _max_append(chunks, header, self._maxlinelen) else: _max_append(chunks, charset.header_encode(header), self._maxlinelen, ' ') joiner = NL + self._continuation_ws return joiner.join(chunks) def encode(self): """Encode a message header into an RFC-compliant format. There are many issues involved in converting a given string for use in an email header. Only certain character sets are readable in most email clients, and as header strings can only contain a subset of 7-bit ASCII, care must be taken to properly convert and encode (with Base64 or quoted-printable) header strings. In addition, there is a 75-character length limit on any given encoded header field, so line-wrapping must be performed, even with double-byte character sets. This method will do its best to convert the string to the correct character set used in email, and encode and line wrap it safely with the appropriate scheme for that character set. If the given charset is not known or an error occurs during conversion, this function will return the header untouched. """ newchunks = [] for s, charset in self._chunks: newchunks += self._split(s, charset, True) self._chunks = newchunks return self._encode_chunks() --- NEW FILE: MIMEMultipart.py --- # Copyright (C) 2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) """Base class for MIME multipart/* type messages. """ from email import MIMEBase class MIMEMultipart(MIMEBase.MIMEBase): """Base class for MIME multipart/* type messages.""" def __init__(self, _subtype='mixed', boundary=None, *_subparts, **_params): """Creates a multipart/* type message. By default, creates a multipart/mixed message, with proper Content-Type and MIME-Version headers. _subtype is the subtype of the multipart content type, defaulting to `mixed'. boundary is the multipart boundary string. By default it is calculated as needed. _subparts is a sequence of initial subparts for the payload. It must be possible to convert this sequence to a list. You can always attach new subparts to the message by using the attach() method. Additional parameters for the Content-Type header are taken from the keyword arguments (or passed into the _params argument). """ MIMEBase.MIMEBase.__init__(self, 'multipart', _subtype, **_params) if _subparts: self.attach(*list(_subparts)) if boundary: self.set_boundary(boundary) --- NEW FILE: MIMENonMultipart.py --- # Copyright (C) 2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) """Base class for MIME type messages that are not multipart. """ from email import Errors from email import MIMEBase class MIMENonMultipart(MIMEBase.MIMEBase): """Base class for MIME multipart/* type messages.""" __pychecker__ = 'unusednames=payload' def attach(self, payload): # The public API prohibits attaching multiple subparts to MIMEBase # derived subtypes since none of them are, by definition, of content # type multipart/* raise Errors.MultipartConversionError( 'Cannot attach additional subparts to non-multipart/*') del __pychecker__ --- NEW FILE: _compat21.py --- # Copyright (C) 2002 Python Software Foundation # Author: barry@zope.com """Module containing compatibility functions for Python 2.1. """ from cStringIO import StringIO from types import StringType, UnicodeType # This function will become a method of the Message class def walk(self): """Walk over the message tree, yielding each subpart. The walk is performed in depth-first order. This method is a generator. """ parts = [] parts.append(self) if self.is_multipart(): for subpart in self.get_payload(): parts.extend(subpart.walk()) return parts # Python 2.2 spells floor division // def _floordiv(i, j): """Do a floor division, i/j.""" return i / j def _isstring(obj): return isinstance(obj, StringType) or isinstance(obj, UnicodeType) # These two functions are imported into the Iterators.py interface module. # The Python 2.2 version uses generators for efficiency. def body_line_iterator(msg): """Iterate over the parts, returning string payloads line-by-line.""" lines = [] for subpart in msg.walk(): payload = subpart.get_payload() if _isstring(payload): for line in StringIO(payload).readlines(): lines.append(line) return lines def typed_subpart_iterator(msg, maintype='text', subtype=None): """Iterate over the subparts with a given MIME type. Use `maintype' as the main MIME type to match against; this defaults to "text". Optional `subtype' is the MIME subtype to match against; if omitted, only the main type is matched. """ parts = [] for subpart in msg.walk(): if subpart.get_main_type('text') == maintype: if subtype is None or subpart.get_subtype('plain') == subtype: parts.append(subpart) return parts --- NEW FILE: _compat22.py --- # Copyright (C) 2002 Python Software Foundation # Author: barry@zope.com """Module containing compatibility functions for Python 2.1. """ from __future__ import generators from __future__ import division from cStringIO import StringIO from types import StringTypes # This function will become a method of the Message class def walk(self): """Walk over the message tree, yielding each subpart. The walk is performed in depth-first order. This method is a generator. """ yield self if self.is_multipart(): for subpart in self.get_payload(): for subsubpart in subpart.walk(): yield subsubpart # Python 2.2 spells floor division // def _floordiv(i, j): """Do a floor division, i/j.""" return i // j def _isstring(obj): return isinstance(obj, StringTypes) # These two functions are imported into the Iterators.py interface module. # The Python 2.2 version uses generators for efficiency. def body_line_iterator(msg): """Iterate over the parts, returning string payloads line-by-line.""" for subpart in msg.walk(): payload = subpart.get_payload() if _isstring(payload): for line in StringIO(payload): yield line def typed_subpart_iterator(msg, maintype='text', subtype=None): """Iterate over the subparts with a given MIME type. Use `maintype' as the main MIME type to match against; this defaults to "text". Optional `subtype' is the MIME subtype to match against; if omitted, only the main type is matched. """ for subpart in msg.walk(): if subpart.get_main_type('text') == maintype: if subtype is None or subpart.get_subtype('plain') == subtype: yield subpart --- NEW FILE: base64MIME.py --- # Copyright (C) 2002 Python Software Foundation # Author: che@debian.org (Ben Gertzfield) """Base64 content transfer encoding per RFCs 2045-2047. This module handles the content transfer encoding method defined in RFC 2045 to encode arbitrary 8-bit data using the three 8-bit bytes in four 7-bit characters encoding known as Base64. It is used in the MIME standards for email to attach images, audio, and text using some 8-bit character sets to messages. This module provides an interface to encode and decode both headers and bodies with Base64 encoding. RFC 2045 defines a method for including character set information in an `encoded-word' in a header. This method is commonly used for 8-bit real names in To:, From:, Cc:, etc. fields, as well as Subject: lines. This module does not do the line wrapping or end-of-line character conversion necessary for proper internationalized headers; it only does dumb encoding and decoding. To deal with the various line wrapping issues, use the email.Header module. """ import re from binascii import b2a_base64, a2b_base64 from email.Utils import fix_eols try: from email._compat22 import _floordiv except SyntaxError: # Python 2.1 spells integer division differently from email._compat21 import _floordiv CRLF = '\r\n' NL = '\n' EMPTYSTRING = '' # See also Charset.py MISC_LEN = 7 try: True, False except NameError: True = 1 False = 0 # Helpers def base64_len(s): """Return the length of s when it is encoded with base64.""" groups_of_3, leftover = divmod(len(s), 3) # 4 bytes out for each 3 bytes (or nonzero fraction thereof) in. # Thanks, Tim! n = groups_of_3 * 4 if leftover: n += 4 return n def header_encode(header, charset='iso-8859-1', keep_eols=False, maxlinelen=76, eol=NL): """Encode a single header line with Base64 encoding in a given charset. Defined in RFC 2045, this Base64 encoding is identical to normal Base64 encoding, except that each line must be intelligently wrapped (respecting the Base64 encoding), and subsequent lines must start with a space. charset names the character set to use to encode the header. It defaults to iso-8859-1. End-of-line characters (\\r, \\n, \\r\\n) will be automatically converted to the canonical email line separator \\r\\n unless the keep_eols parameter is True (the default is False). Each line of the header will be terminated in the value of eol, which defaults to "\\n". Set this to "\\r\\n" if you are using the result of this function directly in email. The resulting string will be in the form: "=?charset?b?WW/5ciBtYXp66XLrIHf8eiBhIGhhbXBzdGHuciBBIFlv+XIgbWF6euly?=\\n =?charset?b?6yB3/HogYSBoYW1wc3Rh7nIgQkMgWW/5ciBtYXp66XLrIHf8eiBhIGhh?=" with each line wrapped at, at most, maxlinelen characters (defaults to 76 characters). """ # Return empty headers unchanged if not header: return header if not keep_eols: header = fix_eols(header) # Base64 encode each line, in encoded chunks no greater than maxlinelen in # length, after the RFC chrome is added in. base64ed = [] max_encoded = maxlinelen - len(charset) - MISC_LEN max_unencoded = _floordiv(max_encoded * 3, 4) # BAW: Ben's original code used a step of max_unencoded, but I think it # ought to be max_encoded. Otherwise, where's max_encoded used? I'm # still not sure what the for i in range(0, len(header), max_unencoded): base64ed.append(b2a_base64(header[i:i+max_unencoded])) # Now add the RFC chrome to each encoded chunk lines = [] for line in base64ed: # Ignore the last character of each line if it is a newline if line.endswith(NL): line = line[:-1] # Add the chrome lines.append('=?%s?b?%s?=' % (charset, line)) # Glue the lines together and return it. BAW: should we be able to # specify the leading whitespace in the joiner? joiner = eol + ' ' return joiner.join(lines) def encode(s, binary=True, maxlinelen=76, eol=NL): """Encode a string with base64. Each line will be wrapped at, at most, maxlinelen characters (defaults to 76 characters). If binary is False, end-of-line characters will be converted to the canonical email end-of-line sequence \\r\\n. Otherwise they will be left verbatim (this is the default). Each line of encoded text will end with eol, which defaults to "\\n". Set this to "\r\n" if you will be using the result of this function directly in an email. """ if not s: return s if not binary: s = fix_eols(s) encvec = [] max_unencoded = _floordiv(maxlinelen * 3, 4) for i in range(0, len(s), max_unencoded): # BAW: should encode() inherit b2a_base64()'s dubious behavior in # adding a newline to the encoded string? enc = b2a_base64(s[i:i + max_unencoded]) if enc.endswith(NL) and eol <> NL: enc = enc[:-1] + eol encvec.append(enc) return EMPTYSTRING.join(encvec) # For convenience and backwards compatibility w/ standard base64 module body_encode = encode encodestring = encode def decode(s, convert_eols=None): """Decode a raw base64 string. If convert_eols is set to a string value, all canonical email linefeeds, e.g. "\\r\\n", in the decoded text will be converted to the value of convert_eols. os.linesep is a good choice for convert_eols if you are decoding a text attachment. This function does not parse a full MIME header value encoded with base64 (like =?iso-8895-1?b?bmloISBuaWgh?=) -- please use the high level email.Header class for that functionality. """ if not s: return s dec = a2b_base64(s) if convert_eols: return dec.replace(CRLF, convert_eols) return dec # For convenience and backwards compatibility w/ standard base64 module body_decode = decode decodestring = decode --- NEW FILE: quopriMIME.py --- # Copyright (C) 2001,2002 Python Software Foundation # Author: che@debian.org (Ben Gertzfield) """Quoted-printable content transfer encoding per RFCs 2045-2047. This module handles the content transfer encoding method defined in RFC 2045 to encode US ASCII-like 8-bit data called `quoted-printable'. It is used to safely encode text that is in a character set similar to the 7-bit US ASCII character set, but that includes some 8-bit characters that are normally not allowed in email bodies or headers. Quoted-printable is very space-inefficient for encoding binary files; use the email.base64MIME module for that instead. This module provides an interface to encode and decode both headers and bodies with quoted-printable encoding. RFC 2045 defines a method for including character set information in an `encoded-word' in a header. This method is commonly used for 8-bit real names in To:/From:/Cc: etc. fields, as well as Subject: lines. This module does not do the line wrapping or end-of-line character conversion necessary for proper internationalized headers; it only does dumb encoding and decoding. To deal with the various line wrapping issues, use the email.Header module. """ import re from string import hexdigits from email.Utils import fix_eols CRLF = '\r\n' NL = '\n' # See also Charset.py MISC_LEN = 7 hqre = re.compile(r'[^-a-zA-Z0-9!*+/ ]') bqre = re.compile(r'[^ !-<>-~\t]') try: True, False except NameError: True = 1 False = 0 # Helpers def header_quopri_check(c): """Return True if the character should be escaped with header quopri.""" return hqre.match(c) and True def body_quopri_check(c): """Return True if the character should be escaped with body quopri.""" return bqre.match(c) and True def header_quopri_len(s): """Return the length of str when it is encoded with header quopri.""" count = 0 for c in s: if hqre.match(c): count += 3 else: count += 1 return count def body_quopri_len(str): """Return the length of str when it is encoded with body quopri.""" count = 0 for c in str: if bqre.match(c): count += 3 else: count += 1 return count def _max_append(L, s, maxlen, extra=''): if not L: L.append(s.lstrip()) elif len(L[-1]) + len(s) < maxlen: L[-1] += extra + s else: L.append(s.lstrip()) def unquote(s): """Turn a string in the form =AB to the ASCII character with value 0xab""" return chr(int(s[1:3], 16)) def quote(c): return "=%02X" % ord(c) def header_encode(header, charset="iso-8859-1", keep_eols=False, maxlinelen=76, eol=NL): """Encode a single header line with quoted-printable (like) encoding. Defined in RFC 2045, this `Q' encoding is similar to quoted-printable, but used specifically for email header fields to allow charsets with mostly 7 bit characters (and some 8 bit) to remain more or less readable in non-RFC 2045 aware mail clients. charset names the character set to use to encode the header. It defaults to iso-8859-1. The resulting string will be in the form: "=?charset?q?I_f=E2rt_in_your_g=E8n=E8ral_dire=E7tion?\\n =?charset?q?Silly_=C8nglish_Kn=EEghts?=" with each line wrapped safely at, at most, maxlinelen characters (defaults to 76 characters). End-of-line characters (\\r, \\n, \\r\\n) will be automatically converted to the canonical email line separator \\r\\n unless the keep_eols parameter is True (the default is False). Each line of the header will be terminated in the value of eol, which defaults to "\\n". Set this to "\\r\\n" if you are using the result of this function directly in email. """ # Return empty headers unchanged if not header: return header if not keep_eols: header = fix_eols(header) # Quopri encode each line, in encoded chunks no greater than maxlinelen in # lenght, after the RFC chrome is added in. quoted = [] max_encoded = maxlinelen - len(charset) - MISC_LEN for c in header: # Space may be represented as _ instead of =20 for readability if c == ' ': _max_append(quoted, '_', max_encoded) # These characters can be included verbatim elif not hqre.match(c): _max_append(quoted, c, max_encoded) # Otherwise, replace with hex value like =E2 else: _max_append(quoted, "=%02X" % ord(c), max_encoded) # Now add the RFC chrome to each encoded chunk and glue the chunks # together. BAW: should we be able to specify the leading whitespace in # the joiner? joiner = eol + ' ' return joiner.join(['=?%s?q?%s?=' % (charset, line) for line in quoted]) def encode(body, binary=False, maxlinelen=76, eol=NL): """Encode with quoted-printable, wrapping at maxlinelen characters. If binary is False (the default), end-of-line characters will be converted to the canonical email end-of-line sequence \\r\\n. Otherwise they will be left verbatim. Each line of encoded text will end with eol, which defaults to "\\n". Set this to "\\r\\n" if you will be using the result of this function directly in an email. Each line will be wrapped at, at most, maxlinelen characters (defaults to 76 characters). Long lines will have the `soft linefeed' quoted-printable character "=" appended to them, so the decoded text will be identical to the original text. """ if not body: return body if not binary: body = fix_eols(body) # BAW: We're accumulating the body text by string concatenation. That # can't be very efficient, but I don't have time now to rewrite it. It # just feels like this algorithm could be more efficient. encoded_body = '' lineno = -1 # Preserve line endings here so we can check later to see an eol needs to # be added to the output later. lines = body.splitlines(1) for line in lines: # But strip off line-endings for processing this line. if line.endswith(CRLF): line = line[:-2] elif line[-1] in CRLF: line = line[:-1] lineno += 1 encoded_line = '' prev = None linelen = len(line) # Now we need to examine every character to see if it needs to be # quopri encoded. BAW: again, string concatenation is inefficient. for j in range(linelen): c = line[j] prev = c if bqre.match(c): c = quote(c) elif j+1 == linelen: # Check for whitespace at end of line; special case if c not in ' \t': encoded_line += c prev = c continue # Check to see to see if the line has reached its maximum length if len(encoded_line) + len(c) >= maxlinelen: encoded_body += encoded_line + '=' + eol encoded_line = '' encoded_line += c # Now at end of line.. if prev and prev in ' \t': # Special case for whitespace at end of file if lineno + 1 == len(lines): prev = quote(prev) if len(encoded_line) + len(prev) > maxlinelen: encoded_body += encoded_line + '=' + eol + prev else: encoded_body += encoded_line + prev # Just normal whitespace at end of line else: encoded_body += encoded_line + prev + '=' + eol encoded_line = '' # Now look at the line we just finished and it has a line ending, we # need to add eol to the end of the line. if lines[lineno].endswith(CRLF) or lines[lineno][-1] in CRLF: encoded_body += encoded_line + eol else: encoded_body += encoded_line encoded_line = '' return encoded_body # For convenience and backwards compatibility w/ standard base64 module body_encode = encode encodestring = encode # BAW: I'm not sure if the intent was for the signature of this function to be # the same as base64MIME.decode() or not... def decode(encoded, eol=NL): """Decode a quoted-printable string. Lines are separated with eol, which defaults to \\n. """ if not encoded: return encoded # BAW: see comment in encode() above. Again, we're building up the # decoded string with string concatenation, which could be done much more # efficiently. decoded = '' for line in encoded.splitlines(): line = line.rstrip() if not line: decoded += eol continue i = 0 n = len(line) while i < n: c = line[i] if c <> '=': decoded += c i += 1 # Otherwise, c == "=". Are we at the end of the line? If so, add # a soft line break. elif i+1 == n: i += 1 continue # Decode if in form =AB elif i+2 < n and line[i+1] in hexdigits and line[i+2] in hexdigits: decoded += unquote(line[i:i+3]) i += 3 # Otherwise, not in form =AB, pass literally else: decoded += c i += 1 if i == n: decoded += eol # Special case if original string did not end with eol if not encoded.endswith(eol) and decoded.endswith(eol): decoded = decoded[:-1] return decoded # For convenience and backwards compatibility w/ standard base64 module body_decode = decode decodestring = decode def _unquote_match(match): """Turn a match in the form =AB to the ASCII character with value 0xab""" s = match.group(0) return unquote(s) # Header decoding is done a bit differently def header_decode(s): """Decode a string encoded with RFC 2045 MIME header `Q' encoding. This function does not parse a full MIME header value encoded with quoted-printable (like =?iso-8895-1?q?Hello_World?=) -- please use the high level email.Header class for that functionality. """ s = s.replace('_', ' ') return re.sub(r'=\w{2}', _unquote_match, s) Index: Encoders.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Encoders.py,v retrieving revision 1.4 retrieving revision 1.4.10.1 diff -C2 -d -r1.4 -r1.4.10.1 *** Encoders.py 4 Oct 2001 17:05:11 -0000 1.4 --- Encoders.py 4 Oct 2002 17:24:23 -0000 1.4.10.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 6,16 **** import base64 - from quopri import encodestring as _encodestring # Helpers ! def _qencode(s): ! return _encodestring(s, quotetabs=1) --- 6,37 ---- import base64 # Helpers ! try: ! from quopri import encodestring as _encodestring ! ! def _qencode(s): ! enc = _encodestring(s, quotetabs=1) ! # Must encode spaces, which quopri.encodestring() doesn't do ! return enc.replace(' ', '=20') ! except ImportError: ! # Python 2.1 doesn't have quopri.encodestring() ! from cStringIO import StringIO ! import quopri as _quopri ! ! def _qencode(s): ! if not s: ! return s ! hasnewline = (s[-1] == '\n') ! infp = StringIO(s) ! outfp = StringIO() ! _quopri.encode(infp, outfp, quotetabs=1) ! # Python 2.x's encode() doesn't encode spaces even when quotetabs==1 ! value = outfp.getvalue().replace(' ', '=20') ! if not hasnewline and value[-1] == '\n': ! return value[:-1] ! return value *************** *** 31,35 **** """Encode the message's payload in Base64. ! Also, add an appropriate Content-Transfer-Encoding: header. """ orig = msg.get_payload() --- 52,56 ---- """Encode the message's payload in Base64. ! Also, add an appropriate Content-Transfer-Encoding header. """ orig = msg.get_payload() *************** *** 41,47 **** def encode_quopri(msg): ! """Encode the message's payload in Quoted-Printable. ! Also, add an appropriate Content-Transfer-Encoding: header. """ orig = msg.get_payload() --- 62,68 ---- def encode_quopri(msg): ! """Encode the message's payload in quoted-printable. ! Also, add an appropriate Content-Transfer-Encoding header. """ orig = msg.get_payload() *************** *** 53,58 **** def encode_7or8bit(msg): ! """Set the Content-Transfer-Encoding: header to 7bit or 8bit.""" orig = msg.get_payload() # We play a trick to make this go fast. If encoding to ASCII succeeds, we # know the data must be 7bit, otherwise treat it as 8bit. --- 74,83 ---- def encode_7or8bit(msg): ! """Set the Content-Transfer-Encoding header to 7bit or 8bit.""" orig = msg.get_payload() + if orig is None: + # There's no payload. For backwards compatibility we use 7bit + msg['Content-Transfer-Encoding'] = '7bit' + return # We play a trick to make this go fast. If encoding to ASCII succeeds, we # know the data must be 7bit, otherwise treat it as 8bit. Index: Errors.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Errors.py,v retrieving revision 1.3 retrieving revision 1.3.10.1 diff -C2 -d -r1.3 -r1.3.10.1 *** Errors.py 4 Oct 2001 17:05:11 -0000 1.3 --- Errors.py 4 Oct 2002 17:24:23 -0000 1.3.10.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 8,12 **** class MessageError(Exception): ! """Base class for errors in this module.""" --- 8,12 ---- class MessageError(Exception): ! """Base class for errors in the email package.""" Index: Generator.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Generator.py,v retrieving revision 1.6.10.1 retrieving revision 1.6.10.2 diff -C2 -d -r1.6.10.1 -r1.6.10.2 *** Generator.py 22 Mar 2002 16:21:56 -0000 1.6.10.1 --- Generator.py 4 Oct 2002 17:24:23 -0000 1.6.10.2 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 9,18 **** import random ! from types import ListType, StringType from cStringIO import StringIO ! # Intrapackage imports ! import Message ! import Errors EMPTYSTRING = '' --- 9,27 ---- import random ! from types import ListType from cStringIO import StringIO ! from email.Header import Header ! ! try: ! from email._compat22 import _isstring ! except SyntaxError: ! from email._compat21 import _isstring ! ! try: ! True, False ! except NameError: ! True = 1 ! False = 0 EMPTYSTRING = '' *************** *** 39,43 **** # ! def __init__(self, outfp, mangle_from_=1, maxheaderlen=78): """Create the generator for message flattening. --- 48,52 ---- # ! def __init__(self, outfp, mangle_from_=True, maxheaderlen=78): """Create the generator for message flattening. *************** *** 45,50 **** must have a write() method. ! Optional mangle_from_ is a flag that, when true, escapes From_ lines ! in the body of the message by putting a `>' in front of them. Optional maxheaderlen specifies the longest length for a non-continued --- 54,60 ---- must have a write() method. ! Optional mangle_from_ is a flag that, when True (the default), escapes ! From_ lines in the body of the message by putting a `>' in front of ! them. Optional maxheaderlen specifies the longest length for a non-continued *************** *** 58,62 **** self._fp = outfp self._mangle_from_ = mangle_from_ - self.__first = 1 self.__maxheaderlen = maxheaderlen --- 68,71 ---- *************** *** 65,69 **** self._fp.write(s) ! def __call__(self, msg, unixfrom=0): """Print the message object tree rooted at msg to the output file specified when the Generator instance was created. --- 74,78 ---- self._fp.write(s) ! def flatten(self, msg, unixfrom=False): """Print the message object tree rooted at msg to the output file specified when the Generator instance was created. *************** *** 72,76 **** before the first object in the message tree. If the original message has no From_ delimiter, a `standard' one is crafted. By default, this ! is 0 to inhibit the printing of any From_ delimiter. Note that for subobjects, no From_ line is printed. --- 81,85 ---- before the first object in the message tree. If the original message has no From_ delimiter, a `standard' one is crafted. By default, this ! is False to inhibit the printing of any From_ delimiter. Note that for subobjects, no From_ line is printed. *************** *** 83,86 **** --- 92,102 ---- self._write(msg) + # For backwards compatibility, but this is slower + __call__ = flatten + + def clone(self, fp): + """Clone this generator with the exact same options.""" + return self.__class__(fp, self._mangle_from_, self.__maxheaderlen) + # # Protected interface - undocumented ;/ *************** *** 116,136 **** def _dispatch(self, msg): # Get the Content-Type: for the message, then try to dispatch to ! # self._handle_maintype_subtype(). If there's no handler for the full ! # MIME type, then dispatch to self._handle_maintype(). If that's ! # missing too, then dispatch to self._writeBody(). ! ctype = msg.get_type() ! if ctype is None: ! # No Content-Type: header so try the default handler ! self._writeBody(msg) ! else: ! # We do have a Content-Type: header. ! specific = UNDERSCORE.join(ctype.split('/')).replace('-', '_') ! meth = getattr(self, '_handle_' + specific, None) if meth is None: ! generic = msg.get_main_type().replace('-', '_') ! meth = getattr(self, '_handle_' + generic, None) ! if meth is None: ! meth = self._writeBody ! meth(msg) # --- 132,148 ---- def _dispatch(self, msg): # Get the Content-Type: for the message, then try to dispatch to ! # self._handle__(). If there's no handler for the ! # full MIME type, then dispatch to self._handle_(). If ! # that's missing too, then dispatch to self._writeBody(). ! main = msg.get_content_maintype() ! sub = msg.get_content_subtype() ! specific = UNDERSCORE.join((main, sub)).replace('-', '_') ! meth = getattr(self, '_handle_' + specific, None) ! if meth is None: ! generic = main.replace('-', '_') ! meth = getattr(self, '_handle_' + generic, None) if meth is None: ! meth = self._writeBody ! meth(msg) # *************** *** 140,149 **** def _write_headers(self, msg): for h, v in msg.items(): - # We only write the MIME-Version: header for the outermost - # container message. Unfortunately, we can't use same technique - # as for the Unix-From above because we don't know when - # MIME-Version: will occur. - if h.lower() == 'mime-version' and not self.__first: - continue # RFC 2822 says that lines SHOULD be no more than maxheaderlen # characters wide, so we're well within our rights to split long --- 152,155 ---- *************** *** 161,165 **** # maxheaderlen characters wide. There could be continuation lines # that actually shorten it. Also, replace hard tabs with 8 spaces. ! lines = [s.replace('\t', SPACE8) for s in text.split('\n')] for line in lines: if len(line) > maxheaderlen: --- 167,171 ---- # maxheaderlen characters wide. There could be continuation lines # that actually shorten it. Also, replace hard tabs with 8 spaces. ! lines = [s.replace('\t', SPACE8) for s in text.splitlines()] for line in lines: if len(line) > maxheaderlen: *************** *** 169,218 **** # just return the original unchanged. return text ! rtn = [] ! for line in text.split('\n'): ! # Short lines can remain unchanged ! if len(line.replace('\t', SPACE8)) <= maxheaderlen: ! rtn.append(line) ! SEMINLTAB.join(rtn) ! else: ! oldlen = len(text) ! # Try to break the line on semicolons, but if that doesn't ! # work, try to split on folding whitespace. ! while len(text) > maxheaderlen: ! i = text.rfind(';', 0, maxheaderlen) ! if i < 0: ! break ! rtn.append(text[:i]) ! text = text[i+1:].lstrip() ! if len(text) <> oldlen: ! # Splitting on semis worked ! rtn.append(text) ! return SEMINLTAB.join(rtn) ! # Splitting on semis didn't help, so try to split on ! # whitespace. ! parts = re.split(r'(\s+)', text) ! # Watch out though for "Header: longnonsplittableline" ! if parts[0].endswith(':') and len(parts) == 3: ! return text ! first = parts.pop(0) ! sublines = [first] ! acc = len(first) ! while parts: ! len0 = len(parts[0]) ! len1 = len(parts[1]) ! if acc + len0 + len1 < maxheaderlen: ! sublines.append(parts.pop(0)) ! sublines.append(parts.pop(0)) ! acc += len0 + len1 ! else: ! # Split it here, but don't forget to ignore the ! # next whitespace-only part ! rtn.append(EMPTYSTRING.join(sublines)) ! del parts[0] ! first = parts.pop(0) ! sublines = [first] ! acc = len(first) ! rtn.append(EMPTYSTRING.join(sublines)) ! return NLTAB.join(rtn) # --- 175,184 ---- # just return the original unchanged. return text ! # The `text' argument already has the field name prepended, so don't ! # provide it here or the first line will get folded too short. ! h = Header(text, maxlinelen=maxheaderlen, ! # For backwards compatibility, we use a hard tab here ! continuation_ws='\t') ! return h.encode() # *************** *** 224,228 **** if payload is None: return ! if not isinstance(payload, StringType): raise TypeError, 'string payload expected: %s' % type(payload) if self._mangle_from_: --- 190,197 ---- if payload is None: return ! cset = msg.get_charset() ! if cset is not None: ! payload = cset.body_encode(payload) ! if not _isstring(payload): raise TypeError, 'string payload expected: %s' % type(payload) if self._mangle_from_: *************** *** 233,246 **** _writeBody = _handle_text ! def _handle_multipart(self, msg, isdigest=0): # The trick here is to write out each part separately, merge them all # together, and then make sure that the boundary we've chosen isn't # present in the payload. msgtexts = [] - # BAW: kludge for broken add_payload() semantics; watch out for - # multipart/* MIME types with None or scalar payloads. subparts = msg.get_payload() if subparts is None: ! # Nothing has every been attached boundary = msg.get_boundary(failobj=_make_boundary()) print >> self._fp, '--' + boundary --- 202,213 ---- _writeBody = _handle_text ! def _handle_multipart(self, msg): # The trick here is to write out each part separately, merge them all # together, and then make sure that the boundary we've chosen isn't # present in the payload. msgtexts = [] subparts = msg.get_payload() if subparts is None: ! # Nothing has ever been attached boundary = msg.get_boundary(failobj=_make_boundary()) print >> self._fp, '--' + boundary *************** *** 248,251 **** --- 215,222 ---- print >> self._fp, '--' + boundary + '--' return + elif _isstring(subparts): + # e.g. a non-strict parse of a message with no starting boundary. + self._fp.write(subparts) + return elif not isinstance(subparts, ListType): # Scalar payload *************** *** 253,258 **** for part in subparts: s = StringIO() ! g = self.__class__(s, self._mangle_from_, self.__maxheaderlen) ! g(part, unixfrom=0) msgtexts.append(s.getvalue()) # Now make sure the boundary we've selected doesn't appear in any of --- 224,229 ---- for part in subparts: s = StringIO() ! g = self.clone(s) ! g.flatten(part, unixfrom=False) msgtexts.append(s.getvalue()) # Now make sure the boundary we've selected doesn't appear in any of *************** *** 275,286 **** # newline. print >> self._fp, '--' + boundary - if isdigest: - print >> self._fp # Join and write the individual parts joiner = '\n--' + boundary + '\n' - if isdigest: - # multipart/digest types effectively add an extra newline between - # the boundary and the body part. - joiner += '\n' self._fp.write(joiner.join(msgtexts)) print >> self._fp, '\n--' + boundary + '--', --- 246,251 ---- *************** *** 291,297 **** self._fp.write(msg.epilogue) - def _handle_multipart_digest(self, msg): - self._handle_multipart(msg, isdigest=1) - def _handle_message_delivery_status(self, msg): # We can't just write the headers directly to self's file object --- 256,259 ---- *************** *** 301,306 **** for part in msg.get_payload(): s = StringIO() ! g = self.__class__(s, self._mangle_from_, self.__maxheaderlen) ! g(part, unixfrom=0) text = s.getvalue() lines = text.split('\n') --- 263,268 ---- for part in msg.get_payload(): s = StringIO() ! g = self.clone(s) ! g.flatten(part, unixfrom=False) text = s.getvalue() lines = text.split('\n') *************** *** 317,325 **** def _handle_message(self, msg): s = StringIO() ! g = self.__class__(s, self._mangle_from_, self.__maxheaderlen) ! # A message/rfc822 should contain a scalar payload which is another ! # Message object. Extract that object, stringify it, and write that ! # out. ! g(msg.get_payload(), unixfrom=0) self._fp.write(s.getvalue()) --- 279,288 ---- def _handle_message(self, msg): s = StringIO() ! g = self.clone(s) ! # The payload of a message/rfc822 part should be a multipart sequence ! # of length 1. The zeroth element of the list should be the Message ! # object for the subpart. Extract that object, stringify it, and ! # write it out. ! g.flatten(msg.get_payload(0), unixfrom=False) self._fp.write(s.getvalue()) *************** *** 332,336 **** with a format string representing the part. """ ! def __init__(self, outfp, mangle_from_=1, maxheaderlen=78, fmt=None): """Like Generator.__init__() except that an additional optional argument is allowed. --- 295,299 ---- with a format string representing the part. """ ! def __init__(self, outfp, mangle_from_=True, maxheaderlen=78, fmt=None): """Like Generator.__init__() except that an additional optional argument is allowed. *************** *** 364,368 **** maintype = part.get_main_type('text') if maintype == 'text': ! print >> self, part.get_payload(decode=1) elif maintype == 'multipart': # Just skip this --- 327,331 ---- maintype = part.get_main_type('text') if maintype == 'text': ! print >> self, part.get_payload(decode=True) elif maintype == 'multipart': # Just skip this *************** *** 391,395 **** b = boundary counter = 0 ! while 1: cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE) if not cre.search(text): --- 354,358 ---- b = boundary counter = 0 ! while True: cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE) if not cre.search(text): Index: Iterators.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Iterators.py,v retrieving revision 1.5 retrieving revision 1.5.10.1 diff -C2 -d -r1.5 -r1.5.10.1 *** Iterators.py 15 Oct 2001 04:38:22 -0000 1.5 --- Iterators.py 4 Oct 2002 17:24:24 -0000 1.5.10.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 5,33 **** """ ! from __future__ import generators ! from cStringIO import StringIO ! from types import StringType ! ! ! def body_line_iterator(msg): ! """Iterate over the parts, returning string payloads line-by-line.""" ! for subpart in msg.walk(): ! payload = subpart.get_payload() ! if type(payload) is StringType: ! for line in StringIO(payload): ! yield line ! def typed_subpart_iterator(msg, maintype='text', subtype=None): ! """Iterate over the subparts with a given MIME type. ! ! Use `maintype' as the main MIME type to match against; this defaults to ! "text". Optional `subtype' is the MIME subtype to match against; if ! omitted, only the main type is matched. ! """ ! for subpart in msg.walk(): ! if subpart.get_main_type('text') == maintype: ! if subtype is None or subpart.get_subtype('plain') == subtype: ! yield subpart --- 5,25 ---- """ ! import sys ! try: ! from email._compat22 import body_line_iterator, typed_subpart_iterator ! except SyntaxError: ! # Python 2.1 doesn't have generators ! from email._compat21 import body_line_iterator, typed_subpart_iterator ! def _structure(msg, fp=None, level=0): ! """A handy debugging aid""" ! if fp is None: ! fp = sys.stdout ! tab = ' ' * (level * 4) ! print >> fp, tab + msg.get_content_type() ! if msg.is_multipart(): ! for subpart in msg.get_payload(): ! _structure(subpart, fp, level+1) Index: MIMEAudio.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/MIMEAudio.py,v retrieving revision 1.2 retrieving revision 1.2.6.1 diff -C2 -d -r1.2 -r1.2.6.1 *** MIMEAudio.py 24 Nov 2001 15:49:53 -0000 1.2 --- MIMEAudio.py 4 Oct 2002 17:24:24 -0000 1.2.6.1 *************** *** 7,13 **** from cStringIO import StringIO ! import MIMEBase ! import Errors ! import Encoders --- 7,13 ---- from cStringIO import StringIO ! from email import Errors ! from email import Encoders ! from email.MIMENonMultipart import MIMENonMultipart *************** *** 38,42 **** ! class MIMEAudio(MIMEBase.MIMEBase): """Class for generating audio/* MIME documents.""" --- 38,42 ---- ! class MIMEAudio(MIMENonMultipart): """Class for generating audio/* MIME documents.""" *************** *** 47,51 **** _audiodata is a string containing the raw audio data. If this data can be decoded by the standard Python `sndhdr' module, then the ! subtype will be automatically included in the Content-Type: header. Otherwise, you can specify the specific audio subtype via the _subtype parameter. If _subtype is not given, and no subtype can be --- 47,51 ---- _audiodata is a string containing the raw audio data. If this data can be decoded by the standard Python `sndhdr' module, then the ! subtype will be automatically included in the Content-Type header. Otherwise, you can specify the specific audio subtype via the _subtype parameter. If _subtype is not given, and no subtype can be *************** *** 56,64 **** Image instance. It should use get_payload() and set_payload() to change the payload to the encoded form. It should also add any ! Content-Transfer-Encoding: or other headers to the message as necessary. The default encoding is Base64. Any additional keyword arguments are passed to the base class ! constructor, which turns them into parameters on the Content-Type: header. """ --- 56,64 ---- Image instance. It should use get_payload() and set_payload() to change the payload to the encoded form. It should also add any ! Content-Transfer-Encoding or other headers to the message as necessary. The default encoding is Base64. Any additional keyword arguments are passed to the base class ! constructor, which turns them into parameters on the Content-Type header. """ *************** *** 67,71 **** if _subtype is None: raise TypeError, 'Could not find audio MIME subtype' ! MIMEBase.MIMEBase.__init__(self, 'audio', _subtype, **_params) self.set_payload(_audiodata) _encoder(self) --- 67,71 ---- if _subtype is None: raise TypeError, 'Could not find audio MIME subtype' ! MIMENonMultipart.__init__(self, 'audio', _subtype, **_params) self.set_payload(_audiodata) _encoder(self) Index: MIMEBase.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/MIMEBase.py,v retrieving revision 1.4 retrieving revision 1.4.10.1 diff -C2 -d -r1.4 -r1.4.10.1 *** MIMEBase.py 4 Oct 2001 17:05:11 -0000 1.4 --- MIMEBase.py 4 Oct 2002 17:24:24 -0000 1.4.10.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 5,9 **** """ ! import Message --- 5,9 ---- """ ! from email import Message Index: MIMEImage.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/MIMEImage.py,v retrieving revision 1.3 retrieving revision 1.3.10.1 diff -C2 -d -r1.3 -r1.3.10.1 *** MIMEImage.py 4 Oct 2001 17:05:11 -0000 1.3 --- MIMEImage.py 4 Oct 2002 17:24:24 -0000 1.3.10.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 7,18 **** import imghdr ! # Intrapackage imports ! import MIMEBase ! import Errors ! import Encoders ! class MIMEImage(MIMEBase.MIMEBase): """Class for generating image/* type MIME documents.""" --- 7,17 ---- import imghdr ! from email import Errors ! from email import Encoders ! from email.MIMENonMultipart import MIMENonMultipart ! class MIMEImage(MIMENonMultipart): """Class for generating image/* type MIME documents.""" *************** *** 23,27 **** _imagedata is a string containing the raw image data. If this data can be decoded by the standard Python `imghdr' module, then the ! subtype will be automatically included in the Content-Type: header. Otherwise, you can specify the specific image subtype via the _subtype parameter. --- 22,26 ---- _imagedata is a string containing the raw image data. If this data can be decoded by the standard Python `imghdr' module, then the ! subtype will be automatically included in the Content-Type header. Otherwise, you can specify the specific image subtype via the _subtype parameter. *************** *** 31,39 **** Image instance. It should use get_payload() and set_payload() to change the payload to the encoded form. It should also add any ! Content-Transfer-Encoding: or other headers to the message as necessary. The default encoding is Base64. Any additional keyword arguments are passed to the base class ! constructor, which turns them into parameters on the Content-Type: header. """ --- 30,38 ---- Image instance. It should use get_payload() and set_payload() to change the payload to the encoded form. It should also add any ! Content-Transfer-Encoding or other headers to the message as necessary. The default encoding is Base64. Any additional keyword arguments are passed to the base class ! constructor, which turns them into parameters on the Content-Type header. """ *************** *** 42,46 **** if _subtype is None: raise TypeError, 'Could not guess image MIME subtype' ! MIMEBase.MIMEBase.__init__(self, 'image', _subtype, **_params) self.set_payload(_imagedata) _encoder(self) --- 41,45 ---- if _subtype is None: raise TypeError, 'Could not guess image MIME subtype' ! MIMENonMultipart.__init__(self, 'image', _subtype, **_params) self.set_payload(_imagedata) _encoder(self) Index: MIMEMessage.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/MIMEMessage.py,v retrieving revision 1.3 retrieving revision 1.3.10.1 diff -C2 -d -r1.3 -r1.3.10.1 *** MIMEMessage.py 4 Oct 2001 17:05:11 -0000 1.3 --- MIMEMessage.py 4 Oct 2002 17:24:24 -0000 1.3.10.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 5,14 **** """ ! import Message ! import MIMEBase ! class MIMEMessage(MIMEBase.MIMEBase): """Class representing message/* MIME documents.""" --- 5,14 ---- """ ! from email import Message ! from email.MIMENonMultipart import MIMENonMultipart ! class MIMEMessage(MIMENonMultipart): """Class representing message/* MIME documents.""" *************** *** 23,28 **** the term "rfc822" is technically outdated by RFC 2822). """ ! MIMEBase.MIMEBase.__init__(self, 'message', _subtype) if not isinstance(_msg, Message.Message): raise TypeError, 'Argument is not an instance of Message' ! self.set_payload(_msg) --- 23,32 ---- the term "rfc822" is technically outdated by RFC 2822). """ ! MIMENonMultipart.__init__(self, 'message', _subtype) if not isinstance(_msg, Message.Message): raise TypeError, 'Argument is not an instance of Message' ! # It's convenient to use this base class method. We need to do it ! # this way or we'll get an exception ! Message.Message.attach(self, _msg) ! # And be sure our default type is set correctly ! self.set_default_type('message/rfc822') Index: MIMEText.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/MIMEText.py,v retrieving revision 1.3 retrieving revision 1.3.10.1 diff -C2 -d -r1.3 -r1.3.10.1 *** MIMEText.py 4 Oct 2001 17:05:11 -0000 1.3 --- MIMEText.py 4 Oct 2002 17:24:24 -0000 1.3.10.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 5,18 **** """ ! import MIMEBase ! from Encoders import encode_7or8bit ! class MIMEText(MIMEBase.MIMEBase): """Class for generating text/* type MIME documents.""" def __init__(self, _text, _subtype='plain', _charset='us-ascii', ! _encoder=encode_7or8bit): """Create a text/* type MIME document. --- 5,19 ---- """ ! import warnings ! from email.MIMENonMultipart import MIMENonMultipart ! from email.Encoders import encode_7or8bit ! class MIMEText(MIMENonMultipart): """Class for generating text/* type MIME documents.""" def __init__(self, _text, _subtype='plain', _charset='us-ascii', ! _encoder=None): """Create a text/* type MIME document. *************** *** 22,41 **** _subtype is the MIME sub content type, defaulting to "plain". ! _charset is the character set parameter added to the Content-Type: ! header. This defaults to "us-ascii". ! _encoder is a function which will perform the actual encoding for ! transport of the text data. It takes one argument, which is this ! Text instance. It should use get_payload() and set_payload() to ! change the payload to the encoded form. It should also add any ! Content-Transfer-Encoding: or other headers to the message as ! necessary. The default encoding doesn't actually modify the payload, ! but it does set Content-Transfer-Encoding: to either `7bit' or `8bit' ! as appropriate. """ ! MIMEBase.MIMEBase.__init__(self, 'text', _subtype, ! **{'charset': _charset}) ! if _text and _text[-1] <> '\n': _text += '\n' ! self.set_payload(_text) ! _encoder(self) --- 23,48 ---- _subtype is the MIME sub content type, defaulting to "plain". ! _charset is the character set parameter added to the Content-Type ! header. This defaults to "us-ascii". Note that as a side-effect, the ! Content-Transfer-Encoding header will also be set. ! The use of the _encoder is deprecated. The encoding of the payload, ! and the setting of the character set parameter now happens implicitly ! based on the _charset argument. If _encoder is supplied, then a ! DeprecationWarning is used, and the _encoder functionality may ! override any header settings indicated by _charset. This is probably ! not what you want. """ ! MIMENonMultipart.__init__(self, 'text', _subtype, ! **{'charset': _charset}) ! if _text and not _text.endswith('\n'): _text += '\n' ! self.set_payload(_text, _charset) ! if _encoder is not None: ! warnings.warn('_encoder argument is obsolete.', ! DeprecationWarning, 2) ! # Because set_payload() with a _charset will set its own ! # Content-Transfer-Encoding header, we need to delete the ! # existing one or will end up with two of them. :( ! del self['content-transfer-encoding'] ! _encoder(self) Index: Message.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Message.py,v retrieving revision 1.9 retrieving revision 1.9.6.1 diff -C2 -d -r1.9 -r1.9.6.1 *** Message.py 24 Nov 2001 16:56:56 -0000 1.9 --- Message.py 4 Oct 2002 17:24:24 -0000 1.9.6.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 5,38 **** """ - from __future__ import generators - import re ! import base64 ! import quopri from cStringIO import StringIO ! from types import ListType # Intrapackage imports ! import Errors ! import Utils SEMISPACE = '; ' paramre = re.compile(r'\s*;\s*') class Message: ! """Basic message object for use inside the object tree. A message object is defined as something that has a bunch of RFC 2822 ! headers and a payload. If the body of the message is a multipart, then ! the payload is a list of Messages, otherwise it is a string. ! These objects implement part of the `mapping' interface, which assumes there is exactly one occurrance of the header per message. Some headers ! do in fact appear multiple times (e.g. Received:) and for those headers, you must use the explicit API to set or get all the headers. Not all of the mapping methods are implemented. - """ def __init__(self): --- 5,83 ---- """ import re ! import warnings from cStringIO import StringIO ! from types import ListType, TupleType, StringType # Intrapackage imports ! from email import Errors ! from email import Utils ! from email import Charset SEMISPACE = '; ' + + try: + True, False + except NameError: + True = 1 + False = 0 + + # Regular expression used to split header parameters. BAW: this may be too + # simple. It isn't strictly RFC 2045 (section 5.1) compliant, but it catches + # most headers found in the wild. We may eventually need a full fledged + # parser eventually. paramre = re.compile(r'\s*;\s*') + # Regular expression that matches `special' characters in parameters, the + # existance of which force quoting of the parameter value. + tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') + + + + # Helper functions + def _formatparam(param, value=None, quote=True): + """Convenience function to format and return a key=value pair. + + This will quote the value if needed or if quote is true. + """ + if value is not None and len(value) > 0: + # TupleType is used for RFC 2231 encoded parameter values where items + # are (charset, language, value). charset is a string, not a Charset + # instance. + if isinstance(value, TupleType): + # Encode as per RFC 2231 + param += '*' + value = Utils.encode_rfc2231(value[2], value[0], value[1]) + # BAW: Please check this. I think that if quote is set it should + # force quoting even if not necessary. + if quote or tspecials.search(value): + return '%s="%s"' % (param, Utils.quote(value)) + else: + return '%s=%s' % (param, value) + else: + return param + + + def _unquotevalue(value): + if isinstance(value, TupleType): + return value[0], value[1], Utils.unquote(value[2]) + else: + return Utils.unquote(value) class Message: ! """Basic message object. A message object is defined as something that has a bunch of RFC 2822 ! headers and a payload. It may optionally have an envelope header ! (a.k.a. Unix-From or From_ header). If the message is a container (i.e. a ! multipart or a message/rfc822), then the payload is a list of Message ! objects, otherwise it is a string. ! Message objects implement part of the `mapping' interface, which assumes there is exactly one occurrance of the header per message. Some headers ! do in fact appear multiple times (e.g. Received) and for those headers, you must use the explicit API to set or get all the headers. Not all of the mapping methods are implemented. """ def __init__(self): *************** *** 40,68 **** self._unixfrom = None self._payload = None # Defaults for multipart messages self.preamble = self.epilogue = None def __str__(self): """Return the entire formatted message as a string. ! This includes the headers, body, and `unixfrom' line. """ ! return self.as_string(unixfrom=1) ! def as_string(self, unixfrom=0): """Return the entire formatted message as a string. ! Optional `unixfrom' when true, means include the Unix From_ envelope header. """ ! from Generator import Generator fp = StringIO() g = Generator(fp) ! g(self, unixfrom=unixfrom) return fp.getvalue() def is_multipart(self): ! """Return true if the message consists of multiple parts.""" ! if type(self._payload) is ListType: ! return 1 ! return 0 # --- 85,116 ---- self._unixfrom = None self._payload = None + self._charset = None # Defaults for multipart messages self.preamble = self.epilogue = None + # Default content type + self._default_type = 'text/plain' def __str__(self): """Return the entire formatted message as a string. ! This includes the headers, body, and envelope header. """ ! return self.as_string(unixfrom=True) ! def as_string(self, unixfrom=False): """Return the entire formatted message as a string. ! Optional `unixfrom' when True, means include the Unix From_ envelope header. """ ! from email.Generator import Generator fp = StringIO() g = Generator(fp) ! g.flatten(self, unixfrom=unixfrom) return fp.getvalue() def is_multipart(self): ! """Return True if the message consists of multiple parts.""" ! if isinstance(self._payload, ListType): ! return True ! return False # *************** *** 83,116 **** If the current payload is empty, then the current payload will be made a scalar, set to the given value. """ if self._payload is None: self._payload = payload ! elif type(self._payload) is ListType: self._payload.append(payload) elif self.get_main_type() not in (None, 'multipart'): raise Errors.MultipartConversionError( ! 'Message main Content-Type: must be "multipart" or missing') else: self._payload = [self._payload, payload] ! # A useful synonym ! attach = add_payload ! def get_payload(self, i=None, decode=0): ! """Return the current payload exactly as is. ! Optional i returns that index into the payload. ! Optional decode is a flag indicating whether the payload should be ! decoded or not, according to the Content-Transfer-Encoding: header. ! When true and the message is not a multipart, the payload will be ! decoded if this header's value is `quoted-printable' or `base64'. If ! some other encoding is used, or the header is missing, the payload is ! returned as-is (undecoded). If the message is a multipart and the ! decode flag is true, then None is returned. """ if i is None: payload = self._payload ! elif type(self._payload) is not ListType: raise TypeError, i else: --- 131,180 ---- If the current payload is empty, then the current payload will be made a scalar, set to the given value. + + Note: This method is deprecated. Use .attach() instead. """ + warnings.warn('add_payload() is deprecated, use attach() instead.', + DeprecationWarning, 2) if self._payload is None: self._payload = payload ! elif isinstance(self._payload, ListType): self._payload.append(payload) elif self.get_main_type() not in (None, 'multipart'): raise Errors.MultipartConversionError( ! 'Message main content type must be "multipart" or missing') else: self._payload = [self._payload, payload] ! def attach(self, payload): ! """Add the given payload to the current payload. ! The current payload will always be a list of objects after this method ! is called. If you want to set the payload to a scalar object, use ! set_payload() instead. ! """ ! if self._payload is None: ! self._payload = [payload] ! else: ! self._payload.append(payload) ! def get_payload(self, i=None, decode=False): ! """Return a reference to the payload. ! The payload will either be a list object or a string. If you mutate ! the list object, you modify the message's payload in place. Optional ! i returns that index into the payload. ! ! Optional decode is a flag (defaulting to False) indicating whether the ! payload should be decoded or not, according to the ! Content-Transfer-Encoding header. When True and the message is not a ! multipart, the payload will be decoded if this header's value is ! `quoted-printable' or `base64'. If some other encoding is used, or ! the header is missing, the payload is returned as-is (undecoded). If ! the message is a multipart and the decode flag is True, then None is ! returned. """ if i is None: payload = self._payload ! elif not isinstance(self._payload, ListType): raise TypeError, i else: *************** *** 128,135 **** return payload ! def set_payload(self, payload): ! """Set the payload to the given value.""" self._payload = payload # --- 192,249 ---- return payload + def set_payload(self, payload, charset=None): + """Set the payload to the given value. ! Optional charset sets the message's default character set. See ! set_charset() for details. ! """ self._payload = payload + if charset is not None: + self.set_charset(charset) + + def set_charset(self, charset): + """Set the charset of the payload to a given character set. + + charset can be a Charset instance, a string naming a character set, or + None. If it is a string it will be converted to a Charset instance. + If charset is None, the charset parameter will be removed from the + Content-Type field. Anything else will generate a TypeError. + + The message will be assumed to be of type text/* encoded with + charset.input_charset. It will be converted to charset.output_charset + and encoded properly, if needed, when generating the plain text + representation of the message. MIME headers (MIME-Version, + Content-Type, Content-Transfer-Encoding) will be added as needed. + + """ + if charset is None: + self.del_param('charset') + self._charset = None + return + if isinstance(charset, StringType): + charset = Charset.Charset(charset) + if not isinstance(charset, Charset.Charset): + raise TypeError, charset + # BAW: should we accept strings that can serve as arguments to the + # Charset constructor? + self._charset = charset + if not self.has_key('MIME-Version'): + self.add_header('MIME-Version', '1.0') + if not self.has_key('Content-Type'): + self.add_header('Content-Type', 'text/plain', + charset=charset.get_output_charset()) + else: + self.set_param('charset', charset.get_output_charset()) + if not self.has_key('Content-Transfer-Encoding'): + cte = charset.get_body_encoding() + if callable(cte): + cte(self) + else: + self.add_header('Content-Transfer-Encoding', cte) + + def get_charset(self): + """Return the Charset instance associated with the message's payload. + """ + return self._charset # *************** *** 171,176 **** self._headers = newheaders ! def __contains__(self, key): ! return key.lower() in [k.lower() for k, v in self._headers] def has_key(self, name): --- 285,290 ---- self._headers = newheaders ! def __contains__(self, name): ! return name.lower() in [k.lower() for k, v in self._headers] def has_key(self, name): *************** *** 183,188 **** These will be sorted in the order they appeared in the original ! message, and may contain duplicates. Any fields deleted and ! re-inserted are always appended to the header list. """ return [k for k, v in self._headers] --- 297,303 ---- These will be sorted in the order they appeared in the original ! message, or were added to the message, and may contain duplicates. ! Any fields deleted and re-inserted are always appended to the header ! list. """ return [k for k, v in self._headers] *************** *** 192,197 **** These will be sorted in the order they appeared in the original ! message, and may contain duplicates. Any fields deleted and ! re-inserted are always appended to the header list. """ return [v for k, v in self._headers] --- 307,313 ---- These will be sorted in the order they appeared in the original ! message, or were added to the message, and may contain duplicates. ! Any fields deleted and re-inserted are always appended to the header ! list. """ return [v for k, v in self._headers] *************** *** 201,206 **** These will be sorted in the order they appeared in the original ! message, and may contain duplicates. Any fields deleted and ! re-inserted are always appended to the header list. """ return self._headers[:] --- 317,323 ---- These will be sorted in the order they appeared in the original ! message, or were added to the message, and may contain duplicates. ! Any fields deleted and re-inserted are always appended to the header ! list. """ return self._headers[:] *************** *** 251,255 **** msg.add_header('content-disposition', 'attachment', filename='bud.gif') - """ parts = [] --- 368,371 ---- *************** *** 258,271 **** parts.append(k.replace('_', '-')) else: ! parts.append('%s="%s"' % (k.replace('_', '-'), v)) if _value is not None: parts.insert(0, _value) self._headers.append((_name, SEMISPACE.join(parts))) def get_type(self, failobj=None): """Returns the message's content type. The returned string is coerced to lowercase and returned as a single ! string of the form `maintype/subtype'. If there was no Content-Type: header in the message, failobj is returned (defaults to None). """ --- 374,407 ---- parts.append(k.replace('_', '-')) else: ! parts.append(_formatparam(k.replace('_', '-'), v)) if _value is not None: parts.insert(0, _value) self._headers.append((_name, SEMISPACE.join(parts))) + def replace_header(self, _name, _value): + """Replace a header. + + Replace the first matching header found in the message, retaining + header order and case. If no matching header was found, a KeyError is + raised. + """ + _name = _name.lower() + for i, (k, v) in zip(range(len(self._headers)), self._headers): + if k.lower() == _name: + self._headers[i] = (k, _value) + break + else: + raise KeyError, _name + + # + # These methods are silently deprecated in favor of get_content_type() and + # friends (see below). They will be noisily deprecated in email 3.0. + # + def get_type(self, failobj=None): """Returns the message's content type. The returned string is coerced to lowercase and returned as a single ! string of the form `maintype/subtype'. If there was no Content-Type header in the message, failobj is returned (defaults to None). """ *************** *** 274,278 **** if value is missing: return failobj ! return paramre.split(value)[0].lower() def get_main_type(self, failobj=None): --- 410,414 ---- if value is missing: return failobj ! return paramre.split(value)[0].lower().strip() def get_main_type(self, failobj=None): *************** *** 282,289 **** if ctype is missing: return failobj ! parts = ctype.split('/') ! if len(parts) > 0: ! return ctype.split('/')[0] ! return failobj def get_subtype(self, failobj=None): --- 418,424 ---- if ctype is missing: return failobj ! if ctype.count('/') <> 1: ! return failobj ! return ctype.split('/')[0] def get_subtype(self, failobj=None): *************** *** 293,300 **** if ctype is missing: return failobj ! parts = ctype.split('/') ! if len(parts) > 1: ! return ctype.split('/')[1] ! return failobj def _get_params_preserve(self, failobj, header): --- 428,498 ---- if ctype is missing: return failobj ! if ctype.count('/') <> 1: ! return failobj ! return ctype.split('/')[1] ! ! # ! # Use these three methods instead of the three above. ! # ! ! def get_content_type(self): ! """Return the message's content type. ! ! The returned string is coerced to lower case of the form ! `maintype/subtype'. If there was no Content-Type header in the ! message, the default type as given by get_default_type() will be ! returned. Since according to RFC 2045, messages always have a default ! type this will always return a value. ! ! RFC 2045 defines a message's default type to be text/plain unless it ! appears inside a multipart/digest container, in which case it would be ! message/rfc822. ! """ ! missing = [] ! value = self.get('content-type', missing) ! if value is missing: ! # This should have no parameters ! return self.get_default_type() ! ctype = paramre.split(value)[0].lower().strip() ! # RFC 2045, section 5.2 says if its invalid, use text/plain ! if ctype.count('/') <> 1: ! return 'text/plain' ! return ctype ! ! def get_content_maintype(self): ! """Return the message's main content type. ! ! This is the `maintype' part of the string returned by ! get_content_type(). ! """ ! ctype = self.get_content_type() ! return ctype.split('/')[0] ! ! def get_content_subtype(self): ! """Returns the message's sub-content type. ! ! This is the `subtype' part of the string returned by ! get_content_type(). ! """ ! ctype = self.get_content_type() ! return ctype.split('/')[1] ! ! def get_default_type(self): ! """Return the `default' content type. ! ! Most messages have a default content type of text/plain, except for ! messages that are subparts of multipart/digest containers. Such ! subparts have a default content type of message/rfc822. ! """ ! return self._default_type ! ! def set_default_type(self, ctype): ! """Set the `default' content type. ! ! ctype should be either "text/plain" or "message/rfc822", although this ! is not enforced. The default content type is not stored in the ! Content-Type header. ! """ ! self._default_type = ctype def _get_params_preserve(self, failobj, header): *************** *** 309,331 **** try: name, val = p.split('=', 1) except ValueError: # Must have been a bare attribute ! name = p val = '' params.append((name, val)) return params ! def get_params(self, failobj=None, header='content-type'): ! """Return the message's Content-Type: parameters, as a list. The elements of the returned list are 2-tuples of key/value pairs, as split on the `=' sign. The left hand side of the `=' is the key, while the right hand side is the value. If there is no `=' sign in ! the parameter the value is the empty string. The value is always ! unquoted. ! Optional failobj is the object to return if there is no Content-Type: header. Optional header is the header to search instead of ! Content-Type: """ missing = [] --- 507,532 ---- try: name, val = p.split('=', 1) + name = name.strip() + val = val.strip() except ValueError: # Must have been a bare attribute ! name = p.strip() val = '' params.append((name, val)) + params = Utils.decode_params(params) return params ! def get_params(self, failobj=None, header='content-type', unquote=True): ! """Return the message's Content-Type parameters, as a list. The elements of the returned list are 2-tuples of key/value pairs, as split on the `=' sign. The left hand side of the `=' is the key, while the right hand side is the value. If there is no `=' sign in ! the parameter the value is the empty string. The value is as ! described in the get_param() method. ! Optional failobj is the object to return if there is no Content-Type header. Optional header is the header to search instead of ! Content-Type. If unquote is True, the value is unquoted. """ missing = [] *************** *** 333,347 **** if params is missing: return failobj ! return [(k, Utils.unquote(v)) for k, v in params] ! def get_param(self, param, failobj=None, header='content-type'): ! """Return the parameter value if found in the Content-Type: header. ! Optional failobj is the object to return if there is no Content-Type: ! header. Optional header is the header to search instead of ! Content-Type: ! Parameter keys are always compared case insensitively. Values are ! always unquoted. """ if not self.has_key(header): --- 534,564 ---- if params is missing: return failobj ! if unquote: ! return [(k, _unquotevalue(v)) for k, v in params] ! else: ! return params ! def get_param(self, param, failobj=None, header='content-type', ! unquote=True): ! """Return the parameter value if found in the Content-Type header. ! Optional failobj is the object to return if there is no Content-Type ! header, or the Content-Type header has no such parameter. Optional ! header is the header to search instead of Content-Type. ! Parameter keys are always compared case insensitively. The return ! value can either be a string, or a 3-tuple if the parameter was RFC ! 2231 encoded. When it's a 3-tuple, the elements of the value are of ! the form (CHARSET, LANGUAGE, VALUE), where LANGUAGE may be the empty ! string. Your application should be prepared to deal with these, and ! can convert the parameter to a Unicode string like so: ! ! param = msg.get_param('foo') ! if isinstance(param, tuple): ! param = unicode(param[2], param[0]) ! ! In any case, the parameter value (either the returned string, or the ! VALUE item in the 3-tuple) is always unquoted, unless unquote is set ! to False. """ if not self.has_key(header): *************** *** 349,359 **** for k, v in self._get_params_preserve(failobj, header): if k.lower() == param.lower(): ! return Utils.unquote(v) return failobj def get_filename(self, failobj=None): """Return the filename associated with the payload if present. ! The filename is extracted from the Content-Disposition: header's `filename' parameter, and it is unquoted. """ --- 566,681 ---- for k, v in self._get_params_preserve(failobj, header): if k.lower() == param.lower(): ! if unquote: ! return _unquotevalue(v) ! else: ! return v return failobj + def set_param(self, param, value, header='Content-Type', requote=True, + charset=None, language=''): + """Set a parameter in the Content-Type header. + + If the parameter already exists in the header, its value will be + replaced with the new value. + + If header is Content-Type and has not yet been defined for this + message, it will be set to "text/plain" and the new parameter and + value will be appended as per RFC 2045. + + An alternate header can specified in the header argument, and all + parameters will be quoted as necessary unless requote is False. + + If charset is specified, the parameter will be encoded according to RFC + 2231. Optional language specifies the RFC 2231 language, defaulting + to the empty string. Both charset and language should be strings. + """ + if not isinstance(value, TupleType) and charset: + value = (charset, language, value) + + if not self.has_key(header) and header.lower() == 'content-type': + ctype = 'text/plain' + else: + ctype = self.get(header) + if not self.get_param(param, header=header): + if not ctype: + ctype = _formatparam(param, value, requote) + else: + ctype = SEMISPACE.join( + [ctype, _formatparam(param, value, requote)]) + else: + ctype = '' + for old_param, old_value in self.get_params(header=header, + unquote=requote): + append_param = '' + if old_param.lower() == param.lower(): + append_param = _formatparam(param, value, requote) + else: + append_param = _formatparam(old_param, old_value, requote) + if not ctype: + ctype = append_param + else: + ctype = SEMISPACE.join([ctype, append_param]) + if ctype <> self.get(header): + del self[header] + self[header] = ctype + + def del_param(self, param, header='content-type', requote=True): + """Remove the given parameter completely from the Content-Type header. + + The header will be re-written in place without the parameter or its + value. All values will be quoted as necessary unless requote is + False. Optional header specifies an alternative to the Content-Type + header. + """ + if not self.has_key(header): + return + new_ctype = '' + for p, v in self.get_params(header, unquote=requote): + if p.lower() <> param.lower(): + if not new_ctype: + new_ctype = _formatparam(p, v, requote) + else: + new_ctype = SEMISPACE.join([new_ctype, + _formatparam(p, v, requote)]) + if new_ctype <> self.get(header): + del self[header] + self[header] = new_ctype + + def set_type(self, type, header='Content-Type', requote=True): + """Set the main type and subtype for the Content-Type header. + + type must be a string in the form "maintype/subtype", otherwise a + ValueError is raised. + + This method replaces the Content-Type header, keeping all the + parameters in place. If requote is False, this leaves the existing + header's quoting as is. Otherwise, the parameters will be quoted (the + default). + + An alternative header can be specified in the header argument. When + the Content-Type header is set, we'll always also add a MIME-Version + header. + """ + # BAW: should we be strict? + if not type.count('/') == 1: + raise ValueError + # Set the Content-Type, you get a MIME-Version + if header.lower() == 'content-type': + del self['mime-version'] + self['MIME-Version'] = '1.0' + if not self.has_key(header): + self[header] = type + return + params = self.get_params(header, unquote=requote) + del self[header] + self[header] = type + # Skip the first param; it's the old type. + for p, v in params[1:]: + self.set_param(p, v, header, requote) + def get_filename(self, failobj=None): """Return the filename associated with the payload if present. ! The filename is extracted from the Content-Disposition header's `filename' parameter, and it is unquoted. """ *************** *** 362,371 **** if filename is missing: return failobj ! return Utils.unquote(filename.strip()) def get_boundary(self, failobj=None): """Return the boundary associated with the payload if present. ! The boundary is extracted from the Content-Type: header's `boundary' parameter, and it is unquoted. """ --- 684,699 ---- if filename is missing: return failobj ! if isinstance(filename, TupleType): ! # It's an RFC 2231 encoded parameter ! newvalue = _unquotevalue(filename) ! return unicode(newvalue[2], newvalue[0]) ! else: ! newvalue = _unquotevalue(filename.strip()) ! return newvalue def get_boundary(self, failobj=None): """Return the boundary associated with the payload if present. ! The boundary is extracted from the Content-Type header's `boundary' parameter, and it is unquoted. """ *************** *** 374,409 **** if boundary is missing: return failobj ! return Utils.unquote(boundary.strip()) def set_boundary(self, boundary): ! """Set the boundary parameter in Content-Type: to 'boundary'. ! This is subtly different than deleting the Content-Type: header and adding a new one with a new boundary parameter via add_header(). The main difference is that using the set_boundary() method preserves the ! order of the Content-Type: header in the original message. ! HeaderParseError is raised if the message has no Content-Type: header. """ missing = [] params = self._get_params_preserve(missing, 'content-type') if params is missing: ! # There was no Content-Type: header, and we don't know what type # to set it to, so raise an exception. ! raise Errors.HeaderParseError, 'No Content-Type: header found' newparams = [] ! foundp = 0 for pk, pv in params: if pk.lower() == 'boundary': newparams.append(('boundary', '"%s"' % boundary)) ! foundp = 1 else: newparams.append((pk, pv)) if not foundp: ! # The original Content-Type: header had no boundary attribute. # Tack one one the end. BAW: should we raise an exception # instead??? newparams.append(('boundary', '"%s"' % boundary)) ! # Replace the existing Content-Type: header with the new value newheaders = [] for h, v in self._headers: --- 702,740 ---- if boundary is missing: return failobj ! if isinstance(boundary, TupleType): ! # RFC 2231 encoded, so decode. It better end up as ascii ! return unicode(boundary[2], boundary[0]).encode('us-ascii') ! return _unquotevalue(boundary.strip()) def set_boundary(self, boundary): ! """Set the boundary parameter in Content-Type to 'boundary'. ! This is subtly different than deleting the Content-Type header and adding a new one with a new boundary parameter via add_header(). The main difference is that using the set_boundary() method preserves the ! order of the Content-Type header in the original message. ! HeaderParseError is raised if the message has no Content-Type header. """ missing = [] params = self._get_params_preserve(missing, 'content-type') if params is missing: ! # There was no Content-Type header, and we don't know what type # to set it to, so raise an exception. ! raise Errors.HeaderParseError, 'No Content-Type header found' newparams = [] ! foundp = False for pk, pv in params: if pk.lower() == 'boundary': newparams.append(('boundary', '"%s"' % boundary)) ! foundp = True else: newparams.append((pk, pv)) if not foundp: ! # The original Content-Type header had no boundary attribute. # Tack one one the end. BAW: should we raise an exception # instead??? newparams.append(('boundary', '"%s"' % boundary)) ! # Replace the existing Content-Type header with the new value newheaders = [] for h, v in self._headers: *************** *** 421,445 **** self._headers = newheaders ! def walk(self): ! """Walk over the message tree, yielding each subpart. ! The walk is performed in depth-first order. This method is a ! generator. """ ! yield self ! if self.is_multipart(): ! for subpart in self.get_payload(): ! for subsubpart in subpart.walk(): ! yield subsubpart def get_charsets(self, failobj=None): """Return a list containing the charset(s) used in this message. ! The returned list of items describes the Content-Type: headers' charset parameter for this message and all the subparts in its payload. Each item will either be a string (the value of the charset parameter ! in the Content-Type: header of that part) or the value of the 'failobj' parameter (defaults to None), if the part does not have a main MIME type of "text", or the charset is not defined. --- 752,785 ---- self._headers = newheaders ! try: ! from email._compat22 import walk ! except SyntaxError: ! # Must be using Python 2.1 ! from email._compat21 import walk ! def get_content_charset(self, failobj=None): ! """Return the charset parameter of the Content-Type header. ! ! If there is no Content-Type header, or if that header has no charset ! parameter, failobj is returned. """ ! missing = [] ! charset = self.get_param('charset', missing) ! if charset is missing: ! return failobj ! if isinstance(charset, TupleType): ! # RFC 2231 encoded, so decode it, and it better end up as ascii. ! return unicode(charset[2], charset[0]).encode('us-ascii') ! return charset def get_charsets(self, failobj=None): """Return a list containing the charset(s) used in this message. ! The returned list of items describes the Content-Type headers' charset parameter for this message and all the subparts in its payload. Each item will either be a string (the value of the charset parameter ! in the Content-Type header of that part) or the value of the 'failobj' parameter (defaults to None), if the part does not have a main MIME type of "text", or the charset is not defined. *************** *** 449,451 **** message will still return a list of length 1. """ ! return [part.get_param('charset', failobj) for part in self.walk()] --- 789,791 ---- message will still return a list of length 1. """ ! return [part.get_content_charset(failobj) for part in self.walk()] Index: Parser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Parser.py,v retrieving revision 1.5.10.1 retrieving revision 1.5.10.2 diff -C2 -d -r1.5.10.1 -r1.5.10.2 *** Parser.py 28 Jan 2002 15:27:20 -0000 1.5.10.1 --- Parser.py 4 Oct 2002 17:24:24 -0000 1.5.10.2 *************** *** 5,22 **** """ from cStringIO import StringIO from types import ListType ! # Intrapackage imports ! import Errors ! import Message EMPTYSTRING = '' NL = '\n' class Parser: ! def __init__(self, _class=Message.Message): """Parser of RFC 2822 and MIME email messages. --- 5,28 ---- """ + import re from cStringIO import StringIO from types import ListType ! from email import Errors ! from email import Message EMPTYSTRING = '' NL = '\n' + try: + True, False + except NameError: + True = 1 + False = 0 + class Parser: ! def __init__(self, _class=Message.Message, strict=False): """Parser of RFC 2822 and MIME email messages. *************** *** 33,47 **** must be created. This class must have a constructor that can take zero arguments. Default is Message.Message. """ self._class = _class ! def parse(self, fp): root = self._class() self._parseheaders(root, fp) ! self._parsebody(root, fp) return root ! def parsestr(self, text): ! return self.parse(StringIO(text)) def _parseheaders(self, container, fp): --- 39,75 ---- must be created. This class must have a constructor that can take zero arguments. Default is Message.Message. + + Optional strict tells the parser to be strictly RFC compliant or to be + more forgiving in parsing of ill-formatted MIME documents. When + non-strict mode is used, the parser will try to make up for missing or + erroneous boundaries and other peculiarities seen in the wild. + Default is non-strict parsing. """ self._class = _class + self._strict = strict ! def parse(self, fp, headersonly=False): ! """Create a message structure from the data in a file. ! ! Reads all the data from the file and returns the root of the message ! structure. Optional headersonly is a flag specifying whether to stop ! parsing after reading the headers or not. The default is False, ! meaning it parses the entire contents of the file. ! """ root = self._class() self._parseheaders(root, fp) ! if not headersonly: ! self._parsebody(root, fp) return root ! def parsestr(self, text, headersonly=False): ! """Create a message structure from a string. ! ! Returns the root of the message structure. Optional headersonly is a ! flag specifying whether to stop parsing after reading the headers or ! not. The default is False, meaning it parses the entire contents of ! the file. ! """ ! return self.parse(StringIO(text), headersonly=headersonly) def _parseheaders(self, container, fp): *************** *** 51,58 **** lastvalue = [] lineno = 0 ! while 1: ! line = fp.readline()[:-1] ! if not line or not line.strip(): break lineno += 1 # Check for initial Unix From_ line --- 79,93 ---- lastvalue = [] lineno = 0 ! while True: ! # Don't strip the line before we test for the end condition, ! # because whitespace-only header lines are RFC compliant ! # continuation lines. ! line = fp.readline() ! if not line: break + line = line.splitlines()[0] + if not line: + break + # Ignore the trailing newline lineno += 1 # Check for initial Unix From_ line *************** *** 61,68 **** container.set_unixfrom(line) continue ! else: raise Errors.HeaderParseError( 'Unix-from in headers after first rfc822 header') ! # # Header continuation line if line[0] in ' \t': --- 96,106 ---- container.set_unixfrom(line) continue ! elif self._strict: raise Errors.HeaderParseError( 'Unix-from in headers after first rfc822 header') ! else: ! # ignore the wierdly placed From_ line ! # XXX: maybe set unixfrom anyway? or only if not already? ! continue # Header continuation line if line[0] in ' \t': *************** *** 79,84 **** i = line.find(':') if i < 0: ! raise Errors.HeaderParseError( ! 'Not a header, not a continuation') if lastheader: container[lastheader] = NL.join(lastvalue) --- 117,129 ---- i = line.find(':') if i < 0: ! if self._strict: ! raise Errors.HeaderParseError( ! "Not a header, not a continuation: ``%s''"%line) ! elif lineno == 1 and line.startswith('--'): ! # allow through duplicate boundary tags. ! continue ! else: ! raise Errors.HeaderParseError( ! "Not a header, not a continuation: ``%s''"%line) if lastheader: container[lastheader] = NL.join(lastvalue) *************** *** 101,143 **** preamble = epilogue = None # Split into subparts. The first boundary we're looking for won't ! # have the leading newline since we're at the start of the body ! # text. separator = '--' + boundary payload = fp.read() ! start = payload.find(separator) ! if start < 0: ! raise Errors.BoundaryError( ! "Couldn't find starting boundary: %s" % boundary) if start > 0: # there's some pre-MIME boundary preamble preamble = payload[0:start] ! start += len(separator) + 1 + isdigest ! terminator = payload.find('\n' + separator + '--', start) ! if terminator < 0: raise Errors.BoundaryError( ! "Couldn't find terminating boundary: %s" % boundary) ! if terminator+len(separator)+3 < len(payload): ! # there's some post-MIME boundary epilogue ! epilogue = payload[terminator+len(separator)+3:] # We split the textual payload on the boundary separator, which ! # includes the trailing newline. If the container is a # multipart/digest then the subparts are by default message/rfc822 ! # instead of text/plain. In that case, they'll have an extra ! # newline before the headers to distinguish the message's headers ! # from the subpart headers. ! if isdigest: ! separator += '\n\n' ! else: ! separator += '\n' ! parts = payload[start:terminator].split('\n' + separator) for part in parts: ! msgobj = self.parsestr(part) container.preamble = preamble container.epilogue = epilogue ! # Ensure that the container's payload is a list ! if not isinstance(container.get_payload(), ListType): ! container.set_payload([msgobj]) ! else: ! container.add_payload(msgobj) elif container.get_type() == 'message/delivery-status': # This special kind of type contains blocks of headers separated --- 146,236 ---- preamble = epilogue = None # Split into subparts. The first boundary we're looking for won't ! # always have a leading newline since we're at the start of the ! # body text, and there's not always a preamble before the first ! # boundary. separator = '--' + boundary payload = fp.read() ! # We use an RE here because boundaries can have trailing ! # whitespace. ! mo = re.search( ! r'(?P' + re.escape(separator) + r')(?P[ \t]*)', ! payload) ! if not mo: ! if self._strict: ! raise Errors.BoundaryError( ! "Couldn't find starting boundary: %s" % boundary) ! container.set_payload(payload) ! return ! start = mo.start() if start > 0: # there's some pre-MIME boundary preamble preamble = payload[0:start] ! # Find out what kind of line endings we're using ! start += len(mo.group('sep')) + len(mo.group('ws')) ! cre = re.compile('\r\n|\r|\n') ! mo = cre.search(payload, start) ! if mo: ! start += len(mo.group(0)) ! # We create a compiled regexp first because we need to be able to ! # specify the start position, and the module function doesn't ! # support this signature. :( ! cre = re.compile('(?P\r\n|\r|\n)' + ! re.escape(separator) + '--') ! mo = cre.search(payload, start) ! if mo: ! terminator = mo.start() ! linesep = mo.group('sep') ! if mo.end() < len(payload): ! # There's some post-MIME boundary epilogue ! epilogue = payload[mo.end():] ! elif self._strict: raise Errors.BoundaryError( ! "Couldn't find terminating boundary: %s" % boundary) ! else: ! # Handle the case of no trailing boundary. Check that it ends ! # in a blank line. Some cases (spamspamspam) don't even have ! # that! ! mo = re.search('(?P\r\n|\r|\n){2}$', payload) ! if not mo: ! mo = re.search('(?P\r\n|\r|\n)$', payload) ! if not mo: ! raise Errors.BoundaryError( ! 'No terminating boundary and no trailing empty line') ! linesep = mo.group('sep') ! terminator = len(payload) # We split the textual payload on the boundary separator, which ! # includes the trailing newline. If the container is a # multipart/digest then the subparts are by default message/rfc822 ! # instead of text/plain. In that case, they'll have a optional ! # block of MIME headers, then an empty line followed by the ! # message headers. ! parts = re.split( ! linesep + re.escape(separator) + r'[ \t]*' + linesep, ! payload[start:terminator]) for part in parts: ! if isdigest: ! if part[0] == linesep: ! # There's no header block so create an empty message ! # object as the container, and lop off the newline so ! # we can parse the sub-subobject ! msgobj = self._class() ! part = part[1:] ! else: ! parthdrs, part = part.split(linesep+linesep, 1) ! # msgobj in this case is the "message/rfc822" container ! msgobj = self.parsestr(parthdrs, headersonly=1) ! # while submsgobj is the message itself ! submsgobj = self.parsestr(part) ! msgobj.attach(submsgobj) ! msgobj.set_default_type('message/rfc822') ! else: ! msgobj = self.parsestr(part) container.preamble = preamble container.epilogue = epilogue ! container.attach(msgobj) ! elif container.get_main_type() == 'multipart': ! # Very bad. A message is a multipart with no boundary! ! raise Errors.BoundaryError( ! 'multipart message with no defined boundary') elif container.get_type() == 'message/delivery-status': # This special kind of type contains blocks of headers separated *************** *** 145,149 **** # separate Message object blocks = [] ! while 1: blockmsg = self._class() self._parseheaders(blockmsg, fp) --- 238,242 ---- # separate Message object blocks = [] ! while True: blockmsg = self._class() self._parseheaders(blockmsg, fp) *************** *** 161,167 **** msg = self._class() self._parsebody(msg, fp) ! container.add_payload(msg) else: ! container.add_payload(fp.read()) --- 254,260 ---- msg = self._class() self._parsebody(msg, fp) ! container.attach(msg) else: ! container.set_payload(fp.read()) Index: Utils.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Utils.py,v retrieving revision 1.9 retrieving revision 1.9.6.1 diff -C2 -d -r1.9 -r1.9.6.1 *** Utils.py 3 Dec 2001 19:26:40 -0000 1.9 --- Utils.py 4 Oct 2002 17:24:24 -0000 1.9.6.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 6,24 **** import time import re ! from rfc822 import unquote, quote, parseaddr ! from rfc822 import dump_address_pair ! from rfc822 import AddrlistClass as _AddrlistClass ! from rfc822 import parsedate_tz, parsedate, mktime_tz - from quopri import decodestring as _qdecode import base64 # Intrapackage imports ! from Encoders import _bencode, _qencode COMMASPACE = ', ' UEMPTYSTRING = u'' --- 6,60 ---- import time + import socket import re + import random + import os + import warnings + from cStringIO import StringIO + from types import ListType ! from rfc822 import quote ! from rfc822 import AddressList as _AddressList ! from rfc822 import mktime_tz ! ! # We need wormarounds for bugs in these methods in older Pythons (see below) ! from rfc822 import parsedate as _parsedate ! from rfc822 import parsedate_tz as _parsedate_tz ! ! try: ! True, False ! except NameError: ! True = 1 ! False = 0 ! ! try: ! from quopri import decodestring as _qdecode ! except ImportError: ! # Python 2.1 doesn't have quopri.decodestring() ! def _qdecode(s): ! import quopri as _quopri ! ! if not s: ! return s ! infp = StringIO(s) ! outfp = StringIO() ! _quopri.decode(infp, outfp) ! value = outfp.getvalue() ! if not s.endswith('\n') and value.endswith('\n'): ! return value[:-1] ! return value import base64 # Intrapackage imports ! from email.Encoders import _bencode, _qencode COMMASPACE = ', ' + EMPTYSTRING = '' UEMPTYSTRING = u'' + CRLF = '\r\n' + + specialsre = re.compile(r'[][\()<>@,:;".]') + escapesre = re.compile(r'[][\()"]') *************** *** 37,43 **** if not s: return s - hasnewline = (s[-1] == '\n') value = base64.decodestring(s) ! if not hasnewline and value[-1] == '\n': return value[:-1] return value --- 73,78 ---- if not s: return s value = base64.decodestring(s) ! if not s.endswith('\n') and value.endswith('\n'): return value[:-1] return value *************** *** 45,53 **** def getaddresses(fieldvalues): """Return a list of (REALNAME, EMAIL) for each fieldvalue.""" all = COMMASPACE.join(fieldvalues) ! a = _AddrlistClass(all) ! return a.getaddrlist() --- 80,123 ---- + def fix_eols(s): + """Replace all line-ending characters with \r\n.""" + # Fix newlines with no preceding carriage return + s = re.sub(r'(?', name) + return '%s%s%s <%s>' % (quotes, name, quotes, address) + return address + + # For backwards compatibility + def dump_address_pair(pair): + warnings.warn('Use email.Utils.formataddr() instead', + DeprecationWarning, 2) + return formataddr(pair) + + + def getaddresses(fieldvalues): """Return a list of (REALNAME, EMAIL) for each fieldvalue.""" all = COMMASPACE.join(fieldvalues) ! a = _AddressList(all) ! return a.addresslist *************** *** 65,92 **** def decode(s): ! """Return a decoded string according to RFC 2047, as a unicode string.""" rtn = [] ! parts = ecre.split(s, 1) ! while parts: ! # If there are less than 4 parts, it can't be encoded and we're done ! if len(parts) < 5: ! rtn.extend(parts) ! break ! # The first element is any non-encoded leading text ! rtn.append(parts[0]) ! charset = parts[1] ! encoding = parts[2].lower() ! atom = parts[3] ! # The next chunk to decode should be in parts[4] ! parts = ecre.split(parts[4]) ! # The encoding must be either `q' or `b', case-insensitive ! if encoding == 'q': ! func = _qdecode ! elif encoding == 'b': ! func = _bdecode else: ! func = _identity ! # Decode and get the unicode in the charset ! rtn.append(unicode(func(atom), charset)) # Now that we've decoded everything, we just need to join all the parts # together into the final string. --- 135,158 ---- def decode(s): ! """Return a decoded string according to RFC 2047, as a unicode string. ! ! NOTE: This function is deprecated. Use Header.decode_header() instead. ! """ ! warnings.warn('Use Header.decode_header() instead.', DeprecationWarning, 2) ! # Intra-package import here to avoid circular import problems. ! from email.Header import decode_header ! L = decode_header(s) ! if not isinstance(L, ListType): ! # s wasn't decoded ! return s ! rtn = [] ! for atom, charset in L: ! if charset is None: ! rtn.append(atom) else: ! # Convert the string to Unicode using the given encoding. Leave ! # Unicode conversion errors to strict. ! rtn.append(unicode(atom, charset)) # Now that we've decoded everything, we just need to join all the parts # together into the final string. *************** *** 97,100 **** --- 163,167 ---- def encode(s, charset='iso-8859-1', encoding='q'): """Encode a string according to RFC 2047.""" + warnings.warn('Use Header.Header.encode() instead.', DeprecationWarning, 2) encoding = encoding.lower() if encoding == 'q': *************** *** 108,112 **** ! def formatdate(timeval=None, localtime=0): """Returns a date string as specified by RFC 2822, e.g.: --- 175,179 ---- ! def formatdate(timeval=None, localtime=False): """Returns a date string as specified by RFC 2822, e.g.: *************** *** 116,120 **** gmtime() and localtime(), otherwise the current time is used. ! Optional localtime is a flag that when true, interprets timeval, and returns a date relative to the local timezone instead of UTC, properly taking daylight savings time into account. --- 183,187 ---- gmtime() and localtime(), otherwise the current time is used. ! Optional localtime is a flag that when True, interprets timeval, and returns a date relative to the local timezone instead of UTC, properly taking daylight savings time into account. *************** *** 151,152 **** --- 218,340 ---- now[0], now[3], now[4], now[5], zone) + + + + def make_msgid(idstring=None): + """Returns a string suitable for RFC 2822 compliant Message-ID, e.g: + + <20020201195627.33539.96671@nightshade.la.mastaler.com> + + Optional idstring if given is a string used to strengthen the + uniqueness of the message id. + """ + timeval = time.time() + utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval)) + pid = os.getpid() + randint = random.randrange(100000) + if idstring is None: + idstring = '' + else: + idstring = '.' + idstring + idhost = socket.getfqdn() + msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, idhost) + return msgid + + + + # These functions are in the standalone mimelib version only because they've + # subsequently been fixed in the latest Python versions. We use this to worm + # around broken older Pythons. + def parsedate(data): + if not data: + return None + return _parsedate(data) + + + def parsedate_tz(data): + if not data: + return None + return _parsedate_tz(data) + + + def parseaddr(addr): + addrs = _AddressList(addr).addresslist + if not addrs: + return '', '' + return addrs[0] + + + # rfc822.unquote() doesn't properly de-backslash-ify in Python pre-2.3. + def unquote(str): + """Remove quotes from a string.""" + if len(str) > 1: + if str.startswith('"') and str.endswith('"'): + return str[1:-1].replace('\\\\', '\\').replace('\\"', '"') + if str.startswith('<') and str.endswith('>'): + return str[1:-1] + return str + + + + # RFC2231-related functions - parameter encoding and decoding + def decode_rfc2231(s): + """Decode string according to RFC 2231""" + import urllib + charset, language, s = s.split("'", 2) + s = urllib.unquote(s) + return charset, language, s + + + def encode_rfc2231(s, charset=None, language=None): + """Encode string according to RFC 2231. + + If neither charset nor language is given, then s is returned as-is. If + charset is given but not language, the string is encoded using the empty + string for language. + """ + import urllib + s = urllib.quote(s, safe='') + if charset is None and language is None: + return s + if language is None: + language = '' + return "%s'%s'%s" % (charset, language, s) + + + rfc2231_continuation = re.compile(r'^(?P\w+)\*((?P[0-9]+)\*?)?$') + + def decode_params(params): + """Decode parameters list according to RFC 2231. + + params is a sequence of 2-tuples containing (content type, string value). + """ + new_params = [] + # maps parameter's name to a list of continuations + rfc2231_params = {} + # params is a sequence of 2-tuples containing (content_type, string value) + name, value = params[0] + new_params.append((name, value)) + # Cycle through each of the rest of the parameters. + for name, value in params[1:]: + value = unquote(value) + mo = rfc2231_continuation.match(name) + if mo: + name, num = mo.group('name', 'num') + if num is not None: + num = int(num) + rfc2231_param1 = rfc2231_params.setdefault(name, []) + rfc2231_param1.append((num, value)) + else: + new_params.append((name, '"%s"' % quote(value))) + if rfc2231_params: + for name, continuations in rfc2231_params.items(): + value = [] + # Sort by number + continuations.sort() + # And now append all values in num order + for num, continuation in continuations: + value.append(continuation) + charset, language, value = decode_rfc2231(EMPTYSTRING.join(value)) + new_params.append((name, + (charset, language, '"%s"' % quote(value)))) + return new_params Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/__init__.py,v retrieving revision 1.4 retrieving revision 1.4.10.1 diff -C2 -d -r1.4 -r1.4.10.1 *** __init__.py 9 Oct 2001 19:14:59 -0000 1.4 --- __init__.py 4 Oct 2002 17:24:24 -0000 1.4.10.1 *************** *** 1,3 **** ! # Copyright (C) 2001 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- 1,3 ---- ! # Copyright (C) 2001,2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) *************** *** 5,35 **** """ ! __version__ = '1.0' ! __all__ = ['Encoders', ! 'Errors', ! 'Generator', ! 'Iterators', ! 'MIMEAudio', ! 'MIMEBase', ! 'MIMEImage', ! 'MIMEMessage', ! 'MIMEText', ! 'Message', ! 'Parser', ! 'Utils', ! 'message_from_string', ! 'message_from_file', ! ] ! # Some convenience routines ! from Parser import Parser as _Parser ! from Message import Message as _Message ! def message_from_string(s, _class=_Message): ! return _Parser(_class).parsestr(s) ! def message_from_file(fp, _class=_Message): ! return _Parser(_class).parse(fp) --- 5,72 ---- """ ! __version__ = '2.4' ! __all__ = [ ! 'base64MIME', ! 'Charset', ! 'Encoders', ! 'Errors', ! 'Generator', ! 'Header', ! 'Iterators', ! 'Message', ! 'MIMEAudio', ! 'MIMEBase', ! 'MIMEImage', ! 'MIMEMessage', ! 'MIMEMultipart', ! 'MIMENonMultipart', ! 'MIMEText', ! 'Parser', ! 'quopriMIME', ! 'Utils', ! 'message_from_string', ! 'message_from_file', ! ] ! ! try: ! True, False ! except NameError: ! True = 1 ! False = 0 ! # Some convenience routines. Don't import Parser and Message as side-effects ! # of importing email since those cascadingly import most of the rest of the ! # email package. ! def message_from_string(s, _class=None, strict=False): ! """Parse a string into a Message object model. ! Optional _class and strict are passed to the Parser constructor. ! """ ! from email.Parser import Parser ! if _class is None: ! from email.Message import Message ! _class = Message ! return Parser(_class, strict=strict).parsestr(s) ! def message_from_file(fp, _class=None, strict=False): ! """Read a file and parse its contents into a Message object model. ! ! Optional _class and strict are passed to the Parser constructor. ! """ ! from email.Parser import Parser ! if _class is None: ! from email.Message import Message ! _class = Message ! return Parser(_class, strict=strict).parse(fp) ! ! ! ! # Patch encodings.aliases to recognize 'ansi_x3.4_1968' which isn't a standard ! # alias in Python 2.1.3, but is used by the email package test suite. ! from encodings.aliases import aliases # The aliases dictionary ! if not aliases.has_key('ansi_x3.4_1968'): ! aliases['ansi_x3.4_1968'] = 'ascii' ! del aliases # Not needed any more From barry@users.sourceforge.net Fri Oct 4 18:40:59 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Fri, 04 Oct 2002 10:40:59 -0700 Subject: [Python-checkins] python/dist/src/Lib/email/test __init__.py,NONE,1.1.2.1 test_email.py,NONE,1.17.2.1 test_email_codecs.py,NONE,1.3.2.1 test_email_torture.py,NONE,1.4.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email/test In directory usw-pr-cvs1:/tmp/cvs-serv19257/Lib/email/test Added Files: Tag: release22-maint __init__.py test_email.py test_email_codecs.py test_email_torture.py Log Message: Backporting of email 2.4 from Python 2.3. These are the backported tests and supporting files. --- NEW FILE: __init__.py --- # Copyright (C) 2002 Python Software Foundation # Author: barry@zope.com (Barry Warsaw) --- NEW FILE: test_email.py --- # Copyright (C) 2001,2002 Python Software Foundation # email package unit tests import sys import os import time import unittest import base64 import difflib from cStringIO import StringIO from types import StringType, ListType import warnings import email from email.Charset import Charset from email.Header import Header, decode_header, make_header from email.Parser import Parser, HeaderParser from email.Generator import Generator, DecodedGenerator [...2241 lines suppressed...] def _testclasses(): mod = sys.modules[__name__] return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] def suite(): suite = unittest.TestSuite() for testclass in _testclasses(): suite.addTest(unittest.makeSuite(testclass)) return suite def test_main(): for testclass in _testclasses(): run_unittest(testclass) if __name__ == '__main__': unittest.main(defaultTest='suite') --- NEW FILE: test_email_codecs.py --- # Copyright (C) 2002 Python Software Foundation # email package unit tests for (optional) Asian codecs import unittest from test.test_support import TestSkipped, run_unittest from email.test.test_email import TestEmailBase from email.Charset import Charset from email.Header import Header, decode_header # See if we have the Japanese codecs package installed try: unicode('foo', 'japanese.iso-2022-jp') except LookupError: raise TestSkipped, 'Optional Japanese codecs not installed' class TestEmailAsianCodecs(TestEmailBase): def test_japanese_codecs(self): eq = self.ndiffAssertEqual j = Charset("euc-jp") g = Charset("iso-8859-1") h = Header("Hello World!") jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' ghello = 'Gr\xfc\xdf Gott!' h.append(jhello, j) h.append(ghello, g) eq(h.encode(), 'Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?=\n =?iso-8859-1?q?Gr=FC=DF_Gott!?=') eq(decode_header(h.encode()), [('Hello World!', None), ('\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'), ('Gr\xfc\xdf Gott!', 'iso-8859-1')]) long = 'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9' h = Header(long, j, header_name="Subject") # test a very long header enc = h.encode() # BAW: The following used to pass. Sadly, the test afterwards is what # happens now. I've no idea which is right. Please, any Japanese and # RFC 2047 experts, please verify! ## eq(enc, '''\ ##=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYRsoQg==?= ## =?iso-2022-jp?b?GyRCITwlayRPO0oycTxUJE4+NRsoQg==?= ## =?iso-2022-jp?b?GyRCRyckckJUJEMkRiQkJF4kORsoQg==?=''') eq(enc, """\ =?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYRsoQg==?= =?iso-2022-jp?b?GyRCITwlayRPO0oycTxUJE4+NUcnJHJCVCRDJEYkJCReJDkbKEI=?=""") # BAW: same deal here. :( ## self.assertEqual( ## decode_header(enc), ## [("test-ja \x1b$B$XEj9F$5$l$?%a\x1b(B\x1b$B!<%k$O;J2q5\x1b(B\x1b$BG'$rBT$C$F$$$^$9\x1b(B", 'iso-2022-jp')]) self.assertEqual( decode_header(enc), [("test-ja \x1b$B$XEj9F$5$l$?%a\x1b(B\x1b$B!<%k$O;J2q5G'$rBT$C$F$$$^$9\x1b(B", 'iso-2022-jp')]) def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestEmailAsianCodecs)) return suite def test_main(): run_unittest(TestEmailAsianCodecs) if __name__ == '__main__': unittest.main(defaultTest='suite') --- NEW FILE: test_email_torture.py --- # Copyright (C) 2002 Python Software Foundation # # A torture test of the email package. This should not be run as part of the # standard Python test suite since it requires several meg of email messages # collected in the wild. These source messages are not checked into the # Python distro, but are available as part of the standalone email package at # http://sf.net/projects/mimelib import sys import os import unittest from cStringIO import StringIO from types import ListType from email.test.test_email import TestEmailBase from test.test_support import TestSkipped import email from email import __file__ as testfile from email.Iterators import _structure def openfile(filename): from os.path import join, dirname, abspath path = abspath(join(dirname(testfile), os.pardir, 'moredata', filename)) return open(path, 'rb') # Prevent this test from running in the Python distro try: openfile('crispin-torture.txt') except IOError: raise TestSkipped class TortureBase(TestEmailBase): def _msgobj(self, filename): fp = openfile(filename) try: msg = email.message_from_file(fp) finally: fp.close() return msg class TestCrispinTorture(TortureBase): # Mark Crispin's torture test from the SquirrelMail project def test_mondo_message(self): eq = self.assertEqual neq = self.ndiffAssertEqual msg = self._msgobj('crispin-torture.txt') payload = msg.get_payload() eq(type(payload), ListType) eq(len(payload), 12) eq(msg.preamble, None) eq(msg.epilogue, '\n\n') # Probably the best way to verify the message is parsed correctly is to # dump its structure and compare it against the known structure. fp = StringIO() _structure(msg, fp=fp) neq(fp.getvalue(), """\ multipart/mixed text/plain message/rfc822 multipart/alternative text/plain multipart/mixed text/richtext application/andrew-inset message/rfc822 audio/basic audio/basic image/pbm message/rfc822 multipart/mixed multipart/mixed text/plain audio/x-sun multipart/mixed image/gif image/gif application/x-be2 application/atomicmail audio/x-sun message/rfc822 multipart/mixed text/plain image/pgm text/plain message/rfc822 multipart/mixed text/plain image/pbm message/rfc822 application/postscript image/gif message/rfc822 multipart/mixed audio/basic audio/basic message/rfc822 multipart/mixed application/postscript text/plain message/rfc822 multipart/mixed text/plain multipart/parallel image/gif audio/basic application/atomicmail message/rfc822 audio/x-sun """) def _testclasses(): mod = sys.modules[__name__] return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] def suite(): suite = unittest.TestSuite() for testclass in _testclasses(): suite.addTest(unittest.makeSuite(testclass)) return suite def test_main(): for testclass in _testclasses(): test_support.run_unittest(testclass) if __name__ == '__main__': unittest.main(defaultTest='suite') From barry@users.sourceforge.net Fri Oct 4 18:40:59 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Fri, 04 Oct 2002 10:40:59 -0700 Subject: [Python-checkins] python/dist/src/Lib/email/test/data PyBanner048.gif,NONE,1.1.2.1 msg_01.txt,NONE,1.1.2.1 msg_02.txt,NONE,1.1.2.1 msg_03.txt,NONE,1.1.2.1 msg_04.txt,NONE,1.1.2.1 msg_05.txt,NONE,1.1.2.1 msg_06.txt,NONE,1.1.2.1 msg_07.txt,NONE,1.1.2.1 msg_08.txt,NONE,1.1.2.1 msg_09.txt,NONE,1.1.2.1 msg_10.txt,NONE,1.1.2.1 msg_11.txt,NONE,1.1.2.1 msg_12.txt,NONE,1.1.2.1 msg_13.txt,NONE,1.1.2.1 msg_14.txt,NONE,1.1.2.1 msg_15.txt,NONE,1.1.2.1 msg_16.txt,NONE,1.1.2.1 msg_17.txt,NONE,1.1.2.1 msg_18.txt,NONE,1.1.2.1 msg_19.txt,NONE,1.1.2.1 msg_20.txt,NONE,1.1.2.1 msg_21.txt,NONE,1.1.2.1 msg_22.txt,NONE,1.1.2.1 msg_23.txt,NONE,1.1.2.1 msg_24.txt,NONE,1.1.2.1 msg_25.txt,NONE,1.1.2.1 msg_26.txt,NONE,1.1.2.1 msg_27.txt,NONE,1.1.2.1 msg_28.txt,NONE,1.1.2.1 msg_29.txt,NONE,1.1.2.1 msg_30.txt,NONE,1.1.2.1 msg_31.txt,NONE,1.1.2.1 msg_32.txt,NONE,1.1.2.1 msg_33.txt,NONE,1.1.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email/test/data In directory usw-pr-cvs1:/tmp/cvs-serv19257/Lib/email/test/data Added Files: Tag: release22-maint PyBanner048.gif msg_01.txt msg_02.txt msg_03.txt msg_04.txt msg_05.txt msg_06.txt msg_07.txt msg_08.txt msg_09.txt msg_10.txt msg_11.txt msg_12.txt msg_13.txt msg_14.txt msg_15.txt msg_16.txt msg_17.txt msg_18.txt msg_19.txt msg_20.txt msg_21.txt msg_22.txt msg_23.txt msg_24.txt msg_25.txt msg_26.txt msg_27.txt msg_28.txt msg_29.txt msg_30.txt msg_31.txt msg_32.txt msg_33.txt Log Message: Backporting of email 2.4 from Python 2.3. These are the backported tests and supporting files. --- NEW FILE: PyBanner048.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: msg_01.txt --- Return-Path: Delivered-To: bbb@zzz.org Received: by mail.zzz.org (Postfix, from userid 889) id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15090.61304.110929.45684@aaa.zzz.org> From: bbb@ddd.com (John X. Doe) To: bbb@zzz.org Subject: This is a test message Date: Fri, 4 May 2001 14:05:44 -0400 Hi, Do you like this message? -Me --- NEW FILE: msg_02.txt --- MIME-version: 1.0 From: ppp-request@zzz.org Sender: ppp-admin@zzz.org To: ppp@zzz.org Subject: Ppp digest, Vol 1 #2 - 5 msgs Date: Fri, 20 Apr 2001 20:18:00 -0400 (EDT) X-Mailer: Mailman v2.0.4 X-Mailman-Version: 2.0.4 Content-Type: multipart/mixed; boundary="192.168.1.2.889.32614.987812255.500.21814" --192.168.1.2.889.32614.987812255.500.21814 Content-type: text/plain; charset=us-ascii Content-description: Masthead (Ppp digest, Vol 1 #2) Send Ppp mailing list submissions to ppp@zzz.org To subscribe or unsubscribe via the World Wide Web, visit http://www.zzz.org/mailman/listinfo/ppp or, via email, send a message with subject or body 'help' to ppp-request@zzz.org You can reach the person managing the list at ppp-admin@zzz.org When replying, please edit your Subject line so it is more specific than "Re: Contents of Ppp digest..." --192.168.1.2.889.32614.987812255.500.21814 Content-type: text/plain; charset=us-ascii Content-description: Today's Topics (5 msgs) Today's Topics: 1. testing #1 (Barry A. Warsaw) 2. testing #2 (Barry A. Warsaw) 3. testing #3 (Barry A. Warsaw) 4. testing #4 (Barry A. Warsaw) 5. testing #5 (Barry A. Warsaw) --192.168.1.2.889.32614.987812255.500.21814 Content-Type: multipart/digest; boundary="__--__--" --__--__-- Message: 1 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Date: Fri, 20 Apr 2001 20:16:13 -0400 To: ppp@zzz.org From: barry@digicool.com (Barry A. Warsaw) Subject: [Ppp] testing #1 Precedence: bulk hello --__--__-- Message: 2 Date: Fri, 20 Apr 2001 20:16:21 -0400 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: ppp@zzz.org From: barry@digicool.com (Barry A. Warsaw) Precedence: bulk hello --__--__-- Message: 3 Date: Fri, 20 Apr 2001 20:16:25 -0400 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: ppp@zzz.org From: barry@digicool.com (Barry A. Warsaw) Subject: [Ppp] testing #3 Precedence: bulk hello --__--__-- Message: 4 Date: Fri, 20 Apr 2001 20:16:28 -0400 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: ppp@zzz.org From: barry@digicool.com (Barry A. Warsaw) Subject: [Ppp] testing #4 Precedence: bulk hello --__--__-- Message: 5 Date: Fri, 20 Apr 2001 20:16:32 -0400 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: ppp@zzz.org From: barry@digicool.com (Barry A. Warsaw) Subject: [Ppp] testing #5 Precedence: bulk hello --__--__---- --192.168.1.2.889.32614.987812255.500.21814 Content-type: text/plain; charset=us-ascii Content-description: Digest Footer _______________________________________________ Ppp mailing list Ppp@zzz.org http://www.zzz.org/mailman/listinfo/ppp --192.168.1.2.889.32614.987812255.500.21814-- End of Ppp Digest --- NEW FILE: msg_03.txt --- Return-Path: Delivered-To: bbb@zzz.org Received: by mail.zzz.org (Postfix, from userid 889) id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) Message-ID: <15090.61304.110929.45684@aaa.zzz.org> From: bbb@ddd.com (John X. Doe) To: bbb@zzz.org Subject: This is a test message Date: Fri, 4 May 2001 14:05:44 -0400 Hi, Do you like this message? -Me --- NEW FILE: msg_04.txt --- Return-Path: Delivered-To: barry@python.org Received: by mail.python.org (Postfix, from userid 889) id C2BF0D37C6; Tue, 11 Sep 2001 00:05:05 -0400 (EDT) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="h90VIIIKmx" Content-Transfer-Encoding: 7bit Message-ID: <15261.36209.358846.118674@anthem.python.org> From: barry@python.org (Barry A. Warsaw) To: barry@python.org Subject: a simple multipart Date: Tue, 11 Sep 2001 00:05:05 -0400 X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid X-Attribution: BAW X-Oblique-Strategy: Make a door into a window --h90VIIIKmx Content-Type: text/plain Content-Disposition: inline; filename="msg.txt" Content-Transfer-Encoding: 7bit a simple kind of mirror to reflect upon our own --h90VIIIKmx Content-Type: text/plain Content-Disposition: inline; filename="msg.txt" Content-Transfer-Encoding: 7bit a simple kind of mirror to reflect upon our own --h90VIIIKmx-- --- NEW FILE: msg_05.txt --- From: foo Subject: bar To: baz MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="D1690A7AC1.996856090/mail.example.com" Message-Id: <20010803162810.0CA8AA7ACC@mail.example.com> This is a MIME-encapsulated message. --D1690A7AC1.996856090/mail.example.com Content-Type: text/plain Yadda yadda yadda --D1690A7AC1.996856090/mail.example.com Yadda yadda yadda --D1690A7AC1.996856090/mail.example.com Content-Type: message/rfc822 From: nobody@python.org Yadda yadda yadda --D1690A7AC1.996856090/mail.example.com-- --- NEW FILE: msg_06.txt --- Return-Path: Delivered-To: barry@python.org MIME-Version: 1.0 Content-Type: message/rfc822 Content-Description: forwarded message Content-Transfer-Encoding: 7bit Message-ID: <15265.9482.641338.555352@python.org> From: barry@zope.com (Barry A. Warsaw) Sender: barry@python.org To: barry@python.org Subject: forwarded message from Barry A. Warsaw Date: Thu, 13 Sep 2001 17:28:42 -0400 X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid X-Attribution: BAW X-Oblique-Strategy: Be dirty X-Url: http://barry.wooz.org MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-Path: Delivered-To: barry@python.org Message-ID: <15265.9468.713530.98441@python.org> From: barry@zope.com (Barry A. Warsaw) Sender: barry@python.org To: barry@python.org Subject: testing Date: Thu, 13 Sep 2001 17:28:28 -0400 X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid X-Attribution: BAW X-Oblique-Strategy: Spectrum analysis X-Url: http://barry.wooz.org --- NEW FILE: msg_07.txt --- MIME-Version: 1.0 From: Barry To: Dingus Lovers Subject: Here is your dingus fish Date: Fri, 20 Apr 2001 19:35:02 -0400 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: text/plain; charset="us-ascii" Hi there, This is the dingus fish. --BOUNDARY Content-Type: image/gif; name="dingusfish.gif" Content-Transfer-Encoding: base64 content-disposition: attachment; filename="dingusfish.gif" R0lGODdhAAEAAfAAAP///wAAACwAAAAAAAEAAQAC/oSPqcvtD6OctNqLs968+w+G4kiW5omm6sq2 7gvH8kzX9o3n+s73/g8MCofEovGITGICTKbyCV0FDNOo9SqpQqpOrJfXzTQj2vD3TGtqL+NtGQ2f qTXmxzuOd7WXdcc9DyjU53ewFni4s0fGhdiYaEhGBelICTNoV1j5NUnFcrmUqemjNifJVWpaOqaI oFq3SspZsSraE7sHq3jr1MZqWvi662vxV4tD+pvKW6aLDOCLyur8PDwbanyDeq0N3DctbQYeLDvR RY6t95m6UB0d3mwIrV7e2VGNvjjffukeJp4w7F65KecGFsTHQGAygOrgrWs1jt28Rc88KESYcGLA /obvTkH6p+CinWJiJmIMqXGQwH/y4qk0SYjgQTczT3ajKZGfuI0uJ4kkVI/DT5s3/ejkxI0aT4Y+ YTYgWbImUaXk9nlLmnSh1qJiJFl0OpUqRK4oOy7NyRQtHWofhoYVxkwWXKUSn0YsS+fUV6lhqfYb 6ayd3Z5qQdG1B7bvQzaJjwUV2lixMUZ7JVsOlfjWVr/3NB/uFvnySBN6Dcb6rGwaRM3wsormw5cC M9NxWy/bWdufudCvy8bOAjXjVVwta/uO21sE5RHBCzNFXtgq9ORtH4eYjVP4Yryo026nvkFmCeyA B29efV6ravCMK5JwWd5897Qrx7ll38o6iHDZ/rXPR//feevhF4l7wjUGX3xq1eeRfM4RSJGBIV1D z1gKPkfWag3mVBVvva1RlX5bAJTPR/2YqNtw/FkIYYEi/pIZiAdpcxpoHtmnYYoZtvhUftzdx5ZX JSKDW405zkGcZzzGZ6KEv4FI224oDmijlEf+xp6MJK5ojY/ASeVUR+wsKRuJ+XFZ5o7ZeEime8t1 ouUsU6YjF5ZtUihhkGfCdFQLWQFJ3UXxmElfhQnR+eCdcDbkFZp6vTRmj56ApCihn5QGpaToNZmR n3NVSpZcQpZ2KEONusaiCsKAug0wkQbJSFO+PTSjneGxOuFjPlUk3ovWvdIerjUg9ZGIOtGq/qeX eCYrrCX+1UPsgTKGGRSbzd5q156d/gpfbJxe66eD5iQKrXj7RGgruGxs62qebBHUKS32CKluCiqZ qh+pmehmEb71noAUoe5e9Zm17S7773V10pjrtG4CmuurCV/n6zLK5turWNhqOvFXbjhZrMD0YhKe wR0zOyuvsh6MWrGoIuzvyWu5y1WIFAqmJselypxXh6dKLNOKEB98L88bS2rkNqqlKzCNJp9c0G0j Gzh0iRrCbHSXmPR643QS+4rWhgFmnSbSuXCjS0xAOWkU2UdLqyuUNfHSFdUouy3bm5i5GnDM3tG8 doJ4r5tqu3pPbRSVfvs8uJzeNXhp3n4j/tZ42SwH7eaWUUOjc3qFV9453UHTXZfcLH+OeNs5g36x lBnHvTm7EbMbLeuaLncao8vWCXimfo1o+843Ak6y4ChNeGntvAYvfLK4ezmoyNIbNCLTCXO9ZV3A E8/s88RczPzDwI4Ob7XZyl7+9Miban29h+tJZPrE21wgvBphDfrrfPdCTPKJD/y98L1rZwHcV6Jq Zab0metpuNIX/qAFPoz171WUaUb4HAhBSzHuHfjzHb3kha/2Cctis/ORArVHNYfFyYRH2pYIRzic isVOfPWD1b6mRTqpCRBozzof6UZVvFXRxWIr3GGrEviGYgyPMfahheiSaLs/9QeFu7oZ/ndSY8DD ya9x+uPed+7mxN2IzIISBOMLFYWVqC3Pew1T2nFuuCiwZS5/v6II10i4t1OJcUH2U9zxKodHsGGv Oa+zkvNUYUOa/TCCRutF9MzDwdlUMJADTCGSbDQ5OV4PTamDoPEi6Ecc/RF5RWwkcdSXvSOaDWSn I9LlvubFTQpuc6JKXLcKeb+xdbKRBnwREemXyjg6ME65aJiOuBgrktzykfPLJBKR9ClMavJ62/Ff BlNIyod9yX9wcSXexnXFpvkrbXk64xsx5Db7wXKP5fSgsvwIMM/9631VLBfkmtbHRXpqmtei52hG pUwSlo+BASQoeILDOBgREECxBBh5/iYmNsQ9dIv5+OI++QkqdsJPc3uykz5fkM+OraeekcQF7X4n B5S67za5U967PmooGQhUXfF7afXyCD7ONdRe17QogYjVx38uLwtrS6nhTnm15LQUnu9E2uK6CNI/ 1HOABj0ESwOjut4FEpFQpdNAm4K2LHnDWHNcmKB2ioKBogysVZtMO2nSxUdZ8Yk2kJc7URioLVI0 YgmtIwZj4LoeKemgnOnbUdGnzZ4Oa6scqiolBGqS6RgWNLu0RMhcaE6rhhU4hiuqFXPAG8fGwTPW FKeLMtdVmXLSs5YJGF/YeVm7rREMlY3UYE+yCxbaMXX8y15m5zVHq6GOKDMynzII/jdUHdyVqIy0 ifX2+r/EgtZcvRzSb72gU9ui87M2VecjKildW/aFqaYhKoryUjfB/g4qtyVuc60xFDGmCxwjW+qu zjuwl2GkOWn66+3QiiEctvd04OVvcCVzjgT7lrkvjVGKKHmmlDUKowSeikb5kK/mJReuWOxONx+s ULsl+Lqb0CVn0SrVyJ6wt4t6yTeSCafhPhAf0OXn6L60UMxiLolFAtmN35S2Ob1lZpQ1r/n0Qb5D oQ1zJiRVDgF8N3Q8TYfbi3DyWCy3lT1nxyBs6FT3S2GOzWRlxwKvlRP0RPJA9SjxEy0UoEnkA+M4 cnzLMJrBGWLFEaaUb5lvpqbq/loOaU5+DFuHPxo82/OZuM8FXG3oVNZhtWpMpb/0Xu5m/LfLhHZQ 7yuVI0MqZ7NE43imC8jH3IwGZlbPm0xkJYs7+2U48hXTsFSMqgGDvai0kLxyynKNT/waj+q1c1tz GjOpPBgdCSq3UKZxCSsqFIY+O6JbAWGWcV1pwqLyj5sGqCF1xb1F3varUWqrJv6cN3PrUXzijtfZ FshpBL3Xwr4GIPvU2N8EjrJgS1zl21rbXQMXeXc5jjFyrhpCzijSv/RQtyPSzHCFMhlME95fHglt pRsX+dfSQjUeHAlpWzJ5iOo79Ldnaxai6bXTcGO3fp07ri7HLEmXXPlYi8bv/qVxvNcdra6m7Rlb 6JBTb5fd66VhFRjGArh2n7R1rDW4P5NOT9K0I183T2scYkeZ3q/VFyLb09U9ajzXBS8Kgkhc4mBS kYY9cy3Vy9lUnuNJH8HGIclUilwnBtjUOH0gteGOZ4c/XNrhXLSYDyxfnD8z1pDy7rYRvDolhnbe UMzxCZUs40s6s7UIvBnLgc0+vKuOkIXeOrDymlp+Zxra4MZLBbVrqD/jTJ597pDmnw5c4+DbyB88 9Cg9DodYcSuMZT/114pptqc/EuTjRPvH/z5slzI3tluOEBBLqOXLOX+0I5929tO97wkvl/atCz+y xJrdwteW2FNW/NSmBP+f/maYtVs/bYyBC7Ox3jsYZHL05CIrBa/nS+b3bHfiYm4Ueil1YZZSgAUI fFZ1dxUmeA2oQRQ3RuGXNGLFV9/XbGFGPV6kfzk1TBBCd+izc7q1H+OHMJwmaBX2IQNYVAKHYepV SSGCe6CnbYHHETKGNe43EDvFgZr0gB/nVHPHZ80VV1ojOiI3XDvYIkl4ayo4bxQIgrFXWTvBI0nH VElWMuw2aLUWCRHHf8ymVCHjFlJnOSojfevCYyyyZDH0IcvHhrsnQ5O1OsWzONuVVKIxSxiFZ/tR fKDAf6xFTnw4O9Qig2VCfW2hJQrmMOuHW0W3dLQmCMO2ccdUd/xyfflH/olTiHZVdGwb8nIwRzSE J15jFlOJuBZBZ4CiyHyd2IFylFlB+HgHhYabhWOGwYO1ZH/Og1dtQlFMk352CGRSIFTapnWQEUtN l4zv8S0aaCFDyGCBqDUxZYpxGHX01y/JuH1xhn7TOCnNCI4eKDs5WGX4R425F4vF1o3BJ4vO0otq I3rimI7jJY1jISqnBxknCIvruF83mF5wN4X7qGLIhR8A2Vg0yFERSIXn9Vv3GHy3Vj/WIkKddlYi yIMv2I/VMjTLpW7pt05SWIZR0RPyxpB4SIUM9lBPGBl0GC7oSEEwRYLe4pJpZY2P0zbI1n+Oc44w qY3PUnmF0ixjVpDD/mJ9wpOBGTVgXlaCaZiPcIWK5NiKBIiPdGaQ0TWGvAiG7nMchdZb7Vgf8zNi MuMyzRdy/lePe9iC4TRx7WhhOQI/QiSVNAmAa2lT/piFbuh7ofJoYSZzrSZ1bvmWw3eN2nKUPVky uPN5/VRfohRd0VYZoqhKIlU6TXYhJxmPUIloAwc1bPmHEpaZYZORHNlXUJM07hATwHR8MJYqkwWR WaIezFhxSFlc8/Fq82hEnpeRozg3ULhhr9lAGtVEkCg5ZNRuuVleBPaZadhG0ZgkyPmDOTOKzViM YgOcpukKqQcbjAWS0IleQ2ROjdh6A+md1qWdBRSX7iSYgFRTtRmBpJioieXJiHfJiMGIR9fJOn8I MSfXYhspn4ooSa2mSAj4n+8Bmg03fBJZoPOJgsVZRxu1oOMRPXYYjdqjihFaEoZpXBREanuJoRI6 cibFinq4ngUKh/wQd/H5ofYCZ0HJXR62opZFaAT0iFIZo4DIiUojkjeqKiuoZirKo5Y1a7AWckGa BkuYoD5lpDK6eUs6CkDqpETwl1EqpfhJpVeKpVl6EgUAADs= --BOUNDARY-- --- NEW FILE: msg_08.txt --- MIME-Version: 1.0 From: Barry Warsaw To: Dingus Lovers Subject: Lyrics Date: Fri, 20 Apr 2001 19:35:02 -0400 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: text/plain; charset="us-ascii" --BOUNDARY Content-Type: text/html; charset="iso-8859-1" --BOUNDARY Content-Type: text/plain; charset="iso-8859-2" --BOUNDARY Content-Type: text/plain; charset="koi8-r" --BOUNDARY-- --- NEW FILE: msg_09.txt --- MIME-Version: 1.0 From: Barry Warsaw To: Dingus Lovers Subject: Lyrics Date: Fri, 20 Apr 2001 19:35:02 -0400 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: text/plain; charset="us-ascii" --BOUNDARY Content-Type: text/html; charset="iso-8859-1" --BOUNDARY Content-Type: text/plain --BOUNDARY Content-Type: text/plain; charset="koi8-r" --BOUNDARY-- --- NEW FILE: msg_10.txt --- MIME-Version: 1.0 From: Barry Warsaw To: Dingus Lovers Subject: Lyrics Date: Fri, 20 Apr 2001 19:35:02 -0400 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit This is a 7bit encoded message. --BOUNDARY Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: Quoted-Printable =A1This is a Quoted Printable encoded message! --BOUNDARY Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: Base64 VGhpcyBpcyBhIEJhc2U2NCBlbmNvZGVkIG1lc3NhZ2Uu --BOUNDARY Content-Type: text/plain; charset="iso-8859-1" This has no Content-Transfer-Encoding: header. --BOUNDARY-- --- NEW FILE: msg_11.txt --- Content-Type: message/rfc822 MIME-Version: 1.0 Subject: The enclosing message Subject: An enclosed message Here is the body of the message. --- NEW FILE: msg_12.txt --- MIME-Version: 1.0 From: Barry Warsaw To: Dingus Lovers Subject: Lyrics Date: Fri, 20 Apr 2001 19:35:02 -0400 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: text/plain; charset="us-ascii" --BOUNDARY Content-Type: text/html; charset="iso-8859-1" --BOUNDARY Content-Type: multipart/mixed; boundary="ANOTHER" --ANOTHER Content-Type: text/plain; charset="iso-8859-2" --ANOTHER Content-Type: text/plain; charset="iso-8859-3" --ANOTHER-- --BOUNDARY Content-Type: text/plain; charset="us-ascii" --BOUNDARY Content-Type: text/plain; charset="koi8-r" --BOUNDARY-- --- NEW FILE: msg_13.txt --- MIME-Version: 1.0 From: Barry To: Dingus Lovers Subject: Here is your dingus fish Date: Fri, 20 Apr 2001 19:35:02 -0400 Content-Type: multipart/mixed; boundary="OUTER" --OUTER Content-Type: text/plain; charset="us-ascii" A text/plain part --OUTER Content-Type: multipart/mixed; boundary=BOUNDARY --BOUNDARY Content-Type: text/plain; charset="us-ascii" Hi there, This is the dingus fish. --BOUNDARY Content-Type: image/gif; name="dingusfish.gif" Content-Transfer-Encoding: base64 content-disposition: attachment; filename="dingusfish.gif" R0lGODdhAAEAAfAAAP///wAAACwAAAAAAAEAAQAC/oSPqcvtD6OctNqLs968+w+G4kiW5omm6sq2 7gvH8kzX9o3n+s73/g8MCofEovGITGICTKbyCV0FDNOo9SqpQqpOrJfXzTQj2vD3TGtqL+NtGQ2f qTXmxzuOd7WXdcc9DyjU53ewFni4s0fGhdiYaEhGBelICTNoV1j5NUnFcrmUqemjNifJVWpaOqaI oFq3SspZsSraE7sHq3jr1MZqWvi662vxV4tD+pvKW6aLDOCLyur8PDwbanyDeq0N3DctbQYeLDvR RY6t95m6UB0d3mwIrV7e2VGNvjjffukeJp4w7F65KecGFsTHQGAygOrgrWs1jt28Rc88KESYcGLA /obvTkH6p+CinWJiJmIMqXGQwH/y4qk0SYjgQTczT3ajKZGfuI0uJ4kkVI/DT5s3/ejkxI0aT4Y+ YTYgWbImUaXk9nlLmnSh1qJiJFl0OpUqRK4oOy7NyRQtHWofhoYVxkwWXKUSn0YsS+fUV6lhqfYb 6ayd3Z5qQdG1B7bvQzaJjwUV2lixMUZ7JVsOlfjWVr/3NB/uFvnySBN6Dcb6rGwaRM3wsormw5cC M9NxWy/bWdufudCvy8bOAjXjVVwta/uO21sE5RHBCzNFXtgq9ORtH4eYjVP4Yryo026nvkFmCeyA B29efV6ravCMK5JwWd5897Qrx7ll38o6iHDZ/rXPR//feevhF4l7wjUGX3xq1eeRfM4RSJGBIV1D z1gKPkfWag3mVBVvva1RlX5bAJTPR/2YqNtw/FkIYYEi/pIZiAdpcxpoHtmnYYoZtvhUftzdx5ZX JSKDW405zkGcZzzGZ6KEv4FI224oDmijlEf+xp6MJK5ojY/ASeVUR+wsKRuJ+XFZ5o7ZeEime8t1 ouUsU6YjF5ZtUihhkGfCdFQLWQFJ3UXxmElfhQnR+eCdcDbkFZp6vTRmj56ApCihn5QGpaToNZmR n3NVSpZcQpZ2KEONusaiCsKAug0wkQbJSFO+PTSjneGxOuFjPlUk3ovWvdIerjUg9ZGIOtGq/qeX eCYrrCX+1UPsgTKGGRSbzd5q156d/gpfbJxe66eD5iQKrXj7RGgruGxs62qebBHUKS32CKluCiqZ qh+pmehmEb71noAUoe5e9Zm17S7773V10pjrtG4CmuurCV/n6zLK5turWNhqOvFXbjhZrMD0YhKe wR0zOyuvsh6MWrGoIuzvyWu5y1WIFAqmJselypxXh6dKLNOKEB98L88bS2rkNqqlKzCNJp9c0G0j Gzh0iRrCbHSXmPR643QS+4rWhgFmnSbSuXCjS0xAOWkU2UdLqyuUNfHSFdUouy3bm5i5GnDM3tG8 doJ4r5tqu3pPbRSVfvs8uJzeNXhp3n4j/tZ42SwH7eaWUUOjc3qFV9453UHTXZfcLH+OeNs5g36x lBnHvTm7EbMbLeuaLncao8vWCXimfo1o+843Ak6y4ChNeGntvAYvfLK4ezmoyNIbNCLTCXO9ZV3A E8/s88RczPzDwI4Ob7XZyl7+9Miban29h+tJZPrE21wgvBphDfrrfPdCTPKJD/y98L1rZwHcV6Jq Zab0metpuNIX/qAFPoz171WUaUb4HAhBSzHuHfjzHb3kha/2Cctis/ORArVHNYfFyYRH2pYIRzic isVOfPWD1b6mRTqpCRBozzof6UZVvFXRxWIr3GGrEviGYgyPMfahheiSaLs/9QeFu7oZ/ndSY8DD ya9x+uPed+7mxN2IzIISBOMLFYWVqC3Pew1T2nFuuCiwZS5/v6II10i4t1OJcUH2U9zxKodHsGGv Oa+zkvNUYUOa/TCCRutF9MzDwdlUMJADTCGSbDQ5OV4PTamDoPEi6Ecc/RF5RWwkcdSXvSOaDWSn I9LlvubFTQpuc6JKXLcKeb+xdbKRBnwREemXyjg6ME65aJiOuBgrktzykfPLJBKR9ClMavJ62/Ff BlNIyod9yX9wcSXexnXFpvkrbXk64xsx5Db7wXKP5fSgsvwIMM/9631VLBfkmtbHRXpqmtei52hG pUwSlo+BASQoeILDOBgREECxBBh5/iYmNsQ9dIv5+OI++QkqdsJPc3uykz5fkM+OraeekcQF7X4n B5S67za5U967PmooGQhUXfF7afXyCD7ONdRe17QogYjVx38uLwtrS6nhTnm15LQUnu9E2uK6CNI/ 1HOABj0ESwOjut4FEpFQpdNAm4K2LHnDWHNcmKB2ioKBogysVZtMO2nSxUdZ8Yk2kJc7URioLVI0 YgmtIwZj4LoeKemgnOnbUdGnzZ4Oa6scqiolBGqS6RgWNLu0RMhcaE6rhhU4hiuqFXPAG8fGwTPW FKeLMtdVmXLSs5YJGF/YeVm7rREMlY3UYE+yCxbaMXX8y15m5zVHq6GOKDMynzII/jdUHdyVqIy0 ifX2+r/EgtZcvRzSb72gU9ui87M2VecjKildW/aFqaYhKoryUjfB/g4qtyVuc60xFDGmCxwjW+qu zjuwl2GkOWn66+3QiiEctvd04OVvcCVzjgT7lrkvjVGKKHmmlDUKowSeikb5kK/mJReuWOxONx+s ULsl+Lqb0CVn0SrVyJ6wt4t6yTeSCafhPhAf0OXn6L60UMxiLolFAtmN35S2Ob1lZpQ1r/n0Qb5D oQ1zJiRVDgF8N3Q8TYfbi3DyWCy3lT1nxyBs6FT3S2GOzWRlxwKvlRP0RPJA9SjxEy0UoEnkA+M4 cnzLMJrBGWLFEaaUb5lvpqbq/loOaU5+DFuHPxo82/OZuM8FXG3oVNZhtWpMpb/0Xu5m/LfLhHZQ 7yuVI0MqZ7NE43imC8jH3IwGZlbPm0xkJYs7+2U48hXTsFSMqgGDvai0kLxyynKNT/waj+q1c1tz GjOpPBgdCSq3UKZxCSsqFIY+O6JbAWGWcV1pwqLyj5sGqCF1xb1F3varUWqrJv6cN3PrUXzijtfZ FshpBL3Xwr4GIPvU2N8EjrJgS1zl21rbXQMXeXc5jjFyrhpCzijSv/RQtyPSzHCFMhlME95fHglt pRsX+dfSQjUeHAlpWzJ5iOo79Ldnaxai6bXTcGO3fp07ri7HLEmXXPlYi8bv/qVxvNcdra6m7Rlb 6JBTb5fd66VhFRjGArh2n7R1rDW4P5NOT9K0I183T2scYkeZ3q/VFyLb09U9ajzXBS8Kgkhc4mBS kYY9cy3Vy9lUnuNJH8HGIclUilwnBtjUOH0gteGOZ4c/XNrhXLSYDyxfnD8z1pDy7rYRvDolhnbe UMzxCZUs40s6s7UIvBnLgc0+vKuOkIXeOrDymlp+Zxra4MZLBbVrqD/jTJ597pDmnw5c4+DbyB88 9Cg9DodYcSuMZT/114pptqc/EuTjRPvH/z5slzI3tluOEBBLqOXLOX+0I5929tO97wkvl/atCz+y xJrdwteW2FNW/NSmBP+f/maYtVs/bYyBC7Ox3jsYZHL05CIrBa/nS+b3bHfiYm4Ueil1YZZSgAUI fFZ1dxUmeA2oQRQ3RuGXNGLFV9/XbGFGPV6kfzk1TBBCd+izc7q1H+OHMJwmaBX2IQNYVAKHYepV SSGCe6CnbYHHETKGNe43EDvFgZr0gB/nVHPHZ80VV1ojOiI3XDvYIkl4ayo4bxQIgrFXWTvBI0nH VElWMuw2aLUWCRHHf8ymVCHjFlJnOSojfevCYyyyZDH0IcvHhrsnQ5O1OsWzONuVVKIxSxiFZ/tR fKDAf6xFTnw4O9Qig2VCfW2hJQrmMOuHW0W3dLQmCMO2ccdUd/xyfflH/olTiHZVdGwb8nIwRzSE J15jFlOJuBZBZ4CiyHyd2IFylFlB+HgHhYabhWOGwYO1ZH/Og1dtQlFMk352CGRSIFTapnWQEUtN l4zv8S0aaCFDyGCBqDUxZYpxGHX01y/JuH1xhn7TOCnNCI4eKDs5WGX4R425F4vF1o3BJ4vO0otq I3rimI7jJY1jISqnBxknCIvruF83mF5wN4X7qGLIhR8A2Vg0yFERSIXn9Vv3GHy3Vj/WIkKddlYi yIMv2I/VMjTLpW7pt05SWIZR0RPyxpB4SIUM9lBPGBl0GC7oSEEwRYLe4pJpZY2P0zbI1n+Oc44w qY3PUnmF0ixjVpDD/mJ9wpOBGTVgXlaCaZiPcIWK5NiKBIiPdGaQ0TWGvAiG7nMchdZb7Vgf8zNi MuMyzRdy/lePe9iC4TRx7WhhOQI/QiSVNAmAa2lT/piFbuh7ofJoYSZzrSZ1bvmWw3eN2nKUPVky uPN5/VRfohRd0VYZoqhKIlU6TXYhJxmPUIloAwc1bPmHEpaZYZORHNlXUJM07hATwHR8MJYqkwWR WaIezFhxSFlc8/Fq82hEnpeRozg3ULhhr9lAGtVEkCg5ZNRuuVleBPaZadhG0ZgkyPmDOTOKzViM YgOcpukKqQcbjAWS0IleQ2ROjdh6A+md1qWdBRSX7iSYgFRTtRmBpJioieXJiHfJiMGIR9fJOn8I MSfXYhspn4ooSa2mSAj4n+8Bmg03fBJZoPOJgsVZRxu1oOMRPXYYjdqjihFaEoZpXBREanuJoRI6 cibFinq4ngUKh/wQd/H5ofYCZ0HJXR62opZFaAT0iFIZo4DIiUojkjeqKiuoZirKo5Y1a7AWckGa BkuYoD5lpDK6eUs6CkDqpETwl1EqpfhJpVeKpVl6EgUAADs= --BOUNDARY-- --OUTER-- --- NEW FILE: msg_14.txt --- Return-Path: Delivered-To: bbb@zzz.org Received: by mail.zzz.org (Postfix, from userid 889) id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) MIME-Version: 1.0 Content-Type: text; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15090.61304.110929.45684@aaa.zzz.org> From: bbb@ddd.com (John X. Doe) To: bbb@zzz.org Subject: This is a test message Date: Fri, 4 May 2001 14:05:44 -0400 Hi, I'm sorry but I'm using a drainbread ISP, which although big and wealthy can't seem to generate standard compliant email. :( This message has a Content-Type: header with no subtype. I hope you can still read it. -Me --- NEW FILE: msg_15.txt --- Return-Path: Received: from fepD.post.tele.dk (195.41.46.149) by mail.groupcare.dk (LSMTP for Windows NT v1.1b) with SMTP id <0.0014F8A2@mail.groupcare.dk>; Mon, 30 Apr 2001 12:17:50 +0200 User-Agent: Microsoft-Outlook-Express-Macintosh-Edition/5.02.2106 Subject: XX From: xx@xx.dk To: XX Message-ID: Mime-version: 1.0 Content-type: multipart/mixed; boundary="MS_Mac_OE_3071477847_720252_MIME_Part" > Denne meddelelse er i MIME-format. Da dit postlsningsprogram ikke forstr dette format, kan del af eller hele meddelelsen vre ulselig. --MS_Mac_OE_3071477847_720252_MIME_Part Content-type: multipart/alternative; boundary="MS_Mac_OE_3071477847_720252_MIME_Part" --MS_Mac_OE_3071477847_720252_MIME_Part Content-type: text/plain; charset="ISO-8859-1" Content-transfer-encoding: quoted-printable Some removed test. --MS_Mac_OE_3071477847_720252_MIME_Part Content-type: text/html; charset="ISO-8859-1" Content-transfer-encoding: quoted-printable Some removed HTML Some removed text. --MS_Mac_OE_3071477847_720252_MIME_Part-- --MS_Mac_OE_3071477847_720252_MIME_Part Content-type: image/gif; name="xx.gif"; x-mac-creator="6F676C65"; x-mac-type="47494666" Content-disposition: attachment Content-transfer-encoding: base64 Some removed base64 encoded chars. --MS_Mac_OE_3071477847_720252_MIME_Part-- --- NEW FILE: msg_16.txt --- Return-Path: <> Delivered-To: scr-admin@socal-raves.org Received: from cougar.noc.ucla.edu (cougar.noc.ucla.edu [169.232.10.18]) by babylon.socal-raves.org (Postfix) with ESMTP id CCC2C51B84 for ; Sun, 23 Sep 2001 20:13:54 -0700 (PDT) Received: from sims-ms-daemon by cougar.noc.ucla.edu (Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10) id <0GK500B01D0B8Y@cougar.noc.ucla.edu> for scr-admin@socal-raves.org; Sun, 23 Sep 2001 20:14:35 -0700 (PDT) Received: from cougar.noc.ucla.edu (Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10) id <0GK500B01D0B8X@cougar.noc.ucla.edu>; Sun, 23 Sep 2001 20:14:35 -0700 (PDT) Date: Sun, 23 Sep 2001 20:14:35 -0700 (PDT) From: Internet Mail Delivery Subject: Delivery Notification: Delivery has failed To: scr-admin@socal-raves.org Message-id: <0GK500B04D0B8X@cougar.noc.ucla.edu> MIME-version: 1.0 Sender: scr-owner@socal-raves.org Errors-To: scr-owner@socal-raves.org X-BeenThere: scr@socal-raves.org X-Mailman-Version: 2.1a3 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: SoCal-Raves List-Unsubscribe: , List-Archive: Content-Type: multipart/report; boundary="Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA)" --Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA) Content-type: text/plain; charset=ISO-8859-1 This report relates to a message you sent with the following header fields: Message-id: <002001c144a6$8752e060$56104586@oxy.edu> Date: Sun, 23 Sep 2001 20:10:55 -0700 From: "Ian T. Henry" To: SoCal Raves Subject: [scr] yeah for Ians!! Your message cannot be delivered to the following recipients: Recipient address: jangel1@cougar.noc.ucla.edu Reason: recipient reached disk quota --Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA) Content-type: message/DELIVERY-STATUS Original-envelope-id: 0GK500B4HD0888@cougar.noc.ucla.edu Reporting-MTA: dns; cougar.noc.ucla.edu Action: failed Status: 5.0.0 (recipient reached disk quota) Original-recipient: rfc822;jangel1@cougar.noc.ucla.edu Final-recipient: rfc822;jangel1@cougar.noc.ucla.edu --Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA) Content-type: MESSAGE/RFC822 Return-path: scr-admin@socal-raves.org Received: from sims-ms-daemon by cougar.noc.ucla.edu (Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10) id <0GK500B01D0B8X@cougar.noc.ucla.edu>; Sun, 23 Sep 2001 20:14:35 -0700 (PDT) Received: from panther.noc.ucla.edu by cougar.noc.ucla.edu (Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10) with ESMTP id <0GK500B4GD0888@cougar.noc.ucla.edu> for jangel1@sims-ms-daemon; Sun, 23 Sep 2001 20:14:33 -0700 (PDT) Received: from babylon.socal-raves.org (ip-209-85-222-117.dreamhost.com [209.85.222.117]) by panther.noc.ucla.edu (8.9.1a/8.9.1) with ESMTP id UAA09793 for ; Sun, 23 Sep 2001 20:14:32 -0700 (PDT) Received: from babylon (localhost [127.0.0.1]) by babylon.socal-raves.org (Postfix) with ESMTP id D3B2951B70; Sun, 23 Sep 2001 20:13:47 -0700 (PDT) Received: by babylon.socal-raves.org (Postfix, from userid 60001) id A611F51B82; Sun, 23 Sep 2001 20:13:46 -0700 (PDT) Received: from tiger.cc.oxy.edu (tiger.cc.oxy.edu [134.69.3.112]) by babylon.socal-raves.org (Postfix) with ESMTP id ADA7351B70 for ; Sun, 23 Sep 2001 20:13:44 -0700 (PDT) Received: from ent (n16h86.dhcp.oxy.edu [134.69.16.86]) by tiger.cc.oxy.edu (8.8.8/8.8.8) with SMTP id UAA08100 for ; Sun, 23 Sep 2001 20:14:24 -0700 (PDT) Date: Sun, 23 Sep 2001 20:10:55 -0700 From: "Ian T. Henry" Subject: [scr] yeah for Ians!! Sender: scr-admin@socal-raves.org To: SoCal Raves Errors-to: scr-admin@socal-raves.org Message-id: <002001c144a6$8752e060$56104586@oxy.edu> MIME-version: 1.0 X-Mailer: Microsoft Outlook Express 5.50.4522.1200 Content-type: text/plain; charset=us-ascii Precedence: bulk Delivered-to: scr-post@babylon.socal-raves.org Delivered-to: scr@socal-raves.org X-Converted-To-Plain-Text: from multipart/alternative by demime 0.98e X-Converted-To-Plain-Text: Alternative section used was text/plain X-BeenThere: scr@socal-raves.org X-Mailman-Version: 2.1a3 List-Help: List-Post: List-Subscribe: , List-Id: SoCal-Raves List-Unsubscribe: , List-Archive: I always love to find more Ian's that are over 3 years old!! Ian _______________________________________________ For event info, list questions, or to unsubscribe, see http://www.socal-raves.org/ --Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA)-- --- NEW FILE: msg_17.txt --- MIME-Version: 1.0 From: Barry To: Dingus Lovers Subject: Here is your dingus fish Date: Fri, 20 Apr 2001 19:35:02 -0400 Content-Type: multipart/mixed; boundary="BOUNDARY" Hi there, This is the dingus fish. [Non-text (image/gif) part of message omitted, filename dingusfish.gif] --- NEW FILE: msg_18.txt --- Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Foobar-Spoink-Defrobnit: wasnipoop; giraffes="very-long-necked-animals"; spooge="yummy"; hippos="gargantuan"; marshmallows="gooey" --- NEW FILE: msg_19.txt --- Send Ppp mailing list submissions to ppp@zzz.org To subscribe or unsubscribe via the World Wide Web, visit http://www.zzz.org/mailman/listinfo/ppp or, via email, send a message with subject or body 'help' to ppp-request@zzz.org You can reach the person managing the list at ppp-admin@zzz.org When replying, please edit your Subject line so it is more specific than "Re: Contents of Ppp digest..." Today's Topics: 1. testing #1 (Barry A. Warsaw) 2. testing #2 (Barry A. Warsaw) 3. testing #3 (Barry A. Warsaw) 4. testing #4 (Barry A. Warsaw) 5. testing #5 (Barry A. Warsaw) hello hello hello hello hello _______________________________________________ Ppp mailing list Ppp@zzz.org http://www.zzz.org/mailman/listinfo/ppp --- NEW FILE: msg_20.txt --- Return-Path: Delivered-To: bbb@zzz.org Received: by mail.zzz.org (Postfix, from userid 889) id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15090.61304.110929.45684@aaa.zzz.org> From: bbb@ddd.com (John X. Doe) To: bbb@zzz.org Cc: ccc@zzz.org CC: ddd@zzz.org cc: eee@zzz.org Subject: This is a test message Date: Fri, 4 May 2001 14:05:44 -0400 Hi, Do you like this message? -Me --- NEW FILE: msg_21.txt --- From: aperson@dom.ain To: bperson@dom.ain Subject: Test Content-Type: multipart/mixed; boundary="BOUNDARY" MIME message --BOUNDARY Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit One --BOUNDARY Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Two --BOUNDARY-- End of MIME message --- NEW FILE: msg_22.txt --- Mime-Version: 1.0 Message-Id: Date: Tue, 16 Oct 2001 13:59:25 +0300 To: a@example.com From: b@example.com Content-Type: multipart/mixed; boundary="============_-1208892523==_============" --============_-1208892523==_============ Content-Type: text/plain; charset="us-ascii" ; format="flowed" Text text text. --============_-1208892523==_============ Content-Id: Content-Type: image/jpeg; name="wibble.JPG" ; x-mac-type="4A504547" ; x-mac-creator="474B4F4E" Content-Disposition: attachment; filename="wibble.JPG" Content-Transfer-Encoding: base64 /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAALCAXABIEBAREA g6bCjjw/pIZSjO6FWFpldjySOmCNrO7DBZibUXhTwtCixw+GtAijVdqxxaPp0aKvmGXa qrbBQvms0mAMeYS/3iTV1dG0hHaRNK01XblnWxtVdjkHLMIgTyqnk9VB7CrP2KzIINpa 4O7I+zxYO9WV8jZg71Zlb+8rMDkEirAVQFAUAKAFAAAUAYAUDgADgY6DjpRtXj5RxjHA 4wQRj0wQCMdCAewpaKKK/9k= --============_-1208892523==_============ Content-Id: Content-Type: image/jpeg; name="wibble2.JPG" ; x-mac-type="4A504547" ; x-mac-creator="474B4F4E" Content-Disposition: attachment; filename="wibble2.JPG" Content-Transfer-Encoding: base64 /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAALCAXABJ0BAREA /8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA W6NFJJBEkU10kKGTcWMDwxuU+0JHvk8qAtOpNwqSR0n8c3BlDyXHlqsUltHEiTvdXLxR 7vMiGDNJAJWkAMk8ZkCFp5G2oo5W++INrbQtNfTQxJAuXlupz9oS4d5Y1W+E2XlWZJJE Y7LWYQxTLE1zuMbfBPxw8X2fibVdIbSbI6nLZxX635t9TjtYreWR7WGKJTLJFFKSlozO 0ShxIXM43uC3/9k= --============_-1208892523==_============ Content-Type: text/plain; charset="us-ascii" ; format="flowed" Text text text. --============_-1208892523==_============-- --- NEW FILE: msg_23.txt --- From: aperson@dom.ain Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: text/plain A message part --BOUNDARY-- --- NEW FILE: msg_24.txt --- Content-Type: multipart/mixed; boundary="BOUNDARY" MIME-Version: 1.0 Subject: A subject To: aperson@dom.ain From: bperson@dom.ain --BOUNDARY --BOUNDARY-- --- NEW FILE: msg_25.txt --- >From MAILER-DAEMON Fri Apr 06 16:46:09 2001 Received: from [204.245.199.98] (helo=zinfandel.lacita.com) by www.linux.org.uk with esmtp (Exim 3.13 #1) id 14lYR6-0008Iv-00 for linuxuser-admin@www.linux.org.uk; Fri, 06 Apr 2001 16:46:09 +0100 Received: from localhost (localhost) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with internal id JAB03225; Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800) Date: Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800) From: Mail Delivery Subsystem Subject: Returned mail: Too many hops 19 (17 max): from via [199.164.235.226], to Message-Id: <200104061723.JAB03225@zinfandel.lacita.com> To: To: postmaster@zinfandel.lacita.com MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; bo Auto-Submitted: auto-generated (failure) This is a MIME-encapsulated message --JAB03225.986577786/zinfandel.lacita.com The original message was received at Fri, 6 Apr 2001 09:23:03 -0800 (GMT-0800) from [199.164.235.226] ----- The following addresses have delivery notifications ----- (unrecoverable error) ----- Transcript of session follows ----- 554 Too many hops 19 (17 max): from via [199.164.235.226], to --JAB03225.986577786/zinfandel.lacita.com Content-Type: message/delivery-status Reporting-MTA: dns; zinfandel.lacita.com Received-From-MTA: dns; [199.164.235.226] Arrival-Date: Fri, 6 Apr 2001 09:23:03 -0800 (GMT-0800) Final-Recipient: rfc822; scoffman@wellpartner.com Action: failed Status: 5.4.6 Last-Attempt-Date: Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800) --JAB03225.986577786/zinfandel.lacita.com Content-Type: text/rfc822-headers Return-Path: linuxuser-admin@www.linux.org.uk Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03225 for ; Fri, 6 Apr 2001 09:23:03 -0800 (GMT-0800) Received: from zinfandel.lacita.com ([204.245.199.98]) by fo Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03221 for ; Fri, 6 Apr 2001 09:22:18 -0800 (GMT-0800) Received: from zinfandel.lacita.com ([204.245.199.98]) by fo Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03217 for ; Fri, 6 Apr 2001 09:21:37 -0800 (GMT-0800) Received: from zinfandel.lacita.com ([204.245.199.98]) by fo Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03213 for ; Fri, 6 Apr 2001 09:20:56 -0800 (GMT-0800) Received: from zinfandel.lacita.com ([204.245.199.98]) by fo Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03209 for ; Fri, 6 Apr 2001 09:20:15 -0800 (GMT-0800) Received: from zinfandel.lacita.com ([204.245.199.98]) by fo Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03205 for ; Fri, 6 Apr 2001 09:19:33 -0800 (GMT-0800) Received: from zinfandel.lacita.com ([204.245.199.98]) by fo Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03201 for ; Fri, 6 Apr 2001 09:18:52 -0800 (GMT-0800) Received: from zinfandel.lacita.com ([204.245.199.98]) by fo Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03197 for ; Fri, 6 Apr 2001 09:17:54 -0800 (GMT-0800) Received: from www.linux.org.uk (parcelfarce.linux.theplanet.co.uk [195.92.249.252]) by fo Received: from localhost.localdomain ([ by id Received: from [212.1.130.11] (helo=s1.uklinux.net ident=root) by id fo Received: from server (ppp-2-22.cvx4.telinco.net [212.1.149.22]) by fo From: Daniel James Organization: LinuxUser To: linuxuser@www.linux.org.uk X-Mailer: KMail [version 1.1.99] Content-Type: text/plain; c MIME-Version: 1.0 Message-Id: <01040616033903.00962@server> Content-Transfer-Encoding: 8bit Subject: [LinuxUser] bulletin no. 45 Sender: linuxuser-admin@www.linux.org.uk Errors-To: linuxuser-admin@www.linux.org.uk X-BeenThere: linuxuser@www.linux.org.uk X-Mailman-Version: 2.0.3 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Unsubscribe: , Date: Fri, 6 Apr 2001 16:03:39 +0100 --JAB03225.986577786/zinfandel.lacita.com-- --- NEW FILE: msg_26.txt --- Received: from xcar [192.168.0.2] by jeeves.wooster.local (SMTPD32-7.07 EVAL) id AFF92F0214; Sun, 12 May 2002 08:55:37 +0100 Date: Sun, 12 May 2002 08:56:15 +0100 From: Father Time To: timbo@jeeves.wooster.local Subject: IMAP file test Message-ID: <6df65d354b.father.time@rpc.wooster.local> X-Organization: Home User-Agent: Messenger-Pro/2.50a (MsgServe/1.50) (RISC-OS/4.02) POPstar/2.03 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="1618492860--2051301190--113853680" Status: R X-UIDL: 319998302 This message is in MIME format which your mailer apparently does not support. You either require a newer version of your software which supports MIME, or a separate MIME decoding utility. Alternatively, ask the sender of this message to resend it in a different format. --1618492860--2051301190--113853680 Content-Type: text/plain; charset=us-ascii Simple email with attachment. --1618492860--2051301190--113853680 Content-Type: application/riscos; name="clock.bmp,69c"; type=BMP; load=&fff69c4b; exec=&355dd4d1; access=&03 Content-Disposition: attachment; filename="clock.bmp" Content-Transfer-Encoding: base64 Qk12AgAAAAAAAHYAAAAoAAAAIAAAACAAAAABAAQAAAAAAAAAAADXDQAA1w0AAAAAAAAA AAAAAAAAAAAAiAAAiAAAAIiIAIgAAACIAIgAiIgAALu7uwCIiIgAERHdACLuIgAz//8A zAAAAN0R3QDu7iIA////AAAAAAAAAAAAAAAAAAAAAAAAAAi3AAAAAAAAADeAAAAAAAAA C3ADMzMzMANwAAAAAAAAAAAHMAAAAANwAAAAAAAAAACAMAd3zPfwAwgAAAAAAAAIAwd/ f8x/f3AwgAAAAAAAgDB0x/f3//zPAwgAAAAAAAcHfM9////8z/AwAAAAAAiwd/f3//// ////A4AAAAAAcEx/f///////zAMAAAAAiwfM9////3///8zwOAAAAAcHf3////B///// 8DAAAAALB/f3///wd3d3//AwAAAABwTPf//wCQAAD/zAMAAAAAsEx/f///B////8wDAA AAAHB39////wf/////AwAAAACwf39///8H/////wMAAAAIcHfM9///B////M8DgAAAAA sHTH///wf///xAMAAAAACHB3f3//8H////cDgAAAAAALB3zH//D//M9wMAAAAAAAgLB0 z39///xHAwgAAAAAAAgLB3d3RHd3cDCAAAAAAAAAgLAHd0R3cAMIAAAAAAAAgAgLcAAA AAMwgAgAAAAACDAAAAu7t7cwAAgDgAAAAABzcIAAAAAAAAgDMwAAAAAAN7uwgAAAAAgH MzMAAAAACH97tzAAAAALu3c3gAAAAAAL+7tzDABAu7f7cAAAAAAACA+3MA7EQAv/sIAA AAAAAAAIAAAAAAAAAIAAAAAA --1618492860--2051301190--113853680-- --- NEW FILE: msg_27.txt --- Return-Path: Received: by mail.dom.ain (Postfix, from userid 889) id B9D0AD35DB; Tue, 4 Jun 2002 21:46:59 -0400 (EDT) Message-ID: <15613.28051.707126.569693@dom.ain> Date: Tue, 4 Jun 2002 21:46:59 -0400 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Subject: bug demonstration 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 more text From: aperson@dom.ain (Anne P. Erson) To: bperson@dom.ain (Barney P. Erson) test --- NEW FILE: msg_28.txt --- From: aperson@dom.ain MIME-Version: 1.0 Content-Type: multipart/digest; boundary=BOUNDARY --BOUNDARY Content-Type: message/rfc822 Content-Type: text/plain; charset=us-ascii To: aa@bb.org From: cc@dd.org Subject: ee message 1 --BOUNDARY Content-Type: message/rfc822 Content-Type: text/plain; charset=us-ascii To: aa@bb.org From: cc@dd.org Subject: ee message 2 --BOUNDARY-- --- NEW FILE: msg_29.txt --- Return-Path: Delivered-To: bbb@zzz.org Received: by mail.zzz.org (Postfix, from userid 889) id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; title*0*="us-ascii'en'This%20is%20even%20more%20"; title*1*="%2A%2A%2Afun%2A%2A%2A%20"; title*2="isn't it!" Content-Transfer-Encoding: 7bit Message-ID: <15090.61304.110929.45684@aaa.zzz.org> From: bbb@ddd.com (John X. Doe) To: bbb@zzz.org Subject: This is a test message Date: Fri, 4 May 2001 14:05:44 -0400 Hi, Do you like this message? -Me --- NEW FILE: msg_30.txt --- From: aperson@dom.ain MIME-Version: 1.0 Content-Type: multipart/digest; boundary=BOUNDARY --BOUNDARY Content-Type: text/plain; charset=us-ascii To: aa@bb.org From: cc@dd.org Subject: ee message 1 --BOUNDARY Content-Type: text/plain; charset=us-ascii To: aa@bb.org From: cc@dd.org Subject: ee message 2 --BOUNDARY-- --- NEW FILE: msg_31.txt --- From: aperson@dom.ain MIME-Version: 1.0 Content-Type: multipart/mixed; boundary=BOUNDARY_ --BOUNDARY Content-Type: text/plain message 1 --BOUNDARY Content-Type: text/plain message 2 --BOUNDARY-- --- NEW FILE: msg_32.txt --- Delivered-To: freebsd-isp@freebsd.org Date: Tue, 26 Sep 2000 12:23:03 -0500 From: Anne Person To: Barney Dude Subject: Re: Limiting Perl CPU Utilization... Mime-Version: 1.0 Content-Type: text/plain; charset*=ansi-x3.4-1968''us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.8i Sender: owner-freebsd-isp@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org Some message. --- NEW FILE: msg_33.txt --- Delivered-To: freebsd-isp@freebsd.org Date: Wed, 27 Sep 2000 11:11:09 -0500 From: Anne Person To: Barney Dude Subject: Re: Limiting Perl CPU Utilization... Mime-Version: 1.0 Content-Type: multipart/signed; micalg*=ansi-x3.4-1968''pgp-md5; protocol*=ansi-x3.4-1968''application%2Fpgp-signature; boundary*="ansi-x3.4-1968''EeQfGwPcQSOJBaQU" Content-Disposition: inline Sender: owner-freebsd-isp@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org --EeQfGwPcQSOJBaQU Content-Type: text/plain; charset*=ansi-x3.4-1968''us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable part 1 --EeQfGwPcQSOJBaQU Content-Type: text/plain Content-Disposition: inline part 2 --EeQfGwPcQSOJBaQU-- From barry@users.sourceforge.net Fri Oct 4 18:57:29 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Fri, 04 Oct 2002 10:57:29 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.337.2.4.2.36,1.337.2.4.2.37 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv26720 Modified Files: Tag: release22-maint NEWS Log Message: Add a note about the backport of email 2.4 Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.337.2.4.2.36 retrieving revision 1.337.2.4.2.37 diff -C2 -d -r1.337.2.4.2.36 -r1.337.2.4.2.37 *** NEWS 25 Sep 2002 15:03:10 -0000 1.337.2.4.2.36 --- NEWS 4 Oct 2002 17:57:27 -0000 1.337.2.4.2.37 *************** *** 53,56 **** --- 53,63 ---- Library + - The email package from the Python 2.3 development tree has been + backported, including updated documentation. This version + corresponds to email 2.4 and should be nearly completely backward + compatible. However there have been lots of improvements in the + API, so you should read the section in the library manual about the + changes since email v1. + - random.gauss() uses a piece of hidden state used by nothing else, and the .seed() and .whseed() methods failed to reset it. In other From barry@users.sourceforge.net Fri Oct 4 19:00:17 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Fri, 04 Oct 2002 11:00:17 -0700 Subject: [Python-checkins] python/dist/src/Lib/email/test test_email_codecs.py,1.3.2.1,1.3.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email/test In directory usw-pr-cvs1:/tmp/cvs-serv28381 Modified Files: Tag: release22-maint test_email_codecs.py Log Message: regrtest expects TestSkipped to come from test_support not test.test_support Index: test_email_codecs.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/test/test_email_codecs.py,v retrieving revision 1.3.2.1 retrieving revision 1.3.2.2 diff -C2 -d -r1.3.2.1 -r1.3.2.2 *** test_email_codecs.py 4 Oct 2002 17:40:57 -0000 1.3.2.1 --- test_email_codecs.py 4 Oct 2002 18:00:13 -0000 1.3.2.2 *************** *** 3,7 **** import unittest ! from test.test_support import TestSkipped, run_unittest from email.test.test_email import TestEmailBase --- 3,7 ---- import unittest ! from test.test_support import run_unittest from email.test.test_email import TestEmailBase *************** *** 13,16 **** --- 13,18 ---- unicode('foo', 'japanese.iso-2022-jp') except LookupError: + # Different in Python 2.3 + from test_support import TestSkipped raise TestSkipped, 'Optional Japanese codecs not installed' From fdrake@users.sourceforge.net Fri Oct 4 19:59:00 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 04 Oct 2002 11:59:00 -0700 Subject: [Python-checkins] python/dist/src/Doc/api refcounts.dat,1.43,1.44 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory usw-pr-cvs1:/tmp/cvs-serv17773 Modified Files: refcounts.dat Log Message: Added refcount information for PyObject_GetIter(). Index: refcounts.dat =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/refcounts.dat,v retrieving revision 1.43 retrieving revision 1.44 diff -C2 -d -r1.43 -r1.44 *** refcounts.dat 2 Jul 2002 16:16:18 -0000 1.43 --- refcounts.dat 4 Oct 2002 18:58:58 -0000 1.44 *************** *** 812,815 **** --- 812,818 ---- PyObject_GetItem:PyObject*:key:0: + PyObject_GetIter:PyObject*::+1: + PyObject_GetIter:PyObject*:o:0: + PyObject_HasAttr:int::: PyObject_HasAttr:PyObject*:o:0: From fdrake@users.sourceforge.net Fri Oct 4 19:59:39 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 04 Oct 2002 11:59:39 -0700 Subject: [Python-checkins] python/dist/src/Doc/api refcounts.dat,1.38.6.3,1.38.6.4 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory usw-pr-cvs1:/tmp/cvs-serv18049 Modified Files: Tag: release22-maint refcounts.dat Log Message: Added refcount information for PyObject_GetIter(). Index: refcounts.dat =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/refcounts.dat,v retrieving revision 1.38.6.3 retrieving revision 1.38.6.4 diff -C2 -d -r1.38.6.3 -r1.38.6.4 *** refcounts.dat 20 Jun 2002 22:09:12 -0000 1.38.6.3 --- refcounts.dat 4 Oct 2002 18:59:36 -0000 1.38.6.4 *************** *** 805,808 **** --- 805,811 ---- PyObject_GetItem:PyObject*:key:0: + PyObject_GetIter:PyObject*::+1: + PyObject_GetIter:PyObject*:o:0: + PyObject_HasAttr:int::: PyObject_HasAttr:PyObject*:o:0: From fdrake@users.sourceforge.net Fri Oct 4 20:23:08 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 04 Oct 2002 12:23:08 -0700 Subject: [Python-checkins] python/dist/src/Doc Makefile,1.246,1.247 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory usw-pr-cvs1:/tmp/cvs-serv26228 Modified Files: Makefile Log Message: Remove some unnecessary dependencies (minor). Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile,v retrieving revision 1.246 retrieving revision 1.247 diff -C2 -d -r1.246 -r1.247 *** Makefile 1 Oct 2002 15:20:18 -0000 1.246 --- Makefile 4 Oct 2002 19:23:06 -0000 1.247 *************** *** 194,199 **** cd paper-$(PAPER) && $(MKPDF) api.tex ! paper-$(PAPER)/api.tex: api/api.tex $(ANNOAPI) ! $(PYTHON) $(TOOLSDIR)/anno-api.py -o $@ api/api.tex paper-$(PAPER)/abstract.tex: api/abstract.tex $(ANNOAPI) --- 194,199 ---- cd paper-$(PAPER) && $(MKPDF) api.tex ! paper-$(PAPER)/api.tex: api/api.tex ! cp api/api.tex $@ paper-$(PAPER)/abstract.tex: api/abstract.tex $(ANNOAPI) *************** *** 209,214 **** $(PYTHON) $(TOOLSDIR)/anno-api.py -o $@ api/init.tex ! paper-$(PAPER)/intro.tex: api/intro.tex $(ANNOAPI) ! $(PYTHON) $(TOOLSDIR)/anno-api.py -o $@ api/intro.tex paper-$(PAPER)/memory.tex: api/memory.tex $(ANNOAPI) --- 209,214 ---- $(PYTHON) $(TOOLSDIR)/anno-api.py -o $@ api/init.tex ! paper-$(PAPER)/intro.tex: api/intro.tex ! cp api/intro.tex $@ paper-$(PAPER)/memory.tex: api/memory.tex $(ANNOAPI) From fdrake@users.sourceforge.net Fri Oct 4 20:22:39 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 04 Oct 2002 12:22:39 -0700 Subject: [Python-checkins] python/dist/src/Doc Makefile,1.235.2.1.2.10,1.235.2.1.2.11 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory usw-pr-cvs1:/tmp/cvs-serv26064 Modified Files: Tag: release22-maint Makefile Log Message: Remove some unnecessary dependencies (minor). Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile,v retrieving revision 1.235.2.1.2.10 retrieving revision 1.235.2.1.2.11 diff -C2 -d -r1.235.2.1.2.10 -r1.235.2.1.2.11 *** Makefile 23 May 2002 19:42:11 -0000 1.235.2.1.2.10 --- Makefile 4 Oct 2002 19:22:37 -0000 1.235.2.1.2.11 *************** *** 191,196 **** cd paper-$(PAPER) && $(MKPDF) api.tex ! paper-$(PAPER)/api.tex: api/api.tex $(ANNOAPI) ! $(PYTHON) $(TOOLSDIR)/anno-api.py -o $@ api/api.tex paper-$(PAPER)/abstract.tex: api/abstract.tex $(ANNOAPI) --- 191,196 ---- cd paper-$(PAPER) && $(MKPDF) api.tex ! paper-$(PAPER)/api.tex: api/api.tex ! cp api/api.tex $@ paper-$(PAPER)/abstract.tex: api/abstract.tex $(ANNOAPI) *************** *** 206,211 **** $(PYTHON) $(TOOLSDIR)/anno-api.py -o $@ api/init.tex ! paper-$(PAPER)/intro.tex: api/intro.tex $(ANNOAPI) ! $(PYTHON) $(TOOLSDIR)/anno-api.py -o $@ api/intro.tex paper-$(PAPER)/memory.tex: api/memory.tex $(ANNOAPI) --- 206,211 ---- $(PYTHON) $(TOOLSDIR)/anno-api.py -o $@ api/init.tex ! paper-$(PAPER)/intro.tex: api/intro.tex ! cp api/intro.tex $@ paper-$(PAPER)/memory.tex: api/memory.tex $(ANNOAPI) From rhettinger@users.sourceforge.net Fri Oct 4 21:01:50 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 04 Oct 2002 13:01:50 -0700 Subject: [Python-checkins] python/dist/src/Lib sets.py,1.30,1.31 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv7956 Modified Files: sets.py Log Message: .iterkeys() is not needed. Index: sets.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/sets.py,v retrieving revision 1.30 retrieving revision 1.31 diff -C2 -d -r1.30 -r1.31 *** sets.py 29 Aug 2002 15:13:50 -0000 1.30 --- sets.py 4 Oct 2002 20:01:48 -0000 1.31 *************** *** 178,182 **** else: little, big = other, self ! common = filter(big._data.has_key, little._data.iterkeys()) return self.__class__(common) --- 178,182 ---- else: little, big = other, self ! common = filter(big._data.has_key, little._data) return self.__class__(common) From fdrake@users.sourceforge.net Fri Oct 4 21:40:47 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 04 Oct 2002 13:40:47 -0700 Subject: [Python-checkins] python/dist/src/Doc/texinputs boilerplate.tex,1.70.2.1.2.6,1.70.2.1.2.7 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/texinputs In directory usw-pr-cvs1:/tmp/cvs-serv22397/texinputs Modified Files: Tag: release22-maint boilerplate.tex Log Message: Version number updates for Python 2.2.2. Index: boilerplate.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/texinputs/boilerplate.tex,v retrieving revision 1.70.2.1.2.6 retrieving revision 1.70.2.1.2.7 diff -C2 -d -r1.70.2.1.2.6 -r1.70.2.1.2.7 *** boilerplate.tex 2 May 2002 04:50:47 -0000 1.70.2.1.2.6 --- boilerplate.tex 4 Oct 2002 20:40:45 -0000 1.70.2.1.2.7 *************** *** 7,11 **** \date{\today} % XXX update before release! ! \release{2.2.1} % software release, not documentation ! \setreleaseinfo{+} % empty for final release \setshortversion{2.2} % major.minor only for software --- 7,11 ---- \date{\today} % XXX update before release! ! \release{2.2.2} % software release, not documentation ! \setreleaseinfo{b1} % empty for final release \setshortversion{2.2} % major.minor only for software From fdrake@users.sourceforge.net Fri Oct 4 21:40:47 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 04 Oct 2002 13:40:47 -0700 Subject: [Python-checkins] python/dist/src/Doc Makefile,1.235.2.1.2.11,1.235.2.1.2.12 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory usw-pr-cvs1:/tmp/cvs-serv22397 Modified Files: Tag: release22-maint Makefile Log Message: Version number updates for Python 2.2.2. Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile,v retrieving revision 1.235.2.1.2.11 retrieving revision 1.235.2.1.2.12 diff -C2 -d -r1.235.2.1.2.11 -r1.235.2.1.2.12 *** Makefile 4 Oct 2002 19:22:37 -0000 1.235.2.1.2.11 --- Makefile 4 Oct 2002 20:40:44 -0000 1.235.2.1.2.12 *************** *** 67,71 **** # This is the *documentation* release, and is used to construct the file # names of the downloadable tarballs. ! RELEASE=2.2.1+ PYTHON= python --- 67,71 ---- # This is the *documentation* release, and is used to construct the file # names of the downloadable tarballs. ! RELEASE=2.2.2 PYTHON= python From gvanrossum@users.sourceforge.net Fri Oct 4 21:49:07 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Fri, 04 Oct 2002 13:49:07 -0700 Subject: [Python-checkins] python/dist/src/Lib/encodings __init__.py,1.12,1.13 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/encodings In directory usw-pr-cvs1:/tmp/cvs-serv24937 Modified Files: __init__.py Log Message: When looking for an alias, first look for the normalized name (which still may contain dots), then if that doesn't exist look for the name with dots replaced by underscores. This is a little more forgiving. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/encodings/__init__.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** __init__.py 4 Oct 2002 11:45:38 -0000 1.12 --- __init__.py 4 Oct 2002 20:49:05 -0000 1.13 *************** *** 70,74 **** except ImportError: import aliases ! modname = aliases.aliases.get(modname, modname) try: mod = __import__(modname, globals(), locals(), _import_tail) --- 70,76 ---- except ImportError: import aliases ! modname = (aliases.aliases.get(modname) or ! aliases.aliases.get(modname.replace('.', '_')) or ! modname) try: mod = __import__(modname, globals(), locals(), _import_tail) From akuchling@users.sourceforge.net Fri Oct 4 23:34:14 2002 From: akuchling@users.sourceforge.net (akuchling@users.sourceforge.net) Date: Fri, 04 Oct 2002 15:34:14 -0700 Subject: [Python-checkins] python/dist/src/Doc/whatsnew whatsnew23.tex,1.52,1.53 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/whatsnew In directory usw-pr-cvs1:/tmp/cvs-serv28240 Modified Files: whatsnew23.tex Log Message: Add a section to be written; remove reference to deleted code Index: whatsnew23.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/whatsnew/whatsnew23.tex,v retrieving revision 1.52 retrieving revision 1.53 diff -C2 -d -r1.52 -r1.53 *** whatsnew23.tex 14 Sep 2002 02:03:25 -0000 1.52 --- whatsnew23.tex 4 Oct 2002 22:34:11 -0000 1.53 *************** *** 314,317 **** --- 314,323 ---- %====================================================================== + \section{PEP 277: XXX} + + XXX write this section + + + %====================================================================== \section{PEP 278: Universal Newline Support} *************** *** 847,859 **** Modifying \file{sample.h} would then cause the module to be recompiled. (Contributed by Jeremy Hylton.) - - \item Two new binary packagers were added to the Distutils. - \code{bdist_pkgtool} builds \file{.pkg} files to use with Solaris - \program{pkgtool}, and \code{bdist_sdux} builds \program{swinstall} - packages for use on HP-UX. - An abstract binary packager class, - \module{distutils.command.bdist_packager}, was added; this may make it - easier to write binary packaging commands. (Contributed by Mark - Alexander.) \item The \module{getopt} module gained a new function, --- 853,856 ---- From tim_one@users.sourceforge.net Sat Oct 5 02:47:36 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Fri, 04 Oct 2002 18:47:36 -0700 Subject: [Python-checkins] python/dist/src/Python pythonrun.c,2.166,2.167 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv11587/python/Python Modified Files: pythonrun.c Log Message: s/_alloca/alloca/g; Windows doesn't need the former, at least not unless __STDC__ is defined (or something like that ...). Index: pythonrun.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/pythonrun.c,v retrieving revision 2.166 retrieving revision 2.167 diff -C2 -d -r2.166 -r2.167 *** pythonrun.c 15 Aug 2002 01:20:16 -0000 2.166 --- pythonrun.c 5 Oct 2002 01:47:34 -0000 2.167 *************** *** 1451,1457 **** { __try { ! /* _alloca throws a stack overflow exception if there's not enough space left on the stack */ ! _alloca(PYOS_STACK_MARGIN * sizeof(void*)); return 0; } __except (EXCEPTION_EXECUTE_HANDLER) { --- 1451,1457 ---- { __try { ! /* alloca throws a stack overflow exception if there's not enough space left on the stack */ ! alloca(PYOS_STACK_MARGIN * sizeof(void*)); return 0; } __except (EXCEPTION_EXECUTE_HANDLER) { From tim_one@users.sourceforge.net Sat Oct 5 02:47:36 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Fri, 04 Oct 2002 18:47:36 -0700 Subject: [Python-checkins] python/dist/src/Modules posixmodule.c,2.262,2.263 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv11587/python/Modules Modified Files: posixmodule.c Log Message: s/_alloca/alloca/g; Windows doesn't need the former, at least not unless __STDC__ is defined (or something like that ...). Index: posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.262 retrieving revision 2.263 diff -C2 -d -r2.262 -r2.263 *** posixmodule.c 3 Oct 2002 07:24:48 -0000 2.262 --- posixmodule.c 5 Oct 2002 01:47:34 -0000 2.263 *************** *** 3607,3611 **** char *comshell; ! s1 = (char *)_alloca(i); if (!(x = GetEnvironmentVariable("COMSPEC", s1, i))) return x; --- 3607,3611 ---- char *comshell; ! s1 = (char *)alloca(i); if (!(x = GetEnvironmentVariable("COMSPEC", s1, i))) return x; *************** *** 3623,3627 **** /* NT/2000 and not using command.com. */ x = i + strlen(s3) + strlen(cmdstring) + 1; ! s2 = (char *)_alloca(x); ZeroMemory(s2, x); PyOS_snprintf(s2, x, "%s%s%s", s1, s3, cmdstring); --- 3623,3627 ---- /* NT/2000 and not using command.com. */ x = i + strlen(s3) + strlen(cmdstring) + 1; ! s2 = (char *)alloca(x); ZeroMemory(s2, x); PyOS_snprintf(s2, x, "%s%s%s", s1, s3, cmdstring); *************** *** 3676,3680 **** strlen(szConsoleSpawn) + 1; ! s2 = (char *)_alloca(x); ZeroMemory(s2, x); /* To maintain correct argument passing semantics, --- 3676,3680 ---- strlen(szConsoleSpawn) + 1; ! s2 = (char *)alloca(x); ZeroMemory(s2, x); /* To maintain correct argument passing semantics, From rhettinger@users.sourceforge.net Sat Oct 5 04:58:18 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 04 Oct 2002 20:58:18 -0700 Subject: [Python-checkins] python/dist/src/Tools/idle EditorWindow.py,1.38.18.3,1.38.18.4 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/idle In directory usw-pr-cvs1:/tmp/cvs-serv17647 Modified Files: Tag: release22-maint EditorWindow.py Log Message: Backport 1.43: Extended IDLE's open module menu item to handle hierarchical module names. Closes SF patch 600152. Index: EditorWindow.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/idle/EditorWindow.py,v retrieving revision 1.38.18.3 retrieving revision 1.38.18.4 diff -C2 -d -r1.38.18.3 -r1.38.18.4 *** EditorWindow.py 23 Sep 2002 14:17:15 -0000 1.38.18.3 --- EditorWindow.py 5 Oct 2002 03:58:16 -0000 1.38.18.4 *************** *** 82,85 **** --- 82,99 ---- """ % idlever.IDLE_VERSION + def _find_module(fullname, path=None): + """Version of imp.find_module() that handles hierarchical module names""" + + file = None + for tgt in fullname.split('.'): + if file is not None: + file.close() # close intermediate files + (file, filename, descr) = imp.find_module(tgt, path) + if descr[2] == imp.PY_SOURCE: + break # find but not load the source file + module = imp.load_module(tgt, file, filename, descr) + path = module.__path__ + return file, filename, descr + class EditorWindow: *************** *** 341,348 **** if not name: return - # XXX Ought to support package syntax # XXX Ought to insert current file's directory in front of path try: ! (f, file, (suffix, mode, type)) = imp.find_module(name) except (NameError, ImportError), msg: tkMessageBox.showerror("Import error", str(msg), parent=self.text) --- 355,361 ---- if not name: return # XXX Ought to insert current file's directory in front of path try: ! (f, file, (suffix, mode, type)) = _find_module(name) except (NameError, ImportError), msg: tkMessageBox.showerror("Import error", str(msg), parent=self.text) From rhettinger@users.sourceforge.net Sat Oct 5 06:04:10 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 04 Oct 2002 22:04:10 -0700 Subject: [Python-checkins] python/dist/src/Doc/tut tut.tex,1.156.4.1.2.10,1.156.4.1.2.11 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory usw-pr-cvs1:/tmp/cvs-serv6364 Modified Files: Tag: release22-maint tut.tex Log Message: Backport 1.161: Message for NameError has changed. Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.156.4.1.2.10 retrieving revision 1.156.4.1.2.11 diff -C2 -d -r1.156.4.1.2.10 -r1.156.4.1.2.11 *** tut.tex 6 Sep 2002 18:09:22 -0000 1.156.4.1.2.10 --- tut.tex 5 Oct 2002 05:04:07 -0000 1.156.4.1.2.11 *************** *** 3080,3084 **** Traceback (most recent call last): File "", line 1, in ? ! NameError: spam >>> '2' + 2 Traceback (most recent call last): --- 3080,3084 ---- Traceback (most recent call last): File "", line 1, in ? ! NameError: name 'spam' is not defined >>> '2' + 2 Traceback (most recent call last): From rhettinger@users.sourceforge.net Sat Oct 5 06:14:21 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 04 Oct 2002 22:14:21 -0700 Subject: [Python-checkins] python/dist/src/Doc/tut tut.tex,1.156.4.1.2.11,1.156.4.1.2.12 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory usw-pr-cvs1:/tmp/cvs-serv9662 Modified Files: Tag: release22-maint tut.tex Log Message: Backport 1.160 on looping idioms. Excludes enumerate(), a Py2.3 feature. Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.156.4.1.2.11 retrieving revision 1.156.4.1.2.12 diff -C2 -d -r1.156.4.1.2.11 -r1.156.4.1.2.12 *** tut.tex 5 Oct 2002 05:04:07 -0000 1.156.4.1.2.11 --- tut.tex 5 Oct 2002 05:14:19 -0000 1.156.4.1.2.12 *************** *** 2047,2050 **** --- 2047,2079 ---- + \section{Looping Techniques \label{loopidioms}} + + When looping through dictionaries, the key and corresponding value can + be retrieved at the same time using the \method{items()} method. + + \begin{verbatim} + >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} + >>> for k, v in knights.items(): + ... print k, v + ... + gallahad the pure + robin the brave + \end{verbatim} + + To loop over two or more sequences at the same time, the entries + can be paired with the \function{zip()} function. + + \begin{verbatim} + >>> questions = ['name', 'quest', 'favorite color'] + >>> answers = ['lancelot', 'the holy grail', 'blue'] + >>> for q, a in zip(questions, answers): + ... print 'What is your %s? It is %s.' % (q, a) + ... + What is your name? It is lancelot. + What is your quest? It is the holy grail. + What is your favorite color? It is blue. + \end{verbatim} + + \section{More on Conditions \label{conditions}} From rhettinger@users.sourceforge.net Sat Oct 5 07:12:12 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 04 Oct 2002 23:12:12 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref6.tex,1.47.4.2,1.47.4.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv30079 Modified Files: Tag: release22-maint ref6.tex Log Message: Backport 1.54 1.53 1.52 1.51 1.50 and 1.49: Try to improve the explanation of the "raise" statement and how its arguments are interpreted. This closes SF bug #532467. Fix Typo. Reword explanation of global statement since an undeclared global is a free variable and is subject to those rules. Note the sole case in which the ban on "from ... import *" within a function is enforced. Remove the following restriction: Names bound by import statements may not occur in global statements in the same scope. Why not? Note that it is illegal to delete a cell variable. Note that deleteing an unbound local will raise a NameError. Index: ref6.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref6.tex,v retrieving revision 1.47.4.2 retrieving revision 1.47.4.3 diff -C2 -d -r1.47.4.2 -r1.47.4.3 *** ref6.tex 25 Jun 2002 13:39:49 -0000 1.47.4.2 --- ref6.tex 5 Oct 2002 06:12:08 -0000 1.47.4.3 *************** *** 353,362 **** to right. ! Deletion of a name removes the binding of that name (which must exist) from the local or global namespace, depending on whether the name ! occurs in a \keyword{global} statement in the same code block. \stindex{global} \indexii{unbinding}{name} Deletion of attribute references, subscriptions and slicings is passed to the primary object involved; deletion of a slicing --- 353,366 ---- to right. ! Deletion of a name removes the binding of that name from the local or global namespace, depending on whether the name ! occurs in a \keyword{global} statement in the same code block. If the ! name is unbound, a \exception{NameError} exception will be raised. \stindex{global} \indexii{unbinding}{name} + It is illegal to delete a name from the local namespace if it occurs + as a free variable\indexii{free}{variable} in a nested block. + Deletion of attribute references, subscriptions and slicings is passed to the primary object involved; deletion of a slicing *************** *** 518,552 **** If no expressions are present, \keyword{raise} re-raises the last ! expression that was raised in the current scope. ! ! Otherwise, \keyword{raise} evaluates its first expression, which must yield ! a string, class, or instance object. If there is a second expression, ! this is evaluated, else \code{None} is substituted. If the first ! expression is a class object, then the second expression may be an ! instance of that class or one of its derivatives, and then that ! instance is raised. If the second expression is not such an instance, ! the given class is instantiated. The argument list for the ! instantiation is determined as follows: if the second expression is a ! tuple, it is used as the argument list; if it is \code{None}, the ! argument list is empty; otherwise, the argument list consists of a ! single argument which is the second expression. If the first ! expression is an instance object, the second expression must be ! \code{None}. \index{exception} \indexii{raising}{exception} ! If the first object is a string, it then raises the exception ! identified by the first object, with the second one (or \code{None}) ! as its parameter. If the first object is a class or instance, ! it raises the exception identified by the class of the instance ! determined in the previous step, with the instance as ! its parameter. - If a third object is present, and it is not \code{None}, it should be - a traceback object (see section~\ref{traceback}), and it is - substituted instead of the current location as the place where the - exception occurred. This is useful to re-raise an exception - transparently in an except clause. - \obindex{traceback} --- 522,563 ---- If no expressions are present, \keyword{raise} re-raises the last ! expression that was active in the current scope. If no exception has ! been active in the current scope, an exception is raised that ! indicates indicates that this is the error. \index{exception} \indexii{raising}{exception} ! Otherwise, \keyword{raise} evaluates the expressions to get three ! objects, using \code{None} as the value of omitted expressions. The ! first two objects are used to determine the \emph{type} and ! \emph{value} of the exception. ! ! If the first object is an instance, the type of the exception is the ! class of the instance, the instance itself if the value, and the ! second object must be \code{None}. ! ! If the first object is a class, it becomes the type of the exception. ! The second object is used to determine the exception value: If it is ! an instance of the class, the instance becomes the exception value. ! If the second object is a tuple, it is used as the argument list for ! the class constructor; if it is \code{None}, an empty argument list is ! used, and any other object is treated as a single argument to the ! constructor. The instance so created by calling the constructor is ! used as the exception value. ! ! If the first object is a string, the string object is the exception ! type, and the second object becomes the exception value. ! ! If a third object is present and not \code{None}, it must be a ! traceback\obindex{traceback} object (see section~\ref{traceback}), and ! it is substituted instead of the current location as the place where ! the exception occurred. If the third object is present and not a ! traceback object or \code{None}, a \exception{TypeError} exception is ! raised. The three-expression form of \keyword{raise} is useful to ! re-raise an exception transparently in an except clause, but ! \keyword{raise} with no expressions should be preferred if the ! exception to be re-raised was the most recently active exception in ! the current scope. *************** *** 691,699 **** (\character{_}). ! Names bound by \keyword{import} statements may not occur in ! \keyword{global} statements in the same scope. ! \stindex{global} - The \keyword{from} form with \samp{*} may only occur in a module scope. \kwindex{from} \stindex{from} --- 702,710 ---- (\character{_}). ! The \keyword{from} form with \samp{*} may only occur in a module ! scope. If the wild card form of import --- \samp{import *} --- is ! used in a function and the function contains or is a nested block with ! free variables, the compiler will raise a \exception{SyntaxError}. \kwindex{from} \stindex{from} *************** *** 730,736 **** The \keyword{global} statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be ! interpreted as globals. While \emph{using} global names is automatic ! if they are not defined in the local scope, \emph{assigning} to global ! names would be impossible without \keyword{global}. \indexiii{global}{name}{binding} --- 741,747 ---- The \keyword{global} statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be ! interpreted as globals. It would be impossible to assign to a global ! variable without \keyword{global}, although free variables may refer ! to globals without being declared global. \indexiii{global}{name}{binding} From rhettinger@users.sourceforge.net Sat Oct 5 07:40:51 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 04 Oct 2002 23:40:51 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref3.tex,1.82.4.5,1.82.4.6 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv9204 Modified Files: Tag: release22-maint ref3.tex Log Message: Backport 1.94: Clarified that the footnote applies to versions 1.5 and after instead of just version 1.5. Closes SF bug 577793. Index: ref3.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref3.tex,v retrieving revision 1.82.4.5 retrieving revision 1.82.4.6 diff -C2 -d -r1.82.4.5 -r1.82.4.6 *** ref3.tex 24 Sep 2002 21:01:07 -0000 1.82.4.5 --- ref3.tex 5 Oct 2002 06:40:49 -0000 1.82.4.6 *************** *** 960,967 **** globals referenced by the \method{__del__()} method may already have been deleted. For this reason, \method{__del__()} methods should do the ! absolute minimum needed to maintain external invariants. Python 1.5 ! guarantees that globals whose name begins with a single underscore are ! deleted from their module before other globals are deleted; if no ! other references to such globals exist, this may help in assuring that imported modules are still available at the time when the \method{__del__()} method is called. --- 960,967 ---- globals referenced by the \method{__del__()} method may already have been deleted. For this reason, \method{__del__()} methods should do the ! absolute minimum needed to maintain external invariants. Starting with ! version 1.5, Python guarantees that globals whose name begins with a single ! underscore are deleted from their module before other globals are deleted; ! if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the \method{__del__()} method is called. From rhettinger@users.sourceforge.net Sat Oct 5 07:51:36 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 04 Oct 2002 23:51:36 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref5.tex,1.53.4.6,1.53.4.7 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv11196 Modified Files: Tag: release22-maint ref5.tex Log Message: Backport 1.61 (note, the actual deprecation is not backported since it could affect existing code; instead, the documentation of the deprecation is being backported to provide maximum advance notice): Patch 543387. Document deprecation of complex %, //,and divmod(). Index: ref5.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref5.tex,v retrieving revision 1.53.4.6 retrieving revision 1.53.4.7 diff -C2 -d -r1.53.4.6 -r1.53.4.7 *** ref5.tex 25 Jun 2002 04:00:24 -0000 1.53.4.6 --- ref5.tex 5 Oct 2002 06:51:34 -0000 1.53.4.7 *************** *** 706,710 **** modulo are also connected with the built-in function \function{divmod()}: \code{divmod(x, y) == (x/y, x\%y)}. These identities don't hold for ! floating point and complex numbers; there similar identities hold approximately where \code{x/y} is replaced by \code{floor(x/y)}) or \code{floor(x/y) - 1} (for floats),\footnote{ --- 706,710 ---- modulo are also connected with the built-in function \function{divmod()}: \code{divmod(x, y) == (x/y, x\%y)}. These identities don't hold for ! floating point numbers; there similar identities hold approximately where \code{x/y} is replaced by \code{floor(x/y)}) or \code{floor(x/y) - 1} (for floats),\footnote{ *************** *** 714,719 **** the latter result, in order to preserve that \code{divmod(x,y)[0] * y + x \%{} y} be very close to \code{x}. ! } or \code{floor((x/y).real)} (for ! complex). The \code{+} (addition) operator yields the sum of its arguments. --- 714,724 ---- the latter result, in order to preserve that \code{divmod(x,y)[0] * y + x \%{} y} be very close to \code{x}. ! }. ! ! Complex floor division operator, modulo operator, and ! \function{divmod()}. ! ! \deprecated{2.3}{Instead convert to float using \function{abs()} ! if appropriate.} The \code{+} (addition) operator yields the sum of its arguments. From loewis@users.sourceforge.net Sat Oct 5 10:46:50 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sat, 05 Oct 2002 02:46:50 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.492,1.493 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv19723/Misc Modified Files: NEWS Log Message: Document patch #594001. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.492 retrieving revision 1.493 diff -C2 -d -r1.492 -r1.493 *** NEWS 4 Oct 2002 11:55:21 -0000 1.492 --- NEWS 5 Oct 2002 09:46:48 -0000 1.493 *************** *** 67,70 **** --- 67,72 ---- ----------------- + - Unicode file name processing for Windows (PEP 277) is implemented. + - Codec error handling callbacks (PEP 293) are implemented. Error handling in unicode.encode or str.decode can now be customized. From loewis@users.sourceforge.net Sat Oct 5 10:46:50 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sat, 05 Oct 2002 02:46:50 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libos.tex,1.96,1.97 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv19723/Doc/lib Modified Files: libos.tex Log Message: Document patch #594001. Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.96 retrieving revision 1.97 diff -C2 -d -r1.96 -r1.97 *** libos.tex 9 Sep 2002 16:17:45 -0000 1.96 --- libos.tex 5 Oct 2002 09:46:48 -0000 1.97 *************** *** 636,639 **** --- 636,645 ---- \end{funcdesc} + \begin{funcdesc}{getcwdu}{} + Return a Unicode object representing the current working directory. + Availability: \UNIX, Windows. + \versionadded{2.3} + \end{funcdesc} + \begin{funcdesc}{chroot}{path} Change the root directory of the current process to \var{path}. *************** *** 671,674 **** --- 677,683 ---- directory. Availability: Macintosh, \UNIX, Windows. + + \versionadded[On Windows NT/2k/XP, if \var{path} is a Unicode object, + the result will be a list of Unicode objects.]{2.3} \end{funcdesc} From rhettinger@users.sourceforge.net Sat Oct 5 15:42:54 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 07:42:54 -0700 Subject: [Python-checkins] python/dist/src/Lib random.py,1.26.6.6,1.26.6.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv17518 Modified Files: Tag: release22-maint random.py Log Message: Backport 1.33 (omitting the deprecation warning but keeping the deprecation comment): Deprecated Random.cunifvariate clearing bug 506647. Also, added docstrings. Index: random.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/random.py,v retrieving revision 1.26.6.6 retrieving revision 1.26.6.7 diff -C2 -d -r1.26.6.6 -r1.26.6.7 *** random.py 23 Sep 2002 14:52:40 -0000 1.26.6.6 --- random.py 5 Oct 2002 14:42:52 -0000 1.26.6.7 *************** *** 108,111 **** --- 108,124 ---- class Random: + """Random number generator base class used by bound module functions. + + Used to instantiate instances of Random to get generators that don't + share state. Especially useful for multi-threaded programs, creating + a different instance of Random for each thread, and using the jumpahead() + method to ensure that the generated sequences seen by each thread don't + overlap. + + Class Random can also be subclassed if you want to use a different basic + generator of your own devising: in that case, override the following + methods: random(), seed(), getstate(), setstate() and jumpahead(). + + """ VERSION = 1 # used by getstate/setstate *************** *** 372,375 **** --- 385,393 ---- def normalvariate(self, mu, sigma): + """Normal distribution. + + mu is the mean, and sigma is the standard deviation. + + """ # mu = mean, sigma = standard deviation *************** *** 392,395 **** --- 410,420 ---- def lognormvariate(self, mu, sigma): + """Log normal distribution. + + If you take the natural logarithm of this distribution, you'll get a + normal distribution with mean mu and standard deviation sigma. + mu can have any value, and sigma must be greater than zero. + + """ return _exp(self.normalvariate(mu, sigma)) *************** *** 397,400 **** --- 422,436 ---- def cunifvariate(self, mean, arc): + """Circular uniform distribution. + + mean is the mean angle, and arc is the range of the distribution, + centered around the mean angle. Both values must be expressed in + radians. Returned values range between mean - arc/2 and + mean + arc/2 and are normalized to between 0 and pi. + + Deprecated in version 2.3. Use: + (mean + arc * (Random.random() - 0.5)) % Math.pi + + """ # mean: mean angle (in radians between 0 and pi) # arc: range of distribution (in radians between 0 and pi) *************** *** 405,408 **** --- 441,451 ---- def expovariate(self, lambd): + """Exponential distribution. + + lambd is 1.0 divided by the desired mean. (The parameter would be + called "lambda", but that is a reserved word in Python.) Returned + values range from 0 to positive infinity. + + """ # lambd: rate lambd = 1/mean # ('lambda' is a Python reserved word) *************** *** 417,420 **** --- 460,471 ---- def vonmisesvariate(self, mu, kappa): + """Circular data distribution. + + mu is the mean angle, expressed in radians between 0 and 2*pi, and + kappa is the concentration parameter, which must be greater than or + equal to zero. If kappa is equal to zero, this distribution reduces + to a uniform random angle over the range 0 to 2*pi. + + """ # mu: mean angle (in radians between 0 and 2*pi) # kappa: concentration parameter kappa (>= 0) *************** *** 459,462 **** --- 510,518 ---- def gammavariate(self, alpha, beta): + """Gamma distribution. Not the gamma function! + + Conditions on the parameters are alpha > 0 and beta > 0. + + """ # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2 *************** *** 538,541 **** --- 594,605 ---- def gauss(self, mu, sigma): + """Gaussian distribution. + + mu is the mean, and sigma is the standard deviation. This is + slightly faster than the normalvariate() function. + + Not thread-safe without a lock around calls. + + """ # When x and y are two variables from [0, 1), uniformly *************** *** 583,586 **** --- 647,657 ---- def betavariate(self, alpha, beta): + """Beta distribution. + + Conditions on the parameters are alpha > -1 and beta} > -1. + Returned values range between 0 and 1. + + """ + # This version due to Janne Sinkkonen, and matches all the std # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution"). *************** *** 594,597 **** --- 665,669 ---- def paretovariate(self, alpha): + """Pareto distribution. alpha is the shape parameter.""" # Jain, pg. 495 *************** *** 602,605 **** --- 674,682 ---- def weibullvariate(self, alpha, beta): + """Weibull distribution. + + alpha is the scale parameter and beta is the shape parameter. + + """ # Jain, pg. 499; bug fix courtesy Bill Arms From rhettinger@users.sourceforge.net Sat Oct 5 16:00:12 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 08:00:12 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib librandom.tex,1.25.18.3,1.25.18.4 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv26146 Modified Files: Tag: release22-maint librandom.tex Log Message: Backport 1.30 and 1.29: Markup adjustments; fix the names of modules referenced in an expression. Deprecated Random.cunifvariate clearing bug 506647. Index: librandom.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/librandom.tex,v retrieving revision 1.25.18.3 retrieving revision 1.25.18.4 diff -C2 -d -r1.25.18.3 -r1.25.18.4 *** librandom.tex 13 May 2002 23:47:02 -0000 1.25.18.3 --- librandom.tex 5 Oct 2002 15:00:09 -0000 1.25.18.4 *************** *** 207,211 **** between 0 and \emph{pi}. Returned values range between \code{\var{mean} - \var{arc}/2} and \code{\var{mean} + ! \var{arc}/2}. \end{funcdesc} --- 207,214 ---- between 0 and \emph{pi}. Returned values range between \code{\var{mean} - \var{arc}/2} and \code{\var{mean} + ! \var{arc}/2} and are normalized to between 0 and \emph{pi}. ! ! \deprecated{2.3}{Instead, use \code{(\var{mean} + \var{arc} * ! (random.random() - 0.5)) \% math.pi}.} \end{funcdesc} From rhettinger@users.sourceforge.net Sat Oct 5 16:14:35 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 08:14:35 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib librotor.tex,1.18,1.18.22.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv638 Modified Files: Tag: release22-maint librotor.tex Log Message: Backport 1.19: Document that the key should not contain null bytes. Index: librotor.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/librotor.tex,v retrieving revision 1.18 retrieving revision 1.18.22.1 diff -C2 -d -r1.18 -r1.18.22.1 *** librotor.tex 24 Jan 2001 17:19:07 -0000 1.18 --- librotor.tex 5 Oct 2002 15:14:33 -0000 1.18.22.1 *************** *** 30,34 **** \begin{funcdesc}{newrotor}{key\optional{, numrotors}} Return a rotor object. \var{key} is a string containing the encryption key ! for the object; it can contain arbitrary binary data. The key will be used to randomly generate the rotor permutations and their initial positions. \var{numrotors} is the number of rotor permutations in the returned object; --- 30,35 ---- \begin{funcdesc}{newrotor}{key\optional{, numrotors}} Return a rotor object. \var{key} is a string containing the encryption key ! for the object; it can contain arbitrary binary data but not null bytes. ! The key will be used to randomly generate the rotor permutations and their initial positions. \var{numrotors} is the number of rotor permutations in the returned object; *************** *** 39,43 **** \begin{methoddesc}[rotor]{setkey}{key} ! Sets the rotor's key to \var{key}. \end{methoddesc} --- 40,44 ---- \begin{methoddesc}[rotor]{setkey}{key} ! Sets the rotor's key to \var{key}. The key should not contain null bytes. \end{methoddesc} From rhettinger@users.sourceforge.net Sat Oct 5 16:25:35 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 08:25:35 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libre.tex,1.73.6.9,1.73.6.10 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv5277 Modified Files: Tag: release22-maint libre.tex Log Message: Backport 1.88 and 1.87: Update docs to reflect that \b considers underscore to be part of a word. Index: libre.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libre.tex,v retrieving revision 1.73.6.9 retrieving revision 1.73.6.10 diff -C2 -d -r1.73.6.9 -r1.73.6.10 *** libre.tex 20 Aug 2002 13:58:12 -0000 1.73.6.9 --- libre.tex 5 Oct 2002 15:25:33 -0000 1.73.6.10 *************** *** 332,342 **** \item[\code{\e b}] Matches the empty string, but only at the beginning or end of a word. A word is defined as a sequence of ! alphanumeric characters, so the end of a word is indicated by ! whitespace or a non-alphanumeric character. Inside a character range, ! \regexp{\e b} represents the backspace character, for compatibility with ! Python's string literals. ! \item[\code{\e B}] Matches the empty string, but only when it is ! \emph{not} at the beginning or end of a word. \item[\code{\e d}]Matches any decimal digit; this is --- 332,346 ---- \item[\code{\e b}] Matches the empty string, but only at the beginning or end of a word. A word is defined as a sequence of ! alphanumeric or underscore characters, so the end of a word is indicated by ! whitespace or a non-alphanumeric, non-underscore character. Note that ! {}\code{\e b} is defined as the boundary between \code{\e w} and \code{\e ! W}, so the precise set of characters deemed to be alphanumeric depends on the ! values of the \code{UNICODE} and \code{LOCALE} flags. Inside a character ! range, \regexp{\e b} represents the backspace character, for compatibility ! with Python's string literals. ! \item[\code{\e B}] Matches the empty string, but only when it is \emph{not} ! at the beginning or end of a word. This is just the opposite of {}\code{\e ! b}, so is also subject to the settings of \code{LOCALE} and \code{UNICODE}. \item[\code{\e d}]Matches any decimal digit; this is From rhettinger@users.sourceforge.net Sat Oct 5 16:38:19 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 08:38:19 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libstdtypes.tex,1.80.6.12,1.80.6.13 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv11024 Modified Files: Tag: release22-maint libstdtypes.tex Log Message: Backport 1.100: Discussion of Stop Iteration in the Iterator Protocol. Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.80.6.12 retrieving revision 1.80.6.13 diff -C2 -d -r1.80.6.12 -r1.80.6.13 *** libstdtypes.tex 19 Aug 2002 22:01:19 -0000 1.80.6.12 --- libstdtypes.tex 5 Oct 2002 15:38:16 -0000 1.80.6.13 *************** *** 368,371 **** --- 368,378 ---- implementation of the iterator protocol. + The intention of the protocol is that once an iterator's + \method{next()} method raises \exception{StopIteration}, it will + continue to do so on subsequent calls. Implementations that + do not obey this property are deemed broken. (This constraint + was added in Python 2.3; in Python 2.2, various iterators are + broken according to this rule.) + \subsection{Sequence Types \label{typesseq}} From rhettinger@users.sourceforge.net Sat Oct 5 16:41:58 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 08:41:58 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libstdtypes.tex,1.80.6.13,1.80.6.14 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv13793 Modified Files: Tag: release22-maint libstdtypes.tex Log Message: Backport 1.94: Patch 543387. Document deprecation of complex %, //,and divmod(). Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.80.6.13 retrieving revision 1.80.6.14 diff -C2 -d -r1.80.6.13 -r1.80.6.14 *** libstdtypes.tex 5 Oct 2002 15:38:16 -0000 1.80.6.13 --- libstdtypes.tex 5 Oct 2002 15:41:56 -0000 1.80.6.14 *************** *** 218,223 **** \bifuncindex{complex} ! All numeric types support the following operations, sorted by ! ascending priority (operations in the same box have the same priority; all numeric operations have a higher priority than comparison operations): --- 218,223 ---- \bifuncindex{complex} ! All numeric types (except complex) support the following operations, ! sorted by ascending priority (operations in the same box have the same priority; all numeric operations have a higher priority than comparison operations): *************** *** 229,233 **** \lineiii{\var{x} * \var{y}}{product of \var{x} and \var{y}}{} \lineiii{\var{x} / \var{y}}{quotient of \var{x} and \var{y}}{(1)} ! \lineiii{\var{x} \%{} \var{y}}{remainder of \code{\var{x} / \var{y}}}{} \hline \lineiii{-\var{x}}{\var{x} negated}{} --- 229,233 ---- \lineiii{\var{x} * \var{y}}{product of \var{x} and \var{y}}{} \lineiii{\var{x} / \var{y}}{quotient of \var{x} and \var{y}}{(1)} ! \lineiii{\var{x} \%{} \var{y}}{remainder of \code{\var{x} / \var{y}}}{(4)} \hline \lineiii{-\var{x}}{\var{x} negated}{} *************** *** 240,244 **** \lineiii{complex(\var{re},\var{im})}{a complex number with real part \var{re}, imaginary part \var{im}. \var{im} defaults to zero.}{} \lineiii{\var{c}.conjugate()}{conjugate of the complex number \var{c}}{} ! \lineiii{divmod(\var{x}, \var{y})}{the pair \code{(\var{x} / \var{y}, \var{x} \%{} \var{y})}}{(3)} \lineiii{pow(\var{x}, \var{y})}{\var{x} to the power \var{y}}{} \lineiii{\var{x} ** \var{y}}{\var{x} to the power \var{y}}{} --- 240,244 ---- \lineiii{complex(\var{re},\var{im})}{a complex number with real part \var{re}, imaginary part \var{im}. \var{im} defaults to zero.}{} \lineiii{\var{c}.conjugate()}{conjugate of the complex number \var{c}}{} ! \lineiii{divmod(\var{x}, \var{y})}{the pair \code{(\var{x} / \var{y}, \var{x} \%{} \var{y})}}{(3)(4)} \lineiii{pow(\var{x}, \var{y})}{\var{x} to the power \var{y}}{} \lineiii{\var{x} ** \var{y}}{\var{x} to the power \var{y}}{} *************** *** 272,275 **** --- 272,281 ---- See section \ref{built-in-funcs}, ``Built-in Functions,'' for a full description. + + \item[(4)] + Complex floor division operator, modulo operator, and \function{divmod()}. + + \deprecated{2.3}{Instead convert to float using \function{abs()} + if appropriate.} \end{description} From rhettinger@users.sourceforge.net Sat Oct 5 16:50:43 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 08:50:43 -0700 Subject: [Python-checkins] python/dist/src/Doc/ext building.tex,1.1.2.2,1.1.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ext In directory usw-pr-cvs1:/tmp/cvs-serv18169 Modified Files: Tag: release22-maint building.tex Log Message: Typo Index: building.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/building.tex,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -C2 -d -r1.1.2.2 -r1.1.2.3 *** building.tex 16 May 2002 13:47:31 -0000 1.1.2.2 --- building.tex 5 Oct 2002 15:50:41 -0000 1.1.2.3 *************** *** 9,13 **** mechanism (known as related to Makefile.pre.in, and Setup files) is no longer supported. Building custom interpreters was rarely used, and ! extensions modules can be built using distutils. Building an extension module using distutils requires that distutils --- 9,13 ---- mechanism (known as related to Makefile.pre.in, and Setup files) is no longer supported. Building custom interpreters was rarely used, and ! extension modules can be built using distutils. Building an extension module using distutils requires that distutils From rhettinger@users.sourceforge.net Sat Oct 5 16:52:40 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 08:52:40 -0700 Subject: [Python-checkins] python/dist/src/Doc/ext windows.tex,1.3.6.2,1.3.6.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ext In directory usw-pr-cvs1:/tmp/cvs-serv19130 Modified Files: Tag: release22-maint windows.tex Log Message: Typo Index: windows.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/windows.tex,v retrieving revision 1.3.6.2 retrieving revision 1.3.6.3 diff -C2 -d -r1.3.6.2 -r1.3.6.3 *** windows.tex 19 Apr 2002 04:06:06 -0000 1.3.6.2 --- windows.tex 5 Oct 2002 15:52:38 -0000 1.3.6.3 *************** *** 111,115 **** \item ! \strong{Cretating your own project}\\ Choose a name and create a directory for it. Copy your C sources into it. Note that the module source file name does not --- 111,115 ---- \item ! \strong{Creating your own project}\\ Choose a name and create a directory for it. Copy your C sources into it. Note that the module source file name does not From rhettinger@users.sourceforge.net Sat Oct 5 17:55:13 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 09:55:13 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref4.tex,1.28.18.2,1.28.18.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv11498 Modified Files: Tag: release22-maint ref4.tex Log Message: Backported Jeremy's documentation of nested scopes, execution frames and such. Index: ref4.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref4.tex,v retrieving revision 1.28.18.2 retrieving revision 1.28.18.3 diff -C2 -d -r1.28.18.2 -r1.28.18.3 *** ref4.tex 28 Aug 2002 02:10:04 -0000 1.28.18.2 --- ref4.tex 5 Oct 2002 16:55:11 -0000 1.28.18.3 *************** *** 3,165 **** ! \section{Code blocks, execution frames, and namespaces \label{execframes}} ! \index{code block} \index{namespace} ! \indexii{execution}{frame} ! A \dfn{code block}\indexii{code}{block} is a piece ! of Python program text that can be executed as a unit, such as a ! module, a class definition or a function body. Some code blocks (like ! modules) are normally executed only once, others (like function ! bodies) may be executed many times. Code blocks may textually contain ! other code blocks. Code blocks may invoke other code blocks (that may ! or may not be textually contained in them) as part of their execution, ! e.g., by invoking (calling) a function. ! The following are code blocks: A module is a code block. A function ! body is a code block. A class definition is a code block. Each ! command typed interactively is a separate code block; a script file (a ! file given as standard input to the interpreter or specified on the ! interpreter command line the first argument) is a code block; a script ! command (a command specified on the interpreter command line with the ! `\strong{-c}' option) is a code block. The file read by the built-in ! function \function{execfile()} is a code block. The string argument ! passed to the built-in function \function{eval()} and to the ! \keyword{exec} statement is a code block. And finally, the expression ! read and evaluated by the built-in function \function{input()} is a ! code block. ! A code block is executed in an execution frame. An \dfn{execution ! frame}\indexii{execution}{frame} contains some administrative ! information (used for debugging), determines where and how execution ! continues after the code block's execution has completed, and (perhaps ! most importantly) defines two namespaces, the local and the global ! namespace, that affect execution of the code block. ! A \dfn{namespace}\index{namespace} is a mapping from names ! (identifiers) to objects. A particular namespace may be referenced by ! more than one execution frame, and from other places as well. Adding ! a name to a namespace is called \dfn{binding}\indexii{binding}{name} a ! name (to an object); changing the mapping of a name is called ! \dfn{rebinding}\indexii{rebinding}{name}; removing a name is ! \dfn{unbinding}\indexii{unbinding}{name}. Namespaces are functionally ! equivalent to dictionaries (and often implemented as dictionaries). ! The \dfn{local namespace}\indexii{local}{namespace} of an execution ! frame determines the default place where names are defined and ! searched. The ! \dfn{global namespace}\indexii{global}{namespace} determines the place ! where names listed in \keyword{global}\stindex{global} statements are ! defined and searched, and where names that are not bound anywhere in ! the current code block are searched. ! Whether a name is local or global in a code block is determined by ! static inspection of the source text for the code block: in the ! absence of \keyword{global} statements, a name that is bound anywhere ! in the code block is local in the entire code block; all other names ! are considered global. The \keyword{global} statement forces global ! interpretation of selected names throughout the code block. The ! following constructs bind names: formal parameters to functions, \keyword{import} statements, class and function definitions (these bind the class or function name in the defining block), and targets that are identifiers if occurring in an assignment, \keyword{for} loop header, or in the second position of an \keyword{except} clause ! header. Local names are searched only on the local namespace; global ! names are searched only in the global and built-in ! namespace.\footnote{ ! If the code block contains \keyword{exec} statements or the ! construct ``\samp{from \ldots import *}'', the semantics of local ! names change: local name lookup first searches the local namespace, ! then the global namespace and the built-in namespace.} A target occurring in a \keyword{del} statement is also considered bound ! for this purpose (though the actual semantics are to ``unbind'' the ! name). ! When a global name is not found in the global namespace, it is ! searched in the built-in namespace (which is actually the global ! namespace of the module ! \module{__builtin__}\refbimodindex{__builtin__}). The built-in ! namespace associated with the execution of a code block is actually ! found by looking up the name \code{__builtins__} in its global ! namespace; this should be a dictionary or a module (in the latter case ! its dictionary is used). Normally, the \code{__builtins__} namespace ! is the dictionary of the built-in module \module{__builtin__} (note: ! no `s'); if it isn't, restricted ! execution\indexii{restricted}{execution} mode is in effect. When a ! name is not found at all, a ! \exception{NameError}\withsubitem{(built-in ! exception)}{\ttindex{NameError}} exception is raised. ! \stindex{from} ! \stindex{exec} ! \stindex{global} ! The following table lists the meaning of the local and global ! namespace for various types of code blocks. The namespace for a ! particular module is automatically created when the module is first ! imported (i.e., when it is loaded). Note that in almost all cases, ! the global namespace is the namespace of the containing module --- ! scopes in Python do not nest! ! \begin{tableiv}{l|l|l|l}{textrm} ! {Code block type}{Global namespace}{Local namespace}{Notes} ! \lineiv{Module} ! {n.s. for this module} ! {same as global}{} ! \lineiv{Script (file or command)} ! {n.s. for \module{__main__}\refbimodindex{__main__}} ! {same as global}{(1)} ! \lineiv{Interactive command} ! {n.s. for \module{__main__}\refbimodindex{__main__}} ! {same as global}{} ! \lineiv{Class definition} ! {global n.s. of containing block} ! {new n.s.}{} ! \lineiv{Function body} ! {global n.s. of containing block} ! {new n.s.}{(2)} ! \lineiv{String passed to \keyword{exec} statement} ! {global n.s. of containing block} ! {local n.s. of containing block}{(2), (3)} ! \lineiv{String passed to \function{eval()}} ! {global n.s. of caller} ! {local n.s. of caller}{(2), (3)} ! \lineiv{File read by \function{execfile()}} ! {global n.s. of caller} ! {local n.s. of caller}{(2), (3)} ! \lineiv{Expression read by \function{input()}} ! {global n.s. of caller} ! {local n.s. of caller}{} ! \end{tableiv} ! Notes: ! \begin{description} ! \item[n.s.] means \emph{namespace} ! \item[(1)] The main module for a script is always called ! \module{__main__}; ``the filename don't enter into it.'' ! \item[(2)] The global and local namespace for these can be ! overridden with optional extra arguments. ! \item[(3)] The \keyword{exec} statement and the \function{eval()} and ! \function{execfile()} functions have optional arguments to override ! the global and local namespace. If only one namespace is specified, ! it is used for both. ! \end{description} ! The built-in functions \function{globals()} and \function{locals()} returns a ! dictionary representing the current global and local namespace, ! respectively. The effect of modifications to this dictionary on the ! namespace are undefined.\footnote{ ! The current implementations return the dictionary actually used to ! implement the namespace, \emph{except} for functions, where the ! optimizer may cause the local namespace to be implemented ! differently, and \function{locals()} returns a read-only ! dictionary.} \section{Exceptions \label{exceptions}} --- 3,152 ---- ! \section{Naming and binding \label{naming}} ! \indexii{code}{block} \index{namespace} ! \index{scope} ! \dfn{Names}\index{name} refer to objects. Names are introduced by ! name binding operations. Each occurrence of a name in the program ! text refers to the \dfn{binding}\indexii{binding}{name} of that name ! established in the innermost function block containing the use. ! A \dfn{block}\index{block} is a piece of Python program text that is ! executed as a unit. The following are blocks: a module, a function ! body, and a class definition. Each command typed interactively is a ! block. A script file (a file given as standard input to the ! interpreter or specified on the interpreter command line the first ! argument) is a code block. A script command (a command specified on ! the interpreter command line with the `\strong{-c}' option) is a code ! block. The file read by the built-in function \function{execfile()} ! is a code block. The string argument passed to the built-in function ! \function{eval()} and to the \keyword{exec} statement is a code block. ! The expression read and evaluated by the built-in function ! \function{input()} is a code block. ! A code block is executed in an \dfn{execution ! frame}\indexii{execution}{frame}. A frame contains some ! administrative information (used for debugging) and determines where ! and how execution continues after the code block's execution has ! completed. ! A \dfn{scope}\index{scope} defines the visibility of a name within a ! block. If a local variable is defined in a block, its scope includes ! that block. If the definition occurs in a function block, the scope ! extends to any blocks contained within the defining one, unless a ! contained block introduces a different binding for the name. The ! scope of names defined in a class block is limited to the class block; ! it does not extend to the code blocks of methods. ! When a name is used in a code block, it is resolved using the nearest ! enclosing scope. The set of all such scopes visible to a code block ! is called the block's \dfn{environment}\index{environment}. ! If a name is bound in a block, it is a local variable of that block. ! If a name is bound at the module level, it is a global variable. (The ! variables of the module code block are local and global.) If a ! variable is used in a code block but not defined there, it is a ! \dfn{free variable}\indexii{free}{variable}. ! ! When a name is not found at all, a ! \exception{NameError}\withsubitem{(built-in ! exception)}{\ttindex{NameError}} exception is raised. If the name ! refers to a local variable that has not been bound, a ! \exception{UnboundLocalError}\ttindex{UnboundLocalError} exception is ! raised. \exception{UnboundLocalError} is a subclass of ! \exception{NameError}. ! ! The following constructs bind names: formal parameters to functions, \keyword{import} statements, class and function definitions (these bind the class or function name in the defining block), and targets that are identifiers if occurring in an assignment, \keyword{for} loop header, or in the second position of an \keyword{except} clause ! header. The \keyword{import} statement of the form ``\samp{from ! \ldots import *}''\stindex{from} binds all names defined in the ! imported module, except those beginning with an underscore. This form ! may only be used at the module level. A target occurring in a \keyword{del} statement is also considered bound ! for this purpose (though the actual semantics are to unbind the ! name). It is illegal to unbind a name that is referenced by an ! enclosing scope; the compiler will report a \exception{SyntaxError}. ! Each assignment or import statement occurs within a block defined by a ! class or function definition or at the module level (the top-level ! code block). ! If a name binding operation occurs anywhere within a code block, all ! uses of the name within the block are treated as references to the ! current block. This can lead to errors when a name is used within a ! block before it is bound. ! The previous rule is a subtle. Python lacks declarations and allows ! name binding operations to occur anywhere within a code block. The ! local variables of a code block can be determined by scanning the ! entire text of the block for name binding operations. ! If the global statement occurs within a block, all uses of the name ! specified in the statement refer to the binding of that name in the ! top-level namespace. Names are resolved in the top-level namespace by ! searching the global namespace, i.e. the namespace of the module ! containing the code block, and the builtin namespace, the namespace of ! the module \module{__builtin__}. The global namespace is searched ! first. If the name is not found there, the builtin namespace is ! searched. The global statement must precede all uses of the name. ! The built-in namespace associated with the execution of a code block ! is actually found by looking up the name \code{__builtins__} in its ! global namespace; this should be a dictionary or a module (in the ! latter case the module's dictionary is used). Normally, the ! \code{__builtins__} namespace is the dictionary of the built-in module ! \module{__builtin__} (note: no `s'). If it isn't, restricted ! execution\indexii{restricted}{execution} mode is in effect. ! The namespace for a module is automatically created the first time a ! module is imported. The main module for a script is always called ! \module{__main__}\refbimodindex{__main__}. ! The global statement has the same scope as a name binding operation ! in the same block. If the nearest enclosing scope for a free variable ! contains a global statement, the free variable is treated as a global. ! A class definition is an executable statement that may use and define ! names. These references follow the normal rules for name resolution. ! The namespace of the class definition becomes the attribute dictionary ! of the class. Names defined at the class scope are not visible in ! methods. ! \subsection{Interaction with dynamic features \label{dynamic-features}} ! There are several cases where Python statements are illegal when ! used in conjunction with nested scopes that contain free ! variables. ! If a variable is referenced in an enclosing scope, it is illegal ! to delete the name. An error will be reported at compile time. + If the wild card form of import --- \samp{import *} --- is used in a + function and the function contains or is a nested block with free + variables, the compiler will raise a SyntaxError. + + If \keyword{exec} is used in a function and the function contains or + is a nested block with free variables, the compiler will raise a + \exception{SyntaxError} unless the exec explicitly specifies the local + namespace for the \keyword{exec}. (In other words, \samp{exec obj} + would be illegal, but \samp{exec obj in ns} would be legal.) + + The \function{eval()}, \function{execfile()}, and \function{input()} + functions and the \keyword{exec} statement do not have access to the + full environment for resolving names. Names may be resolved in the + local and global namespaces of the caller. Free variables are not + resolved in the nearest enclosing namespace, but in the global + namespace.\footnote{This limitation occurs because the code that is + executed by these operations is not available at the time the + module is compiled.} + The \keyword{exec} statement and the \function{eval()} and + \function{execfile()} functions have optional arguments to override + the global and local namespace. If only one namespace is specified, + it is used for both. \section{Exceptions \label{exceptions}} *************** *** 206,214 **** When an exception is raised, an object (maybe \code{None}) is passed ! as the exception's ``parameter'' or ``value''; this object does not ! affect the selection of an exception handler, but is passed to the ! selected exception handler as additional information. For class ! exceptions, this object must be an instance of the exception class ! being raised. \begin{notice}[warning] --- 193,200 ---- When an exception is raised, an object (maybe \code{None}) is passed ! as the exception's \emph{value}; this object does not affect the ! selection of an exception handler, but is passed to the selected ! exception handler as additional information. For class exceptions, ! this object must be an instance of the exception class being raised. \begin{notice}[warning] From tim_one@users.sourceforge.net Sat Oct 5 18:54:59 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sat, 05 Oct 2002 10:54:59 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_pep277.py,1.1,1.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv27605/python/Lib/test Modified Files: test_pep277.py Log Message: This test fails on Win98, which is fine, but when it failed it left a junk directory behind that caused 4 other tests to fail later. Now it cleans up after itself, and the 4 bogus later failures don't happen. Index: test_pep277.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_pep277.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** test_pep277.py 3 Oct 2002 23:14:10 -0000 1.1 --- test_pep277.py 5 Oct 2002 17:54:56 -0000 1.2 *************** *** 7,11 **** from nt import _getfullpathname except ImportError: ! raise TestSkipped, "test works only on NT" filenames = [ --- 7,11 ---- from nt import _getfullpathname except ImportError: ! raise TestSkipped, "test works only on NT+" filenames = [ *************** *** 21,27 **** ] class UnicodeFileTests(unittest.TestCase): def setUp(self): - self.files = [os.path.join(TESTFN, f) for f in filenames] try: os.mkdir(TESTFN) --- 21,37 ---- ] + # Destroy directory dirname and all files under it, to one level. + def deltree(dirname): + # Don't hide legitimate errors: if one of these suckers exists, it's + # an error if we can't remove it. + if os.path.exists(dirname): + for fname in os.listdir(dirname): + os.unlink(os.path.join(dirname, fname)) + os.rmdir(dirname) + class UnicodeFileTests(unittest.TestCase): + files = [os.path.join(TESTFN, f) for f in filenames] + def setUp(self): try: os.mkdir(TESTFN) *************** *** 35,41 **** def tearDown(self): ! for name in self.files: ! os.unlink(name) ! os.rmdir(TESTFN) def _apply_failure(self, fn, filename, expected_exception, --- 45,49 ---- def tearDown(self): ! deltree(TESTFN) def _apply_failure(self, fn, filename, expected_exception, *************** *** 101,105 **** suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(UnicodeFileTests)) ! run_suite(suite) if __name__ == "__main__": --- 109,116 ---- suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(UnicodeFileTests)) ! try: ! run_suite(suite) ! finally: ! deltree(TESTFN) if __name__ == "__main__": From rhettinger@users.sourceforge.net Sat Oct 5 21:43:47 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 13:43:47 -0700 Subject: [Python-checkins] python/dist/src/Objects complexobject.c,2.53.4.5,2.53.4.6 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv14781 Modified Files: Tag: release22-maint complexobject.c Log Message: Backport 2.63 and 2.60: Call me anal, but there was a particular phrase that was speading to comments everywhere that bugged me: /* Foo is inlined */ instead of /* Inline Foo */. Somehow the "is inlined" phrase always confused me for half a second (thinking, "No it isn't" until I added the missing "here"). The new phrase is hopefully unambiguous. Close SF bug 563740. complex() now finds __complex__() in new style classes. Made conversion failure error messages consistent between types. Added related unittests. Index: complexobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/complexobject.c,v retrieving revision 2.53.4.5 retrieving revision 2.53.4.6 diff -C2 -d -r2.53.4.5 -r2.53.4.6 *** complexobject.c 18 Apr 2002 05:39:54 -0000 2.53.4.5 --- complexobject.c 5 Oct 2002 20:43:43 -0000 2.53.4.6 *************** *** 200,204 **** register PyComplexObject *op; ! /* PyObject_New is inlined */ op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject)); if (op == NULL) --- 200,204 ---- register PyComplexObject *op; ! /* Inline PyObject_New */ op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject)); if (op == NULL) *************** *** 812,819 **** complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { ! PyObject *r, *i, *tmp; PyNumberMethods *nbr, *nbi = NULL; Py_complex cr, ci; int own_r = 0; static char *kwlist[] = {"real", "imag", 0}; --- 812,820 ---- complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { ! PyObject *r, *i, *tmp, *f; PyNumberMethods *nbr, *nbi = NULL; Py_complex cr, ci; int own_r = 0; + static PyObject *complexstr; static char *kwlist[] = {"real", "imag", 0}; *************** *** 838,841 **** --- 839,862 ---- } + /* XXX Hack to support classes with __complex__ method */ + if (complexstr == NULL) { + complexstr = PyString_InternFromString("__complex__"); + if (complexstr == NULL) + return NULL; + } + f = PyObject_GetAttr(r, complexstr); + if (f == NULL) + PyErr_Clear(); + else { + PyObject *args = Py_BuildValue("()"); + if (args == NULL) + return NULL; + r = PyEval_CallObject(f, args); + Py_DECREF(args); + Py_DECREF(f); + if (r == NULL) + return NULL; + own_r = 1; + } nbr = r->ob_type->tp_as_number; if (i != NULL) *************** *** 844,873 **** ((i != NULL) && (nbi == NULL || nbi->nb_float == NULL))) { PyErr_SetString(PyExc_TypeError, ! "complex() arg can't be converted to complex"); return NULL; - } - /* XXX Hack to support classes with __complex__ method */ - if (PyInstance_Check(r)) { - static PyObject *complexstr; - PyObject *f; - if (complexstr == NULL) { - complexstr = PyString_InternFromString("__complex__"); - if (complexstr == NULL) - return NULL; - } - f = PyObject_GetAttr(r, complexstr); - if (f == NULL) - PyErr_Clear(); - else { - PyObject *args = Py_BuildValue("()"); - if (args == NULL) - return NULL; - r = PyEval_CallObject(f, args); - Py_DECREF(args); - Py_DECREF(f); - if (r == NULL) - return NULL; - own_r = 1; - } } if (PyComplex_Check(r)) { --- 865,870 ---- ((i != NULL) && (nbi == NULL || nbi->nb_float == NULL))) { PyErr_SetString(PyExc_TypeError, ! "complex() argument must be a string or a number"); return NULL; } if (PyComplex_Check(r)) { From rhettinger@users.sourceforge.net Sat Oct 5 22:14:14 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 14:14:14 -0700 Subject: [Python-checkins] python/dist/src/Objects abstract.c,2.93.6.7,2.93.6.8 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv24475 Modified Files: Tag: release22-maint abstract.c Log Message: Backport 2.103: Made conversion failure error messages consistent between types. Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.93.6.7 retrieving revision 2.93.6.8 diff -C2 -d -r2.93.6.7 -r2.93.6.8 *** abstract.c 24 Sep 2002 11:11:12 -0000 2.93.6.7 --- abstract.c 5 Oct 2002 21:14:12 -0000 2.93.6.8 *************** *** 904,908 **** return int_from_string((char*)buffer, buffer_len); ! return type_error("object can't be converted to int"); } --- 904,908 ---- return int_from_string((char*)buffer, buffer_len); ! return type_error("int() argument must be a string or a number"); } *************** *** 961,965 **** return long_from_string(buffer, buffer_len); ! return type_error("object can't be converted to long"); } --- 961,965 ---- return long_from_string(buffer, buffer_len); ! return type_error("long() argument must be a string or a number"); } From rhettinger@users.sourceforge.net Sun Oct 6 03:16:54 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 19:16:54 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libfuncs.tex,1.100.4.11,1.100.4.12 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv32720 Modified Files: Tag: release22-maint libfuncs.tex Log Message: Backport 1.108 documenting Py2.3's impending deprecation of divmod() for complex numbers. Index: libfuncs.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfuncs.tex,v retrieving revision 1.100.4.11 retrieving revision 1.100.4.12 diff -C2 -d -r1.100.4.11 -r1.100.4.12 *** libfuncs.tex 24 Sep 2002 21:01:06 -0000 1.100.4.11 --- libfuncs.tex 6 Oct 2002 02:16:52 -0000 1.100.4.12 *************** *** 252,255 **** --- 252,258 ---- \code{\var{a} \%{} \var{b}} is non-zero it has the same sign as \var{b}, and \code{0 <= abs(\var{a} \%{} \var{b}) < abs(\var{b})}. + + \versionchanged[Using \function{divmod()} with complex numbers is + deprecated]{2.3} \end{funcdesc} From rhettinger@users.sourceforge.net Sun Oct 6 03:24:02 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 19:24:02 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libpickle.tex,1.33,1.33.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv2478 Modified Files: Tag: release22-maint libpickle.tex Log Message: Backport 1.36 documenting Py2.3's impending deprecation of the non-tuple form. Index: libpickle.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libpickle.tex,v retrieving revision 1.33 retrieving revision 1.33.6.1 diff -C2 -d -r1.33 -r1.33.6.1 *** libpickle.tex 26 Nov 2001 21:30:36 -0000 1.33 --- libpickle.tex 6 Oct 2002 02:24:00 -0000 1.33.6.1 *************** *** 439,442 **** --- 439,443 ---- \item A tuple of arguments for the callable object, or \code{None}. + \deprecated{2.3}{Use the tuple of arguments instead} \item Optionally, the object's state, which will be passed to *************** *** 451,458 **** Upon unpickling, the callable will be called (provided that it meets the above criteria), passing in the tuple of arguments; it should ! return the unpickled object. If the second item was \code{None}, then ! instead of calling the callable directly, its \method{__basicnew__()} ! method is called without arguments. It should also return the ! unpickled object. An alternative to implementing a \method{__reduce__()} method on the --- 452,462 ---- Upon unpickling, the callable will be called (provided that it meets the above criteria), passing in the tuple of arguments; it should ! return the unpickled object. ! ! If the second item was \code{None}, then instead of calling the ! callable directly, its \method{__basicnew__()} method is called ! without arguments. It should also return the unpickled object. ! ! \deprecated{2.3}{Use the tuple of arguments instead} An alternative to implementing a \method{__reduce__()} method on the From rhettinger@users.sourceforge.net Sun Oct 6 03:29:05 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 19:29:05 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libxreadlines.tex,1.2.22.1,1.2.22.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv4163 Modified Files: Tag: release22-maint libxreadlines.tex Log Message: Backport 1.4 documenting the impending deprecation of xreadlines. Index: libxreadlines.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libxreadlines.tex,v retrieving revision 1.2.22.1 retrieving revision 1.2.22.2 diff -C2 -d -r1.2.22.1 -r1.2.22.2 *** libxreadlines.tex 6 May 2002 16:03:00 -0000 1.2.22.1 --- libxreadlines.tex 6 Oct 2002 02:29:03 -0000 1.2.22.2 *************** *** 7,10 **** --- 7,11 ---- \versionadded{2.1} + \deprecated{2.3}{Use \code{for line in file} instead.} This module defines a new object type which can efficiently iterate From rhettinger@users.sourceforge.net Sun Oct 6 03:32:37 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 19:32:37 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libmimetools.tex,1.20.16.1,1.20.16.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv5313 Modified Files: Tag: release22-maint libmimetools.tex Log Message: Backport 1.23 documenting impending deprecation in favor to the email package. Index: libmimetools.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libmimetools.tex,v retrieving revision 1.20.16.1 retrieving revision 1.20.16.2 diff -C2 -d -r1.20.16.1 -r1.20.16.2 *** libmimetools.tex 6 Aug 2002 21:22:59 -0000 1.20.16.1 --- libmimetools.tex 6 Oct 2002 02:32:34 -0000 1.20.16.2 *************** *** 5,8 **** --- 5,12 ---- \modulesynopsis{Tools for parsing MIME-style message bodies.} + \deprecated{2.3}{The \refmodule{email} package should be used in + preference to the \module{mimetools} module. This + module is present only to maintain backward + compatibility.} This module defines a subclass of the From rhettinger@users.sourceforge.net Sun Oct 6 03:34:17 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 19:34:17 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libmimewriter.tex,1.2,1.2.26.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv6040 Modified Files: Tag: release22-maint libmimewriter.tex Log Message: Backport 1.3 documenting impending deprecation in favor of the email module. Index: libmimewriter.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libmimewriter.tex,v retrieving revision 1.2 retrieving revision 1.2.26.1 diff -C2 -d -r1.2 -r1.2.26.1 *** libmimewriter.tex 3 Apr 2000 20:13:53 -0000 1.2 --- libmimewriter.tex 6 Oct 2002 02:34:15 -0000 1.2.26.1 *************** *** 7,10 **** --- 7,15 ---- \sectionauthor{Christopher G. Petrilli}{petrilli@amber.org} + \deprecated{2.3}{The \refmodule{email} package should be used in + preference to the \module{MimeWriter} module. This + module is present only to maintain backward + compatibility.} + This module defines the class \class{MimeWriter}. The \class{MimeWriter} class implements a basic formatter for creating From rhettinger@users.sourceforge.net Sun Oct 6 03:36:38 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 19:36:38 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libmimify.tex,1.11.18.1,1.11.18.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv6819 Modified Files: Tag: release22-maint libmimify.tex Log Message: Backport 1.13 documenting impending deprecation in favor of the email module. Index: libmimify.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libmimify.tex,v retrieving revision 1.11.18.1 retrieving revision 1.11.18.2 diff -C2 -d -r1.11.18.1 -r1.11.18.2 *** libmimify.tex 18 Jun 2002 18:51:49 -0000 1.11.18.1 --- libmimify.tex 6 Oct 2002 02:36:36 -0000 1.11.18.2 *************** *** 5,10 **** \modulesynopsis{Mimification and unmimification of mail messages.} ! The mimify module defines two functions to convert mail messages to and from MIME format. The mail message can be either a simple message or a so-called multipart message. Each part is treated separately. --- 5,14 ---- \modulesynopsis{Mimification and unmimification of mail messages.} + \deprecated{2.3}{The \refmodule{email} package should be used in + preference to the \module{mimify} module. This + module is present only to maintain backward + compatibility.} ! The \module{mimify} module defines two functions to convert mail messages to and from MIME format. The mail message can be either a simple message or a so-called multipart message. Each part is treated separately. From rhettinger@users.sourceforge.net Sun Oct 6 03:38:48 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 19:38:48 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib librfc822.tex,1.38.14.2,1.38.14.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv7786 Modified Files: Tag: release22-maint librfc822.tex Log Message: Backport 1.42 documenting impending deprecation in favor of the email module. Index: librfc822.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/librfc822.tex,v retrieving revision 1.38.14.2 retrieving revision 1.38.14.3 diff -C2 -d -r1.38.14.2 -r1.38.14.3 *** librfc822.tex 6 Aug 2002 21:22:59 -0000 1.38.14.2 --- librfc822.tex 6 Oct 2002 02:38:46 -0000 1.38.14.3 *************** *** 5,8 **** --- 5,13 ---- \modulesynopsis{Parse \rfc{2822} style mail messages.} + \deprecated{2.3}{The \refmodule{email} package should be used in + preference to the \module{rfc822} module. This + module is present only to maintain backward + compatibility.} + This module defines a class, \class{Message}, which represents an ``email message'' as defined by the Internet standard From rhettinger@users.sourceforge.net Sun Oct 6 04:10:28 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 20:10:28 -0700 Subject: [Python-checkins] python/dist/src/Lib webbrowser.py,1.26.6.1,1.26.6.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv18606 Modified Files: Tag: release22-maint webbrowser.py Log Message: Backport 1.28 and 1.29: SF #515026, delete global variable that was apparently used only in a for loop. Index: webbrowser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/webbrowser.py,v retrieving revision 1.26.6.1 retrieving revision 1.26.6.2 diff -C2 -d -r1.26.6.1 -r1.26.6.2 *** webbrowser.py 7 Jan 2002 15:29:33 -0000 1.26.6.1 --- webbrowser.py 6 Oct 2002 03:10:26 -0000 1.26.6.2 *************** *** 323,326 **** --- 323,328 ---- register(cmd.lower(), None, GenericBrowser( "%s '%%s'" % cmd.lower())) + cmd = None # to make del work if _tryorder was empty + del cmd _tryorder = filter(lambda x: _browsers.has_key(x.lower()) From rhettinger@users.sourceforge.net Sun Oct 6 04:13:32 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 20:13:32 -0700 Subject: [Python-checkins] python/dist/src/Lib user.py,1.5,1.5.28.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv19830 Modified Files: Tag: release22-maint user.py Log Message: Backport 1.7: SF # 555779, import user doesn't work with CGIs Index: user.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/user.py,v retrieving revision 1.5 retrieving revision 1.5.28.1 diff -C2 -d -r1.5 -r1.5.28.1 *** user.py 30 Mar 2000 15:00:33 -0000 1.5 --- user.py 6 Oct 2002 03:13:29 -0000 1.5.28.1 *************** *** 27,30 **** --- 27,32 ---- if os.environ.has_key('HOME'): home = os.environ['HOME'] + elif os.name == 'posix': + home = os.path.expanduser("~/") elif os.name == 'nt': # Contributed by Jeff Bauer if os.environ.has_key('HOMEPATH'): From rhettinger@users.sourceforge.net Sun Oct 6 04:18:36 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 20:18:36 -0700 Subject: [Python-checkins] python/dist/src/Lib warnings.py,1.9.14.1,1.9.14.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv20810 Modified Files: Tag: release22-maint warnings.py Log Message: Backport 1.17: Ignore IOError exceptions when writing the message. Index: warnings.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/warnings.py,v retrieving revision 1.9.14.1 retrieving revision 1.9.14.2 diff -C2 -d -r1.9.14.1 -r1.9.14.2 *** warnings.py 18 Apr 2002 04:52:10 -0000 1.9.14.1 --- warnings.py 6 Oct 2002 03:18:34 -0000 1.9.14.2 *************** *** 99,103 **** if file is None: file = sys.stderr ! file.write(formatwarning(message, category, filename, lineno)) def formatwarning(message, category, filename, lineno): --- 99,106 ---- if file is None: file = sys.stderr ! try: ! file.write(formatwarning(message, category, filename, lineno)) ! except IOError: ! pass # the file (probably stderr) is invalid - this warning gets lost. def formatwarning(message, category, filename, lineno): From rhettinger@users.sourceforge.net Sun Oct 6 04:24:31 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 20:24:31 -0700 Subject: [Python-checkins] python/dist/src/Lib urllib.py,1.135.6.4,1.135.6.5 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv21959 Modified Files: Tag: release22-maint urllib.py Log Message: Backport 1.151 and 1.152: Treat file://localhost/ as local too (same as file:/ and file:///). Fixes #607789, bugfix candidate. Index: urllib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/urllib.py,v retrieving revision 1.135.6.4 retrieving revision 1.135.6.5 diff -C2 -d -r1.135.6.4 -r1.135.6.5 *** urllib.py 18 Aug 2002 20:10:08 -0000 1.135.6.4 --- urllib.py 6 Oct 2002 03:24:29 -0000 1.135.6.5 *************** *** 400,404 **** def open_file(self, url): """Use local file or FTP depending on form of URL.""" ! if url[:2] == '//' and url[2:3] != '/': return self.open_ftp(url) else: --- 400,404 ---- def open_file(self, url): """Use local file or FTP depending on form of URL.""" ! if url[:2] == '//' and url[2:3] != '/' and url[2:12].lower() != 'localhost/': return self.open_ftp(url) else: From rhettinger@users.sourceforge.net Sun Oct 6 04:37:02 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 20:37:02 -0700 Subject: [Python-checkins] python/dist/src/Lib smtplib.py,1.46.4.3,1.46.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv24395 Modified Files: Tag: release22-maint smtplib.py Log Message: Backport 1.60 and 1.62: Patch #586999: Fix multiline string in sendmail example. smptlib did not handle empty addresses. The problem was that it expected rfc822.parseaddr() to return None upon a parse failure. The actual, documented return value for a parse failure is (None, None). Closes SF bug 602029. Index: smtplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/smtplib.py,v retrieving revision 1.46.4.3 retrieving revision 1.46.4.4 diff -C2 -d -r1.46.4.3 -r1.46.4.4 *** smtplib.py 2 Jun 2002 12:32:04 -0000 1.46.4.3 --- smtplib.py 6 Oct 2002 03:37:00 -0000 1.46.4.4 *************** *** 167,178 **** Should be able to handle anything rfc822.parseaddr can handle. """ ! m=None try: m=rfc822.parseaddr(addr)[1] except AttributeError: pass ! if not m: #something weird here.. punt -ddm ! return addr else: return "<%s>" % m --- 167,178 ---- Should be able to handle anything rfc822.parseaddr can handle. """ ! m = (None, None) try: m=rfc822.parseaddr(addr)[1] except AttributeError: pass ! if m == (None, None): # Indicates parse failure or AttributeError #something weird here.. punt -ddm ! return "<%s>" % addr else: return "<%s>" % m *************** *** 605,609 **** >>> s=smtplib.SMTP("localhost") >>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"] ! >>> msg = ''' ... From: Me@my.org ... Subject: testin'... --- 605,609 ---- >>> s=smtplib.SMTP("localhost") >>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"] ! >>> msg = '''\\ ... From: Me@my.org ... Subject: testin'... From rhettinger@users.sourceforge.net Sun Oct 6 04:45:42 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 20:45:42 -0700 Subject: [Python-checkins] python/dist/src/Lib smtpd.py,1.11,1.11.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv26305 Modified Files: Tag: release22-maint smtpd.py Log Message: Backport 1.12 and 1.13 and normalize whitespace (remove formfeeds): SF #515021, print the refused list to the DEBUGSTREAM, so the parameter is used Note: There is a TBD (aka FIXME) for how best to handle the refused addresses. smtp_RCPT(): Removed a somewhat embarrassing debugging line, found by Scot Stevenson. Could be a bug fix candidate, but probably doesn't matter much unless a certain blue-nosed cat suddenly becomes corporeal and starts emailing some stmp.py (sic) fronted mailer. Index: smtpd.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/smtpd.py,v retrieving revision 1.11 retrieving revision 1.11.8.1 diff -C2 -d -r1.11 -r1.11.8.1 *** smtpd.py 4 Nov 2001 03:04:25 -0000 1.11 --- smtpd.py 6 Oct 2002 03:45:40 -0000 1.11.8.1 *************** *** 36,40 **** """ ! # Overview: # --- 36,40 ---- """ ! # Overview: # *************** *** 97,101 **** ! def usage(code, msg=''): print >> sys.stderr, __doc__ % globals() --- 97,101 ---- ! def usage(code, msg=''): print >> sys.stderr, __doc__ % globals() *************** *** 105,109 **** ! class SMTPChannel(asynchat.async_chat): COMMAND = 0 --- 105,109 ---- ! class SMTPChannel(asynchat.async_chat): COMMAND = 0 *************** *** 242,248 **** self.push('501 Syntax: RCPT TO:
') return - if address.lower().startswith('stimpy'): - self.push('503 You suck %s' % address) - return self.__rcpttos.append(address) print >> DEBUGSTREAM, 'recips:', self.__rcpttos --- 242,245 ---- *************** *** 272,276 **** ! class SMTPServer(asyncore.dispatcher): def __init__(self, localaddr, remoteaddr): --- 269,273 ---- ! class SMTPServer(asyncore.dispatcher): def __init__(self, localaddr, remoteaddr): *************** *** 319,323 **** ! class DebuggingServer(SMTPServer): # Do something with the gathered message --- 316,320 ---- ! class DebuggingServer(SMTPServer): # Do something with the gathered message *************** *** 335,339 **** ! class PureProxy(SMTPServer): def process_message(self, peer, mailfrom, rcpttos, data): --- 332,336 ---- ! class PureProxy(SMTPServer): def process_message(self, peer, mailfrom, rcpttos, data): *************** *** 349,353 **** refused = self._deliver(mailfrom, rcpttos, data) # TBD: what to do with refused addresses? ! print >> DEBUGSTREAM, 'we got some refusals' def _deliver(self, mailfrom, rcpttos, data): --- 346,350 ---- refused = self._deliver(mailfrom, rcpttos, data) # TBD: what to do with refused addresses? ! print >> DEBUGSTREAM, 'we got some refusals:', refused def _deliver(self, mailfrom, rcpttos, data): *************** *** 376,380 **** ! class MailmanProxy(PureProxy): def process_message(self, peer, mailfrom, rcpttos, data): --- 373,377 ---- ! class MailmanProxy(PureProxy): def process_message(self, peer, mailfrom, rcpttos, data): *************** *** 418,422 **** refused = self._deliver(mailfrom, rcpttos, data) # TBD: what to do with refused addresses? ! print >> DEBUGSTREAM, 'we got refusals' # Now deliver directly to the list commands mlists = {} --- 415,419 ---- refused = self._deliver(mailfrom, rcpttos, data) # TBD: what to do with refused addresses? ! print >> DEBUGSTREAM, 'we got refusals:', refused # Now deliver directly to the list commands mlists = {} *************** *** 455,459 **** ! class Options: setuid = 1 --- 452,456 ---- ! class Options: setuid = 1 *************** *** 461,465 **** ! def parseargs(): global DEBUGSTREAM --- 458,462 ---- ! def parseargs(): global DEBUGSTREAM *************** *** 518,522 **** ! if __name__ == '__main__': options = parseargs() --- 515,519 ---- ! if __name__ == '__main__': options = parseargs() From rhettinger@users.sourceforge.net Sun Oct 6 04:52:46 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 20:52:46 -0700 Subject: [Python-checkins] python/dist/src/Lib site.py,1.39,1.39.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv28071 Modified Files: Tag: release22-maint site.py Log Message: Backport 1.45: Fix a problem in site.py which triggers in case sys.path is empty. Bugfix candidate for 2.2.2. Index: site.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/site.py,v retrieving revision 1.39 retrieving revision 1.39.4.1 diff -C2 -d -r1.39 -r1.39.4.1 *** site.py 17 Dec 2001 16:07:06 -0000 1.39 --- site.py 6 Oct 2002 03:52:44 -0000 1.39.4.1 *************** *** 93,97 **** # Append ./build/lib. in case we're running in the build dir # (especially for Guido :-) ! if os.name == "posix" and os.path.basename(sys.path[-1]) == "Modules": from distutils.util import get_platform s = "build/lib.%s-%.3s" % (get_platform(), sys.version) --- 93,98 ---- # Append ./build/lib. in case we're running in the build dir # (especially for Guido :-) ! if (os.name == "posix" and sys.path and ! os.path.basename(sys.path[-1]) == "Modules"): from distutils.util import get_platform s = "build/lib.%s-%.3s" % (get_platform(), sys.version) From tim_one@users.sourceforge.net Sun Oct 6 05:04:48 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sat, 05 Oct 2002 21:04:48 -0700 Subject: [Python-checkins] python/dist/src LICENSE,1.22,1.23 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv30935/python Modified Files: LICENSE Log Message: Update info for impending 2.2.2. Index: LICENSE =================================================================== RCS file: /cvsroot/python/python/dist/src/LICENSE,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** LICENSE 11 Apr 2002 20:54:35 -0000 1.22 --- LICENSE 6 Oct 2002 04:04:45 -0000 1.23 *************** *** 41,44 **** --- 41,45 ---- 2.1.3 2.1.2 2002 PSF yes 2.2.1 2.2 2002 PSF yes + 2.2.2 2.2.1 2002 PSF yes Footnotes: From tim_one@users.sourceforge.net Sun Oct 6 05:04:48 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sat, 05 Oct 2002 21:04:48 -0700 Subject: [Python-checkins] python/dist/src/PCbuild BUILDno.txt,1.38,1.39 Message-ID: Update of /cvsroot/python/python/dist/src/PCbuild In directory usw-pr-cvs1:/tmp/cvs-serv30935/python/PCbuild Modified Files: BUILDno.txt Log Message: Update info for impending 2.2.2. Index: BUILDno.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/BUILDno.txt,v retrieving revision 1.38 retrieving revision 1.39 diff -C2 -d -r1.38 -r1.39 *** BUILDno.txt 9 Apr 2002 21:18:37 -0000 1.38 --- BUILDno.txt 6 Oct 2002 04:04:46 -0000 1.39 *************** *** 34,37 **** --- 34,39 ---- Windows Python BUILD numbers ---------------------------- + 36 2.2.2b1 + 7-Oct-2002 35 2.1.3 (final) 8-Apr-2002 From tim_one@users.sourceforge.net Sun Oct 6 05:14:19 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sat, 05 Oct 2002 21:14:19 -0700 Subject: [Python-checkins] python/dist/src LICENSE,1.18.16.5,1.18.16.6 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv32616/22 Modified Files: Tag: release22-maint LICENSE Log Message: Assorted changes needed to release 2.2.2b1. Index: LICENSE =================================================================== RCS file: /cvsroot/python/python/dist/src/LICENSE,v retrieving revision 1.18.16.5 retrieving revision 1.18.16.6 diff -C2 -d -r1.18.16.5 -r1.18.16.6 *** LICENSE 26 Jul 2002 15:41:59 -0000 1.18.16.5 --- LICENSE 6 Oct 2002 04:14:17 -0000 1.18.16.6 *************** *** 41,44 **** --- 41,45 ---- 2.1.3 2.1.2 2002 PSF yes 2.2.1 2.2 2002 PSF yes + 2.2.2 2.2.1 2002 PSF yes Footnotes: *************** *** 57,66 **** =============================================================== ! PSF LICENSE AGREEMENT FOR PYTHON 2.2.1 -------------------------------------- 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and ! otherwise using Python 2.2.1 software in source or binary form and its associated documentation. --- 58,67 ---- =============================================================== ! PSF LICENSE AGREEMENT FOR PYTHON 2.2.2 -------------------------------------- 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and ! otherwise using Python 2.2.2 software in source or binary form and its associated documentation. *************** *** 68,94 **** hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, ! prepare derivative works, distribute, and otherwise use Python 2.2.1 alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002 Python Software Foundation; All Rights Reserved" are ! retained in Python 2.2.1 alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on ! or incorporates Python 2.2.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of ! the changes made to Python 2.2.1. ! 4. PSF is making Python 2.2.1 available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS ! FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.2.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON ! 2.2.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS ! A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.2.1, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. --- 69,95 ---- hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, ! prepare derivative works, distribute, and otherwise use Python 2.2.2 alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002 Python Software Foundation; All Rights Reserved" are ! retained in Python 2.2.2 alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on ! or incorporates Python 2.2.2 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of ! the changes made to Python 2.2.2. ! 4. PSF is making Python 2.2.2 available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS ! FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.2.2 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON ! 2.2.2 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS ! A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.2.2, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. *************** *** 102,106 **** products or services of Licensee, or any third party. ! 8. By copying, installing or otherwise using Python 2.2.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. --- 103,107 ---- products or services of Licensee, or any third party. ! 8. By copying, installing or otherwise using Python 2.2.2, Licensee agrees to be bound by the terms and conditions of this License Agreement. From tim_one@users.sourceforge.net Sun Oct 6 05:14:20 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sat, 05 Oct 2002 21:14:20 -0700 Subject: [Python-checkins] python/dist/src/Include patchlevel.h,2.60.2.1.2.6,2.60.2.1.2.7 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv32616/22/Include Modified Files: Tag: release22-maint patchlevel.h Log Message: Assorted changes needed to release 2.2.2b1. Index: patchlevel.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/patchlevel.h,v retrieving revision 2.60.2.1.2.6 retrieving revision 2.60.2.1.2.7 diff -C2 -d -r2.60.2.1.2.6 -r2.60.2.1.2.7 *** patchlevel.h 24 Sep 2002 17:14:19 -0000 2.60.2.1.2.6 --- patchlevel.h 6 Oct 2002 04:14:17 -0000 2.60.2.1.2.7 *************** *** 23,31 **** #define PY_MINOR_VERSION 2 #define PY_MICRO_VERSION 2 ! #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA ! #define PY_RELEASE_SERIAL 0 /* Version as a string */ ! #define PY_VERSION "2.2.2a0" /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. --- 23,31 ---- #define PY_MINOR_VERSION 2 #define PY_MICRO_VERSION 2 ! #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA ! #define PY_RELEASE_SERIAL 1 /* Version as a string */ ! #define PY_VERSION "2.2.2b1" /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. From tim_one@users.sourceforge.net Sun Oct 6 05:14:20 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sat, 05 Oct 2002 21:14:20 -0700 Subject: [Python-checkins] python/dist/src/PCbuild BUILDno.txt,1.26.4.7,1.26.4.8 python20.wse,1.98.4.7,1.98.4.8 pythoncore.dsp,1.30.4.3,1.30.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/PCbuild In directory usw-pr-cvs1:/tmp/cvs-serv32616/22/PCbuild Modified Files: Tag: release22-maint BUILDno.txt python20.wse pythoncore.dsp Log Message: Assorted changes needed to release 2.2.2b1. Index: BUILDno.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/BUILDno.txt,v retrieving revision 1.26.4.7 retrieving revision 1.26.4.8 diff -C2 -d -r1.26.4.7 -r1.26.4.8 *** BUILDno.txt 9 Apr 2002 21:19:53 -0000 1.26.4.7 --- BUILDno.txt 6 Oct 2002 04:14:18 -0000 1.26.4.8 *************** *** 34,37 **** --- 34,39 ---- Windows Python BUILD numbers ---------------------------- + 36 2.2.2b1 + 7-Oct-2002 34 2.2.1 (final) 10-Apr-2002 Index: python20.wse =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/python20.wse,v retrieving revision 1.98.4.7 retrieving revision 1.98.4.8 diff -C2 -d -r1.98.4.7 -r1.98.4.8 *** python20.wse 24 Sep 2002 17:17:38 -0000 1.98.4.7 --- python20.wse 6 Oct 2002 04:14:18 -0000 1.98.4.8 *************** *** 2,6 **** item: Global Version=8.14 ! Title=Python 2.2.2a0 Flags=00010100 Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --- 2,6 ---- item: Global Version=8.14 ! Title=Python 2.2.2b1 Flags=00010100 Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 *************** *** 19,25 **** Patch Threshold=85 Patch Memory=4000 ! EXE Filename=Python-2.2.2a0.exe Dialogs Version=8 ! Version File=2.2.2a0 Version Description=Python Programming Language Version Copyright=2002 Python Software Foundation --- 19,25 ---- Patch Threshold=85 Patch Memory=4000 ! EXE Filename=Python-2.2.2b1.exe Dialogs Version=8 ! Version File=2.2.2b1 Version Description=Python Programming Language Version Copyright=2002 Python Software Foundation *************** *** 65,69 **** item: Set Variable Variable=PYVER_STRING ! Value=2.2.2a0 end item: Remark --- 65,69 ---- item: Set Variable Variable=PYVER_STRING ! Value=2.2.2b1 end item: Remark Index: pythoncore.dsp =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/pythoncore.dsp,v retrieving revision 1.30.4.3 retrieving revision 1.30.4.4 diff -C2 -d -r1.30.4.3 -r1.30.4.4 *** pythoncore.dsp 4 Apr 2002 21:49:28 -0000 1.30.4.3 --- pythoncore.dsp 6 Oct 2002 04:14:18 -0000 1.30.4.4 *************** *** 740,748 **** !IF "$(CFG)" == "pythoncore - Win32 Release" ! # ADD CPP /D BUILD=34 !ELSEIF "$(CFG)" == "pythoncore - Win32 Debug" ! # ADD CPP /D BUILD=34 !ELSEIF "$(CFG)" == "pythoncore - Win32 Alpha Debug" --- 740,748 ---- !IF "$(CFG)" == "pythoncore - Win32 Release" ! # ADD CPP /D BUILD=36 !ELSEIF "$(CFG)" == "pythoncore - Win32 Debug" ! # ADD CPP /D BUILD=36 !ELSEIF "$(CFG)" == "pythoncore - Win32 Alpha Debug" From rhettinger@users.sourceforge.net Sun Oct 6 05:34:46 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 21:34:46 -0700 Subject: [Python-checkins] python/dist/src/Lib ntpath.py,1.44,1.44.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv4840 Modified Files: Tag: release22-maint ntpath.py Log Message: Backport 1.45: Allow abspath to still do something sensisble if the nt module can not be imported. Index: ntpath.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ntpath.py,v retrieving revision 1.44 retrieving revision 1.44.8.1 diff -C2 -d -r1.44 -r1.44.8.1 *** ntpath.py 5 Nov 2001 21:25:02 -0000 1.44 --- ntpath.py 6 Oct 2002 04:34:44 -0000 1.44.8.1 *************** *** 458,463 **** def abspath(path): """Return the absolute version of a path""" ! if path: # Empty path must return current working directory. from nt import _getfullpathname try: path = _getfullpathname(path) --- 458,473 ---- def abspath(path): """Return the absolute version of a path""" ! try: from nt import _getfullpathname + except ImportError: # Not running on Windows - mock up something sensible. + global abspath + def _abspath(path): + if not isabs(path): + path = join(os.getcwd(), path) + return normpath(path) + abspath = _abspath + return _abspath(path) + + if path: # Empty path must return current working directory. try: path = _getfullpathname(path) From rhettinger@users.sourceforge.net Sun Oct 6 06:43:49 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 05 Oct 2002 22:43:49 -0700 Subject: [Python-checkins] python/dist/src/Modules readline.c,2.41.6.2,2.41.6.3 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv17507 Modified Files: Tag: release22-maint readline.c Log Message: Backport 2.49: SF #558432: Prevent Annoying ' ' from readline (Holker Krekel). readline in all python versions is configured to append a 'space' character for a successful completion. But for almost all python expressions 'space' is not wanted (see coding conventions PEP 8). For example if you have a function 'longfunction' and you type 'longf' you get 'longfunction ' as a completion. note the unwanted space at the end. The patch fixes this behaviour by setting readline's append_character to '\0' which means don't append anything. This doesn't work with readline < 2.1 (AFAIK nowadays readline2.2 is in good use). An alternative approach would be to make the append_character accessable from python so that modules like the rlcompleter.py can set it to '\0'. [Ed.: I think expecting readline >= 2.2 is fine. If a completer wants another character they can append that to the keyword in the list.] Index: readline.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/readline.c,v retrieving revision 2.41.6.2 retrieving revision 2.41.6.3 diff -C2 -d -r2.41.6.2 -r2.41.6.3 *** readline.c 24 Sep 2002 01:17:41 -0000 2.41.6.2 --- readline.c 6 Oct 2002 05:43:47 -0000 2.41.6.3 *************** *** 521,524 **** --- 521,525 ---- strdup(" \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?"); /* All nonalphanums except '.' */ + rl_completion_append_character ='\0'; begidx = PyInt_FromLong(0L); From loewis@users.sourceforge.net Sun Oct 6 12:48:12 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 04:48:12 -0700 Subject: [Python-checkins] python/dist/src configure,1.340,1.341 configure.in,1.351,1.352 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv25615 Modified Files: configure configure.in Log Message: Also look in -lposix4 for sem_init. Fixes #618615. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.340 retrieving revision 1.341 diff -C2 -d -r1.340 -r1.341 *** configure 4 Oct 2002 10:21:59 -0000 1.340 --- configure 6 Oct 2002 11:48:08 -0000 1.341 *************** *** 1,4 **** #! /bin/sh ! # From configure.in Revision: 1.350 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. --- 1,4 ---- #! /bin/sh ! # From configure.in Revision: 1.351 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. *************** *** 9220,9231 **** fi # Dynamic linking for HP-UX ! ! echo "$as_me:$LINENO: checking for sem_init in -lrt" >&5 ! echo $ECHO_N "checking for sem_init in -lrt... $ECHO_C" >&6 ! if test "${ac_cv_lib_rt_sem_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ! ac_check_lib_save_LIBS=$LIBS ! LIBS="-lrt $LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" --- 9220,9230 ---- fi # Dynamic linking for HP-UX ! echo "$as_me:$LINENO: checking for library containing sem_init" >&5 ! echo $ECHO_N "checking for library containing sem_init... $ECHO_C" >&6 ! if test "${ac_cv_search_sem_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ! ac_func_search_save_LIBS=$LIBS ! ac_cv_search_sem_init=no cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" *************** *** 9265,9288 **** echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ! ac_cv_lib_rt_sem_init=yes else echo "$as_me: failed program was:" >&5 cat conftest.$ac_ext >&5 - ac_cv_lib_rt_sem_init=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext ! LIBS=$ac_check_lib_save_LIBS ! fi ! echo "$as_me:$LINENO: result: $ac_cv_lib_rt_sem_init" >&5 ! echo "${ECHO_T}$ac_cv_lib_rt_sem_init" >&6 ! if test $ac_cv_lib_rt_sem_init = yes; then ! cat >>confdefs.h <<_ACEOF ! #define HAVE_LIBRT 1 ! _ACEOF ! LIBS="-lrt $LIBS" fi ! # 'Real Time' functions on Solaris # checks for system dependent C++ extensions support --- 9264,9332 ---- echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ! ac_cv_search_sem_init="none required" else echo "$as_me: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext ! if test "$ac_cv_search_sem_init" = no; then ! for ac_lib in rt posix4; do ! LIBS="-l$ac_lib $ac_func_search_save_LIBS" ! cat >conftest.$ac_ext <<_ACEOF ! #line $LINENO "configure" ! #include "confdefs.h" ! /* Override any gcc2 internal prototype to avoid an error. */ ! #ifdef __cplusplus ! extern "C" ! #endif ! /* We use char because int might match the return type of a gcc2 ! builtin and then its argument prototype would still apply. */ ! char sem_init (); ! #ifdef F77_DUMMY_MAIN ! # ifdef __cplusplus ! extern "C" ! # endif ! int F77_DUMMY_MAIN() { return 1; } ! #endif ! int ! main () ! { ! sem_init (); ! ; ! return 0; ! } ! _ACEOF ! rm -f conftest.$ac_objext conftest$ac_exeext ! if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ! (eval $ac_link) 2>&5 ! ac_status=$? ! echo "$as_me:$LINENO: \$? = $ac_status" >&5 ! (exit $ac_status); } && ! { ac_try='test -s conftest$ac_exeext' ! { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ! (eval $ac_try) 2>&5 ! ac_status=$? ! echo "$as_me:$LINENO: \$? = $ac_status" >&5 ! (exit $ac_status); }; }; then ! ac_cv_search_sem_init="-l$ac_lib" ! break ! else ! echo "$as_me: failed program was:" >&5 ! cat conftest.$ac_ext >&5 ! fi ! rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext ! done ! fi ! LIBS=$ac_func_search_save_LIBS ! fi ! echo "$as_me:$LINENO: result: $ac_cv_search_sem_init" >&5 ! echo "${ECHO_T}$ac_cv_search_sem_init" >&6 ! if test "$ac_cv_search_sem_init" != no; then ! test "$ac_cv_search_sem_init" = "none required" || LIBS="$ac_cv_search_sem_init $LIBS" fi ! # 'Real Time' functions on Solaris, ! # posix4 on Solaris 2.6 # checks for system dependent C++ extensions support Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.351 retrieving revision 1.352 diff -C2 -d -r1.351 -r1.352 *** configure.in 4 Oct 2002 10:22:02 -0000 1.351 --- configure.in 6 Oct 2002 11:48:09 -0000 1.352 *************** *** 1094,1098 **** AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX ! AC_CHECK_LIB(rt, sem_init) # 'Real Time' functions on Solaris # checks for system dependent C++ extensions support --- 1094,1099 ---- AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX ! AC_SEARCH_LIBS(sem_init, rt posix4) # 'Real Time' functions on Solaris, ! # posix4 on Solaris 2.6 # checks for system dependent C++ extensions support From gvanrossum@users.sourceforge.net Sun Oct 6 15:37:13 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Sun, 06 Oct 2002 07:37:13 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_email.py,1.42,1.43 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv3232 Modified Files: test_email.py Log Message: Make sure the email test suite can be run both stand-alone and under supervision of regrtest.py. Will backport to 2.2.2. Index: test_email.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_email.py,v retrieving revision 1.42 retrieving revision 1.43 diff -C2 -d -r1.42 -r1.43 *** test_email.py 19 Jul 2002 22:44:12 -0000 1.42 --- test_email.py 6 Oct 2002 14:37:11 -0000 1.43 *************** *** 5,11 **** # The specific tests now live in Lib/email/test from email.test.test_email import suite - if __name__ == '__main__': ! unittest.main(defaultTest='suite') --- 5,13 ---- # The specific tests now live in Lib/email/test from email.test.test_email import suite + from test.test_support import run_suite + def test_main(): + run_suite(suite()) if __name__ == '__main__': ! test_main() From gvanrossum@users.sourceforge.net Sun Oct 6 15:38:02 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Sun, 06 Oct 2002 07:38:02 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_email.py,1.24.4.3,1.24.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv3453 Modified Files: Tag: release22-maint test_email.py Log Message: Backport: Make sure the email test suite can be run both stand-alone and under supervision of regrtest.py. Index: test_email.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_email.py,v retrieving revision 1.24.4.3 retrieving revision 1.24.4.4 diff -C2 -d -r1.24.4.3 -r1.24.4.4 *** test_email.py 4 Oct 2002 17:24:24 -0000 1.24.4.3 --- test_email.py 6 Oct 2002 14:38:00 -0000 1.24.4.4 *************** *** 5,11 **** # The specific tests now live in Lib/email/test from email.test.test_email import suite - if __name__ == '__main__': ! unittest.main(defaultTest='suite') --- 5,13 ---- # The specific tests now live in Lib/email/test from email.test.test_email import suite + from test.test_support import run_suite + def test_main(): + run_suite(suite()) if __name__ == '__main__': ! test_main() From loewis@users.sourceforge.net Sun Oct 6 18:51:13 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 10:51:13 -0700 Subject: [Python-checkins] python/dist/src/Lib smtplib.py,1.46.4.4,1.46.4.5 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv507 Modified Files: Tag: release22-maint smtplib.py Log Message: Patch #572031: AUTH method LOGIN for smtplib. Index: smtplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/smtplib.py,v retrieving revision 1.46.4.4 retrieving revision 1.46.4.5 diff -C2 -d -r1.46.4.4 -r1.46.4.5 *** smtplib.py 6 Oct 2002 03:37:00 -0000 1.46.4.4 --- smtplib.py 6 Oct 2002 17:51:10 -0000 1.46.4.5 *************** *** 57,60 **** --- 57,65 ---- CRLF="\r\n" + OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) + + def encode_base64(s, eol=None): + return "".join(base64.encodestring(s).split("\n")) + # Exception classes used by this module. class SMTPException(Exception): *************** *** 392,400 **** del resp[0] for each in resp: m=re.match(r'(?P[A-Za-z0-9][A-Za-z0-9\-]*)',each) if m: feature=m.group("feature").lower() params=m.string[m.end("feature"):].strip() ! self.esmtp_features[feature]=params return (code,msg) --- 397,426 ---- del resp[0] for each in resp: + # To be able to communicate with as many SMTP servers as possible, + # we have to take the old-style auth advertisement into account, + # because: + # 1) Else our SMTP feature parser gets confused. + # 2) There are some servers that only advertise the auth methods we + # support using the old style. + auth_match = OLDSTYLE_AUTH.match(each) + if auth_match: + # This doesn't remove duplicates, but that's no problem + self.esmtp_features["auth"] = self.esmtp_features.get("auth", "") \ + + " " + auth_match.groups(0)[0] + continue + + # RFC 1869 requires a space between ehlo keyword and parameters. + # It's actually stricter, in that only spaces are allowed between + # parameters, but were not going to check for that here. Note + # that the space isn't present if there are no parameters. m=re.match(r'(?P[A-Za-z0-9][A-Za-z0-9\-]*)',each) if m: feature=m.group("feature").lower() params=m.string[m.end("feature"):].strip() ! if feature == "auth": ! self.esmtp_features[feature] = self.esmtp_features.get(feature, "") \ ! + " " + params ! else: ! self.esmtp_features[feature]=params return (code,msg) *************** *** 495,506 **** challenge = base64.decodestring(challenge) response = user + " " + hmac.HMAC(password, challenge).hexdigest() ! return base64.encodestring(response)[:-1] def encode_plain(user, password): ! return base64.encodestring("%s\0%s\0%s" % ! (user, user, password))[:-1] AUTH_PLAIN = "PLAIN" AUTH_CRAM_MD5 = "CRAM-MD5" if self.helo_resp is None and self.ehlo_resp is None: --- 521,533 ---- challenge = base64.decodestring(challenge) response = user + " " + hmac.HMAC(password, challenge).hexdigest() ! return encode_base64(response, eol="") def encode_plain(user, password): ! return encode_base64("%s\0%s\0%s" % (user, user, password), eol="") ! AUTH_PLAIN = "PLAIN" AUTH_CRAM_MD5 = "CRAM-MD5" + AUTH_LOGIN = "LOGIN" if self.helo_resp is None and self.ehlo_resp is None: *************** *** 519,524 **** # less preferred methods. Except for the purpose of testing the weaker # ones, we prefer stronger methods like CRAM-MD5: ! preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN] ! #preferred_auths = [AUTH_PLAIN, AUTH_CRAM_MD5] # Determine the authentication method we'll use --- 546,550 ---- # less preferred methods. Except for the purpose of testing the weaker # ones, we prefer stronger methods like CRAM-MD5: ! preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN, AUTH_LOGIN] # Determine the authentication method we'll use *************** *** 528,532 **** authmethod = method break - if self.debuglevel > 0: print "AuthMethod:", authmethod if authmethod == AUTH_CRAM_MD5: --- 554,557 ---- *************** *** 539,542 **** --- 564,573 ---- (code, resp) = self.docmd("AUTH", AUTH_PLAIN + " " + encode_plain(user, password)) + elif authmethod == AUTH_LOGIN: + (code, resp) = self.docmd("AUTH", + "%s %s" % (AUTH_LOGIN, encode_base64(user, eol=""))) + if code != 334: + raise SMTPAuthenticationError(code, resp) + (code, resp) = self.docmd(encode_base64(password, eol="")) elif authmethod == None: raise SMTPException("No suitable authentication method found.") From loewis@users.sourceforge.net Sun Oct 6 18:55:11 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 10:55:11 -0700 Subject: [Python-checkins] python/dist/src/Lib smtplib.py,1.62,1.63 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv1851 Modified Files: smtplib.py Log Message: Patch #572031: AUTH method LOGIN for smtplib (most of the patch hides in rev. 1.59). Backported to 2.2. Index: smtplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/smtplib.py,v retrieving revision 1.62 retrieving revision 1.63 diff -C2 -d -r1.62 -r1.63 *** smtplib.py 5 Sep 2002 01:14:07 -0000 1.62 --- smtplib.py 6 Oct 2002 17:55:08 -0000 1.63 *************** *** 575,579 **** if code != 334: raise SMTPAuthenticationError(code, resp) ! (code, resp) = self.docmd(encode_base64(user, eol="")) elif authmethod is None: raise SMTPException("No suitable authentication method found.") --- 575,579 ---- if code != 334: raise SMTPAuthenticationError(code, resp) ! (code, resp) = self.docmd(encode_base64(password, eol="")) elif authmethod is None: raise SMTPException("No suitable authentication method found.") From gvanrossum@users.sourceforge.net Sun Oct 6 21:15:00 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Sun, 06 Oct 2002 13:15:00 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_email.py,1.24.4.4,1.24.4.5 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv1079 Modified Files: Tag: release22-maint test_email.py Log Message: Aargh! The 2.3 version of this file requires "from test.test_support import run_suite", but the 2.2.2 version requires "from test_support import run_suite" ... :-( Index: test_email.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_email.py,v retrieving revision 1.24.4.4 retrieving revision 1.24.4.5 diff -C2 -d -r1.24.4.4 -r1.24.4.5 *** test_email.py 6 Oct 2002 14:38:00 -0000 1.24.4.4 --- test_email.py 6 Oct 2002 20:14:58 -0000 1.24.4.5 *************** *** 5,9 **** # The specific tests now live in Lib/email/test from email.test.test_email import suite ! from test.test_support import run_suite def test_main(): --- 5,9 ---- # The specific tests now live in Lib/email/test from email.test.test_email import suite ! from test_support import run_suite def test_main(): From gvanrossum@users.sourceforge.net Sun Oct 6 21:36:33 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Sun, 06 Oct 2002 13:36:33 -0700 Subject: [Python-checkins] python/dist/src/Lib/test regrtest.py,1.98,1.99 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv7538 Modified Files: regrtest.py Log Message: Add test_pep277 to the expected skips on Linux. (This test seems to be skipped everywhere except on Windows NT and descendants, but I'm only going to add it to the skip list for the platform I can test.) Index: regrtest.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/regrtest.py,v retrieving revision 1.98 retrieving revision 1.99 diff -C2 -d -r1.98 -r1.99 *** regrtest.py 30 Sep 2002 16:19:48 -0000 1.98 --- regrtest.py 6 Oct 2002 20:36:31 -0000 1.99 *************** *** 544,547 **** --- 544,548 ---- test_nis test_ntpath + test_pep277 test_socket_ssl test_socketserver From rhettinger@users.sourceforge.net Sun Oct 6 23:11:15 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sun, 06 Oct 2002 15:11:15 -0700 Subject: [Python-checkins] python/dist/src/Lib posixpath.py,1.46,1.46.10.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv11198 Modified Files: Tag: release22-maint posixpath.py Log Message: Backport 1.52: SF # 555779, import user doesn't work with CGIs Index: posixpath.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/posixpath.py,v retrieving revision 1.46 retrieving revision 1.46.10.1 diff -C2 -d -r1.46 -r1.46.10.1 *** posixpath.py 10 Oct 2001 04:16:20 -0000 1.46 --- posixpath.py 6 Oct 2002 22:11:13 -0000 1.46.10.1 *************** *** 307,312 **** if i == 1: if not os.environ.has_key('HOME'): ! return path ! userhome = os.environ['HOME'] else: import pwd --- 307,314 ---- if i == 1: if not os.environ.has_key('HOME'): ! import pwd ! userhome = pwd.getpwuid(os.getuid())[5] ! else: ! userhome = os.environ['HOME'] else: import pwd From rhettinger@users.sourceforge.net Sun Oct 6 23:37:43 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sun, 06 Oct 2002 15:37:43 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref7.tex,1.29.8.3,1.29.8.4 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv22393 Modified Files: Tag: release22-maint ref7.tex Log Message: Backport 1.33: Update programmer's note on nested functions. Index: ref7.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref7.tex,v retrieving revision 1.29.8.3 retrieving revision 1.29.8.4 diff -C2 -d -r1.29.8.3 -r1.29.8.4 *** ref7.tex 15 Mar 2002 23:18:05 -0000 1.29.8.3 --- ref7.tex 6 Oct 2002 22:37:40 -0000 1.29.8.4 *************** *** 390,398 **** \indexii{lambda}{form} ! \strong{Programmer's note:} a ``\code{def}'' form executed inside a ! function definition defines a local function that can be returned or ! passed around. The semantics of name resolution in the nested ! function will change in Python 2.2. See the appendix for a ! description of the new semantics. --- 390,398 ---- \indexii{lambda}{form} ! \strong{Programmer's note:} Functions are first-class objects. A ! ``\code{def}'' form executed inside a function definition defines a ! local function that can be returned or passed around. Free variables ! used in the nested function can access the local variables of the ! function containing the def. See section \ref{naming} for details. From rhettinger@users.sourceforge.net Sun Oct 6 23:47:14 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sun, 06 Oct 2002 15:47:14 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref7.tex,1.29.8.4,1.29.8.5 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv26637 Modified Files: Tag: release22-maint ref7.tex Log Message: Backport 1.34: Changing section reference. Index: ref7.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref7.tex,v retrieving revision 1.29.8.4 retrieving revision 1.29.8.5 diff -C2 -d -r1.29.8.4 -r1.29.8.5 *** ref7.tex 6 Oct 2002 22:37:40 -0000 1.29.8.4 --- ref7.tex 6 Oct 2002 22:47:12 -0000 1.29.8.5 *************** *** 417,421 **** inheritance list, if present. Each item in the inheritance list should evaluate to a class object. The class's suite is then executed ! in a new execution frame (see section \ref{execframes}), using a newly created local namespace and the original global namespace. (Usually, the suite contains only function definitions.) When the --- 417,421 ---- inheritance list, if present. Each item in the inheritance list should evaluate to a class object. The class's suite is then executed ! in a new execution frame (see section \ref{naming}), using a newly created local namespace and the original global namespace. (Usually, the suite contains only function definitions.) When the From tim_one@users.sourceforge.net Mon Oct 7 01:59:04 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 06 Oct 2002 17:59:04 -0700 Subject: [Python-checkins] python/dist/src/PCbuild python20.wse,1.98.4.8,1.98.4.9 Message-ID: Update of /cvsroot/python/python/dist/src/PCbuild In directory usw-pr-cvs1:/tmp/cvs-serv17639/22/PCbuild Modified Files: Tag: release22-maint python20.wse Log Message: They don't work yet, but the installer at least needs to install the email pkg's distinct test suite. Index: python20.wse =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/python20.wse,v retrieving revision 1.98.4.8 retrieving revision 1.98.4.9 diff -C2 -d -r1.98.4.8 -r1.98.4.9 *** python20.wse 6 Oct 2002 04:14:18 -0000 1.98.4.8 --- python20.wse 7 Oct 2002 00:59:01 -0000 1.98.4.9 *************** *** 1912,1915 **** --- 1912,1933 ---- Flags=0000000000000010 end + item: Install File + Source=..\lib\email\test\*.py + Destination=%MAINDIR%\Lib\email\test + Description=email tests + Flags=0000000000000010 + end + item: Install File + Source=..\lib\email\test\data\*.txt + Destination=%MAINDIR%\Lib\email\test\data + Description=email test data + Flags=0000000000000010 + end + item: Install File + Source=..\lib\email\test\data\*.gif + Destination=%MAINDIR%\Lib\email\test\data + Description=email test data + Flags=0000000000000010 + end item: Remark end From tim_one@users.sourceforge.net Mon Oct 7 02:18:19 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 06 Oct 2002 18:18:19 -0700 Subject: [Python-checkins] python/dist/src/Lib/test pickletester.py,1.12.4.2,1.12.4.3 test_StringIO.py,1.10.6.2,1.10.6.3 test_cfgparser.py,1.9.10.3,1.9.10.4 test_generators.py,1.30.6.1,1.30.6.2 test_httplib.py,1.2.12.2,1.2.12.3 test_multifile.py,1.1.2.1,1.1.2.2 test_netrc.py,1.1.2.1,1.1.2.2 test_string.py,1.15.6.1,1.15.6.2 test_trace.py,1.4.2.1,1.4.2.2 test_urlparse.py,1.2.24.2,1.2.24.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv25501/Lib/test Modified Files: Tag: release22-maint pickletester.py test_StringIO.py test_cfgparser.py test_generators.py test_httplib.py test_multifile.py test_netrc.py test_string.py test_trace.py test_urlparse.py Log Message: Whitespace normalization. Index: pickletester.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/pickletester.py,v retrieving revision 1.12.4.2 retrieving revision 1.12.4.3 diff -C2 -d -r1.12.4.2 -r1.12.4.3 *** pickletester.py 7 Mar 2002 10:12:38 -0000 1.12.4.2 --- pickletester.py 7 Oct 2002 01:18:17 -0000 1.12.4.3 *************** *** 254,258 **** s = self.dumps(t) u = self.loads(s) ! self.assertEqual(t, u) import os if hasattr(os, "stat"): --- 254,258 ---- s = self.dumps(t) u = self.loads(s) ! self.assertEqual(t, u) import os if hasattr(os, "stat"): Index: test_StringIO.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_StringIO.py,v retrieving revision 1.10.6.2 retrieving revision 1.10.6.3 diff -C2 -d -r1.10.6.2 -r1.10.6.3 *** test_StringIO.py 18 Mar 2002 13:31:31 -0000 1.10.6.2 --- test_StringIO.py 7 Oct 2002 01:18:17 -0000 1.10.6.3 *************** *** 78,82 **** # snippets to larger Unicode strings. This is tested by this # method. Note that cStringIO does not support this extension. ! f = self.MODULE.StringIO() f.write(self._line[:6]) --- 78,82 ---- # snippets to larger Unicode strings. This is tested by this # method. Note that cStringIO does not support this extension. ! f = self.MODULE.StringIO() f.write(self._line[:6]) Index: test_cfgparser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_cfgparser.py,v retrieving revision 1.9.10.3 retrieving revision 1.9.10.4 diff -C2 -d -r1.9.10.3 -r1.9.10.4 *** test_cfgparser.py 27 Sep 2002 16:34:30 -0000 1.9.10.3 --- test_cfgparser.py 7 Oct 2002 01:18:17 -0000 1.9.10.4 *************** *** 71,75 **** likes it. """) ! def case_sensitivity(): print "Testing case sensitivity..." --- 71,75 ---- likes it. """) ! def case_sensitivity(): print "Testing case sensitivity..." Index: test_generators.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_generators.py,v retrieving revision 1.30.6.1 retrieving revision 1.30.6.2 diff -C2 -d -r1.30.6.1 -r1.30.6.2 *** test_generators.py 12 Jun 2002 03:48:46 -0000 1.30.6.1 --- test_generators.py 7 Oct 2002 01:18:17 -0000 1.30.6.2 *************** *** 817,821 **** ... finally: ... yield i ! ... >>> g = f() >>> print g.next() --- 817,821 ---- ... finally: ... yield i ! ... >>> g = f() >>> print g.next() Index: test_httplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_httplib.py,v retrieving revision 1.2.12.2 retrieving revision 1.2.12.3 diff -C2 -d -r1.2.12.2 -r1.2.12.3 *** test_httplib.py 12 Jul 2002 14:23:43 -0000 1.2.12.2 --- test_httplib.py 7 Oct 2002 01:18:17 -0000 1.2.12.3 *************** *** 57,59 **** if cookies != hdr: raise AssertionError, "multiple headers not combined properly" - --- 57,58 ---- Index: test_multifile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_multifile.py,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -C2 -d -r1.1.2.1 -r1.1.2.2 *** test_multifile.py 22 Sep 2002 09:03:03 -0000 1.1.2.1 --- test_multifile.py 7 Oct 2002 01:18:17 -0000 1.1.2.2 *************** *** 5,14 **** msg = """Mime-Version: 1.0 Content-Type: multipart/mixed; ! boundary="=====================_590453667==_" X-OriginalArrivalTime: 05 Feb 2002 03:43:23.0310 (UTC) FILETIME=[42D88CE0:01C1ADF7] --=====================_590453667==_ Content-Type: multipart/alternative; ! boundary="=====================_590453677==_.ALT" --=====================_590453677==_.ALT --- 5,14 ---- msg = """Mime-Version: 1.0 Content-Type: multipart/mixed; ! boundary="=====================_590453667==_" X-OriginalArrivalTime: 05 Feb 2002 03:43:23.0310 (UTC) FILETIME=[42D88CE0:01C1ADF7] --=====================_590453667==_ Content-Type: multipart/alternative; ! boundary="=====================_590453677==_.ALT" --=====================_590453677==_.ALT *************** *** 50,55 **** mf.push(boundary) ! while mf.next(): ! getMIMEMsg(mf) mf.pop() else: --- 50,55 ---- mf.push(boundary) ! while mf.next(): ! getMIMEMsg(mf) mf.pop() else: Index: test_netrc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_netrc.py,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -C2 -d -r1.1.2.1 -r1.1.2.2 *** test_netrc.py 25 Mar 2002 13:23:53 -0000 1.1.2.1 --- test_netrc.py 7 Oct 2002 01:18:17 -0000 1.1.2.2 *************** *** 13,17 **** line4 ! default login log2 password pass2 """ --- 13,17 ---- line4 ! default login log2 password pass2 """ *************** *** 26,30 **** fp.close() self.netrc = netrc.netrc(temp_filename) ! def tearDown (self): del self.netrc --- 26,30 ---- fp.close() self.netrc = netrc.netrc(temp_filename) ! def tearDown (self): del self.netrc *************** *** 37,43 **** self.assert_(self.netrc.hosts['foo'] == ('log1', 'acct1', 'pass1')) self.assert_(self.netrc.hosts['default'] == ('log2', None, 'pass2')) ! ! if __name__ == "__main__": test_support.run_unittest(NetrcTestCase) - --- 37,42 ---- self.assert_(self.netrc.hosts['foo'] == ('log1', 'acct1', 'pass1')) self.assert_(self.netrc.hosts['default'] == ('log2', None, 'pass2')) ! ! if __name__ == "__main__": test_support.run_unittest(NetrcTestCase) Index: test_string.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_string.py,v retrieving revision 1.15.6.1 retrieving revision 1.15.6.2 diff -C2 -d -r1.15.6.1 -r1.15.6.2 *** test_string.py 22 Apr 2002 11:57:05 -0000 1.15.6.1 --- test_string.py 7 Oct 2002 01:18:17 -0000 1.15.6.2 *************** *** 39,43 **** if value is input: if verbose: ! print 'no' print '*',f, `input`, `output`, `value` return --- 39,43 ---- if value is input: if verbose: ! print 'no' print '*',f, `input`, `output`, `value` return Index: test_trace.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_trace.py,v retrieving revision 1.4.2.1 retrieving revision 1.4.2.2 diff -C2 -d -r1.4.2.1 -r1.4.2.2 *** test_trace.py 2 Oct 2002 13:13:46 -0000 1.4.2.1 --- test_trace.py 7 Oct 2002 01:18:17 -0000 1.4.2.2 *************** *** 120,124 **** def settrace_and_return(tracefunc): _settrace_and_return(tracefunc) ! settrace_and_return.events = [(1, 'return')] --- 120,124 ---- def settrace_and_return(tracefunc): _settrace_and_return(tracefunc) ! settrace_and_return.events = [(1, 'return')] *************** *** 132,136 **** except RuntimeError, exc: pass ! settrace_and_raise.events = [(2, 'exception'), (3, 'line'), --- 132,136 ---- except RuntimeError, exc: pass ! settrace_and_raise.events = [(2, 'exception'), (3, 'line'), *************** *** 147,151 **** class TraceTestCase(unittest.TestCase): def compare_events(self, line_offset, events, expected_events): ! events = [(l - line_offset, e) for (l, e) in events] if events != expected_events: self.fail( --- 147,151 ---- class TraceTestCase(unittest.TestCase): def compare_events(self, line_offset, events, expected_events): ! events = [(l - line_offset, e) for (l, e) in events] if events != expected_events: self.fail( *************** *** 153,158 **** "\n".join(difflib.ndiff(map(str, expected_events), map(str, events)))) ! ! def run_test(self, func): tracer = Tracer() --- 153,158 ---- "\n".join(difflib.ndiff(map(str, expected_events), map(str, events)))) ! ! def run_test(self, func): tracer = Tracer() *************** *** 169,173 **** self.compare_events(func.func_code.co_firstlineno, tracer.events, func.events) ! def test_1_basic(self): self.run_test(basic) --- 169,173 ---- self.compare_events(func.func_code.co_firstlineno, tracer.events, func.events) ! def test_1_basic(self): self.run_test(basic) *************** *** 207,211 **** except RuntimeError: self.fail("recursion counter not reset") ! def test_main(): --- 207,211 ---- except RuntimeError: self.fail("recursion counter not reset") ! def test_main(): Index: test_urlparse.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_urlparse.py,v retrieving revision 1.2.24.2 retrieving revision 1.2.24.3 diff -C2 -d -r1.2.24.2 -r1.2.24.3 *** test_urlparse.py 25 Sep 2002 19:22:10 -0000 1.2.24.2 --- test_urlparse.py 7 Oct 2002 01:18:17 -0000 1.2.24.3 *************** *** 13,18 **** (RFC1808_BASE, ('http', 'a', '/b/c/d', 'p', 'q', 'f')), ! ('file:///tmp/junk.txt', ! ('file', '', '/tmp/junk.txt', '', '', '')), ]: result = urlparse.urlparse(url) --- 13,18 ---- (RFC1808_BASE, ('http', 'a', '/b/c/d', 'p', 'q', 'f')), ! ('file:///tmp/junk.txt', ! ('file', '', '/tmp/junk.txt', '', '', '')), ]: result = urlparse.urlparse(url) From tim_one@users.sourceforge.net Mon Oct 7 02:18:19 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 06 Oct 2002 18:18:19 -0700 Subject: [Python-checkins] python/dist/src/Lib ConfigParser.py,1.38.10.6,1.38.10.7 StringIO.py,1.19.12.3,1.19.12.4 fileinput.py,1.8.8.1,1.8.8.2 httplib.py,1.42.10.8,1.42.10.9 smtplib.py,1.46.4.5,1.46.4.6 tabnanny.py,1.16.16.1,1.16.16.2 tokenize.py,1.28.14.1,1.28.14.2 urllib2.py,1.24.8.2,1.24.8.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv25501/Lib Modified Files: Tag: release22-maint ConfigParser.py StringIO.py fileinput.py httplib.py smtplib.py tabnanny.py tokenize.py urllib2.py Log Message: Whitespace normalization. Index: ConfigParser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ConfigParser.py,v retrieving revision 1.38.10.6 retrieving revision 1.38.10.7 diff -C2 -d -r1.38.10.6 -r1.38.10.7 *** ConfigParser.py 3 Oct 2002 15:27:47 -0000 1.38.10.6 --- ConfigParser.py 7 Oct 2002 01:18:17 -0000 1.38.10.7 *************** *** 283,287 **** # do the string interpolation value = rawval ! depth = MAX_INTERPOLATION_DEPTH while depth: # Loop through this until it's done depth -= 1 --- 283,287 ---- # do the string interpolation value = rawval ! depth = MAX_INTERPOLATION_DEPTH while depth: # Loop through this until it's done depth -= 1 Index: StringIO.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/StringIO.py,v retrieving revision 1.19.12.3 retrieving revision 1.19.12.4 diff -C2 -d -r1.19.12.3 -r1.19.12.4 *** StringIO.py 15 May 2002 03:50:31 -0000 1.19.12.3 --- StringIO.py 7 Oct 2002 01:18:17 -0000 1.19.12.4 *************** *** 38,51 **** class StringIO: ! """class StringIO([buffer]) ! When a StringIO object is created, it can be initialized to an existing string by passing the string to the constructor. If no string is given, ! the StringIO will start empty. The StringIO object can accept either Unicode or 8-bit strings, but mixing the two may take some care. If both are used, 8-bit strings that cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause ! a UnicodeError to be raised when getvalue() is called. """ def __init__(self, buf = ''): --- 38,51 ---- class StringIO: ! """class StringIO([buffer]) ! When a StringIO object is created, it can be initialized to an existing string by passing the string to the constructor. If no string is given, ! the StringIO will start empty. The StringIO object can accept either Unicode or 8-bit strings, but mixing the two may take some care. If both are used, 8-bit strings that cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause ! a UnicodeError to be raised when getvalue() is called. """ def __init__(self, buf = ''): *************** *** 186,190 **** strings that cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause a UnicodeError to be raised when getvalue() ! is called. """ if self.buflist: --- 186,190 ---- strings that cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause a UnicodeError to be raised when getvalue() ! is called. """ if self.buflist: Index: fileinput.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/fileinput.py,v retrieving revision 1.8.8.1 retrieving revision 1.8.8.2 diff -C2 -d -r1.8.8.1 -r1.8.8.2 *** fileinput.py 15 May 2002 03:50:31 -0000 1.8.8.1 --- fileinput.py 7 Oct 2002 01:18:17 -0000 1.8.8.2 *************** *** 95,99 **** as global state for the functions of this module, and is also returned to use during iteration. The parameters to this function will be passed ! along to the constructor of the FileInput class. """ global _state --- 95,99 ---- as global state for the functions of this module, and is also returned to use during iteration. The parameters to this function will be passed ! along to the constructor of the FileInput class. """ global _state *************** *** 119,123 **** Before the first line has been read, this function has no effect; it cannot be used to skip the first file. After the last line of the ! last file has been read, this function has no effect. """ if not _state: --- 119,123 ---- Before the first line has been read, this function has no effect; it cannot be used to skip the first file. After the last line of the ! last file has been read, this function has no effect. """ if not _state: *************** *** 128,132 **** """ Return the name of the file currently being read. ! Before the first line has been read, returns None. """ if not _state: --- 128,132 ---- """ Return the name of the file currently being read. ! Before the first line has been read, returns None. """ if not _state: *************** *** 138,142 **** Return the cumulative line number of the line that has just been read. Before the first line has been read, returns 0. After the last line ! of the last file has been read, returns the line number of that line. """ if not _state: --- 138,142 ---- Return the cumulative line number of the line that has just been read. Before the first line has been read, returns 0. After the last line ! of the last file has been read, returns the line number of that line. """ if not _state: *************** *** 148,152 **** Return the line number in the current file. Before the first line has been read, returns 0. After the last line of the last file has ! been read, returns the line number of that line within the file. """ if not _state: --- 148,152 ---- Return the line number in the current file. Before the first line has been read, returns 0. After the last line of the last file has ! been read, returns the line number of that line within the file. """ if not _state: *************** *** 157,161 **** """ Returns true the line just read is the first line of its file, ! otherwise returns false. """ if not _state: --- 157,161 ---- """ Returns true the line just read is the first line of its file, ! otherwise returns false. """ if not _state: *************** *** 166,170 **** """ Returns true if the last line was read from sys.stdin, ! otherwise returns false. """ if not _state: --- 166,170 ---- """ Returns true if the last line was read from sys.stdin, ! otherwise returns false. """ if not _state: *************** *** 174,178 **** class FileInput: """class FileInput([files[, inplace[, backup]]]) ! Class FileInput is the implementation of the module; its methods filename(), lineno(), fileline(), isfirstline(), isstdin(), nextfile() --- 174,178 ---- class FileInput: """class FileInput([files[, inplace[, backup]]]) ! Class FileInput is the implementation of the module; its methods filename(), lineno(), fileline(), isfirstline(), isstdin(), nextfile() *************** *** 181,185 **** input line, and a __getitem__() method which implements the sequence behavior. The sequence must be accessed in strictly ! sequential order; random access and readline() cannot be mixed. """ --- 181,185 ---- input line, and a __getitem__() method which implements the sequence behavior. The sequence must be accessed in strictly ! sequential order; random access and readline() cannot be mixed. """ Index: httplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/httplib.py,v retrieving revision 1.42.10.8 retrieving revision 1.42.10.9 diff -C2 -d -r1.42.10.8 -r1.42.10.9 *** httplib.py 25 Sep 2002 16:53:17 -0000 1.42.10.8 --- httplib.py 7 Oct 2002 01:18:17 -0000 1.42.10.9 *************** *** 372,376 **** if self.chunked: return self._read_chunked(amt) ! if amt is None: # unbounded read --- 372,376 ---- if self.chunked: return self._read_chunked(amt) ! if amt is None: # unbounded read *************** *** 442,446 **** return value ! def _safe_read(self, amt): """Read the number of bytes requested, compensating for partial reads. --- 442,446 ---- return value ! def _safe_read(self, amt): """Read the number of bytes requested, compensating for partial reads. Index: smtplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/smtplib.py,v retrieving revision 1.46.4.5 retrieving revision 1.46.4.6 diff -C2 -d -r1.46.4.5 -r1.46.4.6 *** smtplib.py 6 Oct 2002 17:51:10 -0000 1.46.4.5 --- smtplib.py 7 Oct 2002 01:18:17 -0000 1.46.4.6 *************** *** 409,413 **** + " " + auth_match.groups(0)[0] continue ! # RFC 1869 requires a space between ehlo keyword and parameters. # It's actually stricter, in that only spaces are allowed between --- 409,413 ---- + " " + auth_match.groups(0)[0] continue ! # RFC 1869 requires a space between ehlo keyword and parameters. # It's actually stricter, in that only spaces are allowed between *************** *** 525,529 **** def encode_plain(user, password): return encode_base64("%s\0%s\0%s" % (user, user, password), eol="") ! AUTH_PLAIN = "PLAIN" --- 525,529 ---- def encode_plain(user, password): return encode_base64("%s\0%s\0%s" % (user, user, password), eol="") ! AUTH_PLAIN = "PLAIN" Index: tabnanny.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tabnanny.py,v retrieving revision 1.16.16.1 retrieving revision 1.16.16.2 diff -C2 -d -r1.16.16.1 -r1.16.16.2 *** tabnanny.py 15 May 2002 03:50:31 -0000 1.16.16.1 --- tabnanny.py 7 Oct 2002 01:18:17 -0000 1.16.16.2 *************** *** 3,14 **** """The Tab Nanny despises ambiguous indentation. She knows no mercy. ! tabnanny -- Detection of ambiguous indentation For the time being this module is intended to be called as a script. However it is possible to import it into an IDE and use the function ! check() described below. Warning: The API provided by this module is likely to change in future ! releases; such changes may not be backward compatible. """ --- 3,14 ---- """The Tab Nanny despises ambiguous indentation. She knows no mercy. ! tabnanny -- Detection of ambiguous indentation For the time being this module is intended to be called as a script. However it is possible to import it into an IDE and use the function ! check() described below. Warning: The API provided by this module is likely to change in future ! releases; such changes may not be backward compatible. """ *************** *** 74,85 **** def check(file): """check(file_or_dir) ! If file_or_dir is a directory and not a symbolic link, then recursively descend the directory tree named by file_or_dir, checking all .py files along the way. If file_or_dir is an ordinary Python source file, it is checked for whitespace related problems. The diagnostic messages are ! written to standard output using the print statement. """ ! if os.path.isdir(file) and not os.path.islink(file): if verbose: --- 74,85 ---- def check(file): """check(file_or_dir) ! If file_or_dir is a directory and not a symbolic link, then recursively descend the directory tree named by file_or_dir, checking all .py files along the way. If file_or_dir is an ordinary Python source file, it is checked for whitespace related problems. The diagnostic messages are ! written to standard output using the print statement. """ ! if os.path.isdir(file) and not os.path.islink(file): if verbose: Index: tokenize.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tokenize.py,v retrieving revision 1.28.14.1 retrieving revision 1.28.14.2 diff -C2 -d -r1.28.14.1 -r1.28.14.2 *** tokenize.py 15 May 2002 03:50:31 -0000 1.28.14.1 --- tokenize.py 7 Oct 2002 01:18:17 -0000 1.28.14.2 *************** *** 126,137 **** The tokenize() function accepts two parameters: one representing the input stream, and one providing an output mechanism for tokenize(). ! The first parameter, readline, must be a callable object which provides the same interface as the readline() method of built-in file objects. ! Each call to the function should return one line of input as a string. The second parameter, tokeneater, must also be a callable object. It is called once for each token, with five arguments, corresponding to the ! tuples generated by generate_tokens(). """ try: --- 126,137 ---- The tokenize() function accepts two parameters: one representing the input stream, and one providing an output mechanism for tokenize(). ! The first parameter, readline, must be a callable object which provides the same interface as the readline() method of built-in file objects. ! Each call to the function should return one line of input as a string. The second parameter, tokeneater, must also be a callable object. It is called once for each token, with five arguments, corresponding to the ! tuples generated by generate_tokens(). """ try: *************** *** 151,155 **** readline() method of built-in file objects. Each call to the function should return one line of input as a string. ! The generator produces 5-tuples with these members: the token type; the token string; a 2-tuple (srow, scol) of ints specifying the row and --- 151,155 ---- readline() method of built-in file objects. Each call to the function should return one line of input as a string. ! The generator produces 5-tuples with these members: the token type; the token string; a 2-tuple (srow, scol) of ints specifying the row and *************** *** 157,161 **** ints specifying the row and column where the token ends in the source; and the line on which the token was found. The line passed is the ! logical line; continuation lines are included. """ lnum = parenlev = continued = 0 --- 157,161 ---- ints specifying the row and column where the token ends in the source; and the line on which the token was found. The line passed is the ! logical line; continuation lines are included. """ lnum = parenlev = continued = 0 Index: urllib2.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/urllib2.py,v retrieving revision 1.24.8.2 retrieving revision 1.24.8.3 diff -C2 -d -r1.24.8.2 -r1.24.8.3 *** urllib2.py 25 Sep 2002 10:32:49 -0000 1.24.8.2 --- urllib2.py 7 Oct 2002 01:18:17 -0000 1.24.8.3 *************** *** 459,463 **** if ':' in user_pass: user, password = user_pass.split(':', 1) ! user_pass = base64.encodestring('%s:%s' % (unquote(user), unquote(password))) req.add_header('Proxy-Authorization', 'Basic ' + user_pass) --- 459,463 ---- if ':' in user_pass: user, password = user_pass.split(':', 1) ! user_pass = base64.encodestring('%s:%s' % (unquote(user), unquote(password))) req.add_header('Proxy-Authorization', 'Basic ' + user_pass) From tim_one@users.sourceforge.net Mon Oct 7 02:20:54 2002 From: tim_one@users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 06 Oct 2002 18:20:54 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_trace.py,1.4.2.2,1.4.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv26753/Lib/test Modified Files: Tag: release22-maint test_trace.py Log Message: This has no hope of working under -O. Skip it then instead of failing. Index: test_trace.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_trace.py,v retrieving revision 1.4.2.2 retrieving revision 1.4.2.3 diff -C2 -d -r1.4.2.2 -r1.4.2.3 *** test_trace.py 7 Oct 2002 01:18:17 -0000 1.4.2.2 --- test_trace.py 7 Oct 2002 01:20:52 -0000 1.4.2.3 *************** *** 6,9 **** --- 6,12 ---- import difflib + if not __debug__: + raise test_support.TestSkipped, "tracing not supported under -O" + # A very basic example. If this fails, we're in deep trouble. def basic(): From rhettinger@users.sourceforge.net Mon Oct 7 03:33:58 2002 From: rhettinger@users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sun, 06 Oct 2002 19:33:58 -0700 Subject: [Python-checkins] python/dist/src/Parser myreadline.c,2.26,2.26.24.1 Message-ID: Update of /cvsroot/python/python/dist/src/Parser In directory usw-pr-cvs1:/tmp/cvs-serv24304 Modified Files: Tag: release22-maint myreadline.c Log Message: Backport 2.27: Fix bug 439992 - [win32] KeyboardInterrupt Not Caught. This gets us closer to consistent Ctrl+C behaviour on NT and Win9x. NT now reliably generates KeyboardInterrupt exceptions for NT when a file IO operation was aborted. Bugfix candidate Index: myreadline.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Parser/myreadline.c,v retrieving revision 2.26 retrieving revision 2.26.24.1 diff -C2 -d -r2.26 -r2.26.24.1 *** myreadline.c 2 Mar 2001 06:29:51 -0000 2.26 --- myreadline.c 7 Oct 2002 02:33:56 -0000 2.26.24.1 *************** *** 11,14 **** --- 11,18 ---- #include "Python.h" + #ifdef MS_WINDOWS + #define WIN32_LEAN_AND_MEAN + #include "windows.h" + #endif /* MS_WINDOWS */ int (*PyOS_InputHook)(void) = NULL; *************** *** 32,35 **** --- 36,68 ---- if (p != NULL) return 0; /* No error */ + #ifdef MS_WINDOWS + /* In the case of a Ctrl+C or some other external event + interrupting the operation: + Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32 + error code (and feof() returns TRUE). + Win9x: Ctrl+C seems to have no effect on fgets() returning + early - the signal handler is called, but the fgets() + only returns "normally" (ie, when Enter hit or feof()) + */ + if (GetLastError()==ERROR_OPERATION_ABORTED) { + /* Signals come asynchronously, so we sleep a brief + moment before checking if the handler has been + triggered (we cant just return 1 before the + signal handler has been called, as the later + signal may be treated as a separate interrupt). + */ + Sleep(1); + if (PyOS_InterruptOccurred()) { + return 1; /* Interrupt */ + } + /* Either the sleep wasn't long enough (need a + short loop retrying?) or not interrupted at all + (in which case we should revisit the whole thing!) + Logging some warning would be nice. assert is not + viable as under the debugger, the various dialogs + mean the condition is not true. + */ + } + #endif /* MS_WINDOWS */ if (feof(fp)) { return -1; /* EOF */ From loewis@users.sourceforge.net Mon Oct 7 06:53:32 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 22:53:32 -0700 Subject: [Python-checkins] python/dist/src/Misc/RPM python-2.2.spec,1.1.2.2,1.1.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Misc/RPM In directory usw-pr-cvs1:/tmp/cvs-serv11355 Modified Files: Tag: release22-maint python-2.2.spec Log Message: Patch #619352: Update for 2.2.2b1. Install python2 and python2.2. Add Makefile.pre.in to -devel. Index: python-2.2.spec =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/RPM/python-2.2.spec,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -C2 -d -r1.1.2.2 -r1.1.2.3 *** python-2.2.spec 9 Apr 2002 09:29:28 -0000 1.1.2.2 --- python-2.2.spec 7 Oct 2002 05:53:29 -0000 1.1.2.3 *************** *** 5,28 **** # Is the resulting package and the installed binary named "python" or # "python2"? ! #WARNING: Commenting out doesn't work. Last line is what's used. ! %define config_binsuffix none ! %define config_binsuffix 2 # Build tkinter? "auto" enables it if /usr/bin/wish exists. ! #WARNING: Commenting out doesn't work. Last line is what's used. ! %define config_tkinter no ! %define config_tkinter yes %define config_tkinter auto # Use pymalloc? The last line (commented or not) determines wether # pymalloc is used. ! #WARNING: Commenting out doesn't work. Last line is what's used. ! %define config_pymalloc yes %define config_pymalloc no # Enable IPV6? ! #WARNING: Commenting out doesn't work. Last line is what's used. ! %define config_ipv6 yes ! %define config_ipv6 no ################################# --- 5,23 ---- # Is the resulting package and the installed binary named "python" or # "python2"? ! # Valid values: [none/2/2.2] ! %define config_binsuffix 2.2.2b1 # Build tkinter? "auto" enables it if /usr/bin/wish exists. ! # Valid values: [no/yes/auto] %define config_tkinter auto # Use pymalloc? The last line (commented or not) determines wether # pymalloc is used. ! # Valid values: [no/yes] %define config_pymalloc no # Enable IPV6? ! # Valid values: [no/yes/auto] ! %define config_ipv6 auto ################################# *************** *** 31,35 **** %define name python ! %define version 2.2.1 %define release 1 %define __prefix /usr --- 26,30 ---- %define name python ! %define version 2.2.2b1 %define release 1 %define __prefix /usr *************** *** 37,41 **** # kludge to get around rpm define weirdness ! %define ipv6 %(if [ "%{config_ipv6}" = yes ]; then echo --enable-ipv6; else echo --disable-ipv6; fi) %define pymalloc %(if [ "%{config_pymalloc}" = yes ]; then echo --with-pymalloc; else echo --without-pymalloc; fi) %define binsuffix %(if [ "%{config_binsuffix}" = none ]; then echo ; else echo "%{config_binsuffix}"; fi) --- 32,36 ---- # kludge to get around rpm define weirdness ! %define ipv6 %(if [ "%{config_ipv6}" = yes ]; then echo --enable-ipv6; else if [ "%{config_ipv6}" == auto ]; then echo; else echo --disable-ipv6; fi; fi) %define pymalloc %(if [ "%{config_pymalloc}" = yes ]; then echo --with-pymalloc; else echo --without-pymalloc; fi) %define binsuffix %(if [ "%{config_binsuffix}" = none ]; then echo ; else echo "%{config_binsuffix}"; fi) *************** *** 128,132 **** %changelog ! * Tue Mar 26 2002 Sean Reifschneider [Release 2.2.1c2-1] - Updated to 2.2.1c2. --- 123,139 ---- %changelog ! * Sun Oct 06 2002 Sean Reifschneider ! [Release 2.2.2b1-1] ! - Updated for the 2.2.2b1 release. ! - Changing ipv6 settings to include "auto" which will let configure ! figure it out. (suggested by Martin v. Loewis) ! - Changing the settable flags at the top of this file. ! (suggested by Martin v. Loewis) ! ! [Release 2.2.1-2] ! - Enabled IPV6 by default. (Suggested by Pekka Pessi) ! - Set up to install python2 and python2.2 when using the suffix. ! - Added Makefile.pre.in to -devel. ! [Release 2.2.1c2-1] - Updated to 2.2.1c2. *************** *** 219,222 **** --- 226,232 ---- make prefix=$RPM_BUILD_ROOT%{__prefix} install + # copy over Makefile.pre.in + cp Makefile.pre.in Makefile.pre $RPM_BUILD_ROOT%{__prefix}/lib/python%{libvers}/config/ + # REPLACE PATH IN PYDOC if [ ! -z "%{binsuffix}" ] *************** *** 235,239 **** if [ ! -z "%{binsuffix}" ] then ! ( cd $RPM_BUILD_ROOT%{__prefix}/bin; rm -f python[0-9a-zA-Z]*; mv -f python python"%{binsuffix}" ) ( cd $RPM_BUILD_ROOT%{__prefix}/man/man1; mv python.1 python%{binsuffix}.1 ) --- 245,250 ---- if [ ! -z "%{binsuffix}" ] then ! ( cd $RPM_BUILD_ROOT%{__prefix}/bin; ! rm -f python"%{binsuffix}"; mv -f python python"%{binsuffix}" ) ( cd $RPM_BUILD_ROOT%{__prefix}/man/man1; mv python.1 python%{binsuffix}.1 ) From loewis@users.sourceforge.net Mon Oct 7 06:56:44 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 22:56:44 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils/command bdist_rpm.py,1.27.6.1,1.27.6.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/distutils/command In directory usw-pr-cvs1:/tmp/cvs-serv13168 Modified Files: Tag: release22-maint bdist_rpm.py Log Message: Patch #619493: Prefer rpmbuild over rpm if available. Index: bdist_rpm.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/distutils/command/bdist_rpm.py,v retrieving revision 1.27.6.1 retrieving revision 1.27.6.2 diff -C2 -d -r1.27.6.1 -r1.27.6.2 *** bdist_rpm.py 25 Mar 2002 13:13:45 -0000 1.27.6.1 --- bdist_rpm.py 7 Oct 2002 05:56:42 -0000 1.27.6.2 *************** *** 281,284 **** --- 281,287 ---- self.announce('building RPMs') rpm_cmd = ['rpm'] + if os.path.exists('/usr/bin/rpmbuild') or \ + os.path.exists('/bin/rpmbuild'): + rpm_cmd = ['rpmbuild'] if self.source_only: # what kind of RPMs? rpm_cmd.append('-bs') From loewis@users.sourceforge.net Mon Oct 7 06:57:23 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 22:57:23 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils/command bdist_rpm.py,1.31,1.32 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/distutils/command In directory usw-pr-cvs1:/tmp/cvs-serv13493 Modified Files: bdist_rpm.py Log Message: Patch #619493: Prefer rpmbuild over rpm if available. Backported to 2.2. Index: bdist_rpm.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/distutils/command/bdist_rpm.py,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -d -r1.31 -r1.32 *** bdist_rpm.py 11 Sep 2002 16:31:52 -0000 1.31 --- bdist_rpm.py 7 Oct 2002 05:57:21 -0000 1.32 *************** *** 283,286 **** --- 283,289 ---- log.info("building RPMs") rpm_cmd = ['rpm'] + if os.path.exists('/usr/bin/rpmbuild') or \ + os.path.exists('/bin/rpmbuild'): + rpm_cmd = ['rpmbuild'] if self.source_only: # what kind of RPMs? rpm_cmd.append('-bs') From loewis@users.sourceforge.net Mon Oct 7 07:21:09 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 23:21:09 -0700 Subject: [Python-checkins] python/dist/src configure.in,1.352,1.353 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv24905 Modified Files: configure.in Log Message: Fix quoting for Solaris LDSHARED. Will backport to 2.2. Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.352 retrieving revision 1.353 diff -C2 -d -r1.352 -r1.353 *** configure.in 6 Oct 2002 11:48:09 -0000 1.352 --- configure.in 7 Oct 2002 06:21:05 -0000 1.353 *************** *** 929,933 **** if test "$GCC" = "yes" then LDSHARED='$(CC) -shared' ! else LDSHARED="$(CC) -G"; fi ;; hp*|HP*) LDSHARED="ld -b";; --- 929,933 ---- if test "$GCC" = "yes" then LDSHARED='$(CC) -shared' ! else LDSHARED='$(CC) -G'; fi ;; hp*|HP*) LDSHARED="ld -b";; From loewis@users.sourceforge.net Mon Oct 7 07:21:46 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 23:21:46 -0700 Subject: [Python-checkins] python/dist/src configure,1.341,1.342 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv25139 Modified Files: configure Log Message: Fix quoting for Solaris LDSHARED. Will backport to 2.2. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.341 retrieving revision 1.342 diff -C2 -d -r1.341 -r1.342 *** configure 6 Oct 2002 11:48:08 -0000 1.341 --- configure 7 Oct 2002 06:21:41 -0000 1.342 *************** *** 1,4 **** #! /bin/sh ! # From configure.in Revision: 1.351 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. --- 1,4 ---- #! /bin/sh ! # From configure.in Revision: 1.352 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. *************** *** 8918,8922 **** if test "$GCC" = "yes" then LDSHARED='$(CC) -shared' ! else LDSHARED="$(CC) -G"; fi ;; hp*|HP*) LDSHARED="ld -b";; --- 8918,8922 ---- if test "$GCC" = "yes" then LDSHARED='$(CC) -shared' ! else LDSHARED='$(CC) -G'; fi ;; hp*|HP*) LDSHARED="ld -b";; From loewis@users.sourceforge.net Mon Oct 7 07:22:24 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 23:22:24 -0700 Subject: [Python-checkins] python/dist/src configure,1.279.6.13,1.279.6.14 configure.in,1.288.6.13,1.288.6.14 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv25339 Modified Files: Tag: release22-maint configure configure.in Log Message: Fix quoting for Solaris LDSHARED. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.279.6.13 retrieving revision 1.279.6.14 diff -C2 -d -r1.279.6.13 -r1.279.6.14 *** configure 4 Oct 2002 10:16:24 -0000 1.279.6.13 --- configure 7 Oct 2002 06:22:19 -0000 1.279.6.14 *************** *** 1,5 **** #! /bin/sh ! # From configure.in Revision: 1.288.6.12 # Guess values for system-dependent variables and create Makefiles. --- 1,5 ---- #! /bin/sh ! # From configure.in Revision: 1.288.6.13 # Guess values for system-dependent variables and create Makefiles. *************** *** 3187,3191 **** if test "$GCC" = "yes" then LDSHARED='$(CC) -shared' ! else LDSHARED="$(CC) -G"; fi ;; hp*|HP*) LDSHARED="ld -b";; --- 3187,3191 ---- if test "$GCC" = "yes" then LDSHARED='$(CC) -shared' ! else LDSHARED='$(CC) -G'; fi ;; hp*|HP*) LDSHARED="ld -b";; Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.288.6.13 retrieving revision 1.288.6.14 diff -C2 -d -r1.288.6.13 -r1.288.6.14 *** configure.in 4 Oct 2002 10:16:27 -0000 1.288.6.13 --- configure.in 7 Oct 2002 06:22:21 -0000 1.288.6.14 *************** *** 801,805 **** if test "$GCC" = "yes" then LDSHARED='$(CC) -shared' ! else LDSHARED="$(CC) -G"; fi ;; hp*|HP*) LDSHARED="ld -b";; --- 801,805 ---- if test "$GCC" = "yes" then LDSHARED='$(CC) -shared' ! else LDSHARED='$(CC) -G'; fi ;; hp*|HP*) LDSHARED="ld -b";; From loewis@users.sourceforge.net Mon Oct 7 07:44:24 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Sun, 06 Oct 2002 23:44:24 -0700 Subject: [Python-checkins] python/dist/src/Modules posixmodule.c,2.263,2.264 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv1042 Modified Files: posixmodule.c Log Message: Apply file system default encoding to exec and spawn path and arguments. Index: posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.263 retrieving revision 2.264 diff -C2 -d -r2.263 -r2.264 *** posixmodule.c 5 Oct 2002 01:47:34 -0000 2.263 --- posixmodule.c 7 Oct 2002 06:44:21 -0000 2.264 *************** *** 1853,1856 **** --- 1853,1867 ---- } + #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) + static void + free_string_array(char **array, int count) + { + int i; + for (i = 0; i < count; i++) + PyMem_Free(array[i]); + PyMem_DEL(array); + } + #endif + #ifdef HAVE_EXECV *************** *** 1874,1878 **** argv is a list or tuple of strings. */ ! if (!PyArg_ParseTuple(args, "sO:execv", &path, &argv)) return NULL; if (PyList_Check(argv)) { --- 1885,1891 ---- argv is a list or tuple of strings. */ ! if (!PyArg_ParseTuple(args, "etO:execv", ! Py_FileSystemDefaultEncoding, ! &path, &argv)) return NULL; if (PyList_Check(argv)) { *************** *** 1886,1889 **** --- 1899,1903 ---- else { PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list"); + PyMem_Free(path); return NULL; } *************** *** 1891,1905 **** if (argc == 0) { PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); return NULL; } argvlist = PyMem_NEW(char *, argc+1); ! if (argvlist == NULL) return NULL; for (i = 0; i < argc; i++) { ! if (!PyArg_Parse((*getitem)(argv, i), "s", &argvlist[i])) { ! PyMem_DEL(argvlist); PyErr_SetString(PyExc_TypeError, "execv() arg 2 must contain only strings"); return NULL; --- 1905,1925 ---- if (argc == 0) { PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); + PyMem_Free(path); return NULL; } argvlist = PyMem_NEW(char *, argc+1); ! if (argvlist == NULL) { ! PyMem_Free(path); return NULL; + } for (i = 0; i < argc; i++) { ! if (!PyArg_Parse((*getitem)(argv, i), "et", ! Py_FileSystemDefaultEncoding, ! &argvlist[i])) { ! free_string_array(argvlist, i); PyErr_SetString(PyExc_TypeError, "execv() arg 2 must contain only strings"); + PyMem_Free(path); return NULL; *************** *** 1916,1920 **** /* If we get here it's definitely an error */ ! PyMem_DEL(argvlist); return posix_error(); } --- 1936,1941 ---- /* If we get here it's definitely an error */ ! free_string_array(argvlist, argc); ! PyMem_Free(path); return posix_error(); } *************** *** 1939,1942 **** --- 1960,1964 ---- int i, pos, argc, envc; PyObject *(*getitem)(PyObject *, int); + int lastarg = 0; /* execve has three arguments: (path, argv, env), where *************** *** 1944,1948 **** like posix.environ. */ ! if (!PyArg_ParseTuple(args, "sOO:execve", &path, &argv, &env)) return NULL; if (PyList_Check(argv)) { --- 1966,1972 ---- like posix.environ. */ ! if (!PyArg_ParseTuple(args, "etOO:execve", ! Py_FileSystemDefaultEncoding, ! &path, &argv, &env)) return NULL; if (PyList_Check(argv)) { *************** *** 1956,1964 **** else { PyErr_SetString(PyExc_TypeError, "execve() arg 2 must be a tuple or list"); ! return NULL; } if (!PyMapping_Check(env)) { PyErr_SetString(PyExc_TypeError, "execve() arg 3 must be a mapping object"); ! return NULL; } --- 1980,1988 ---- else { PyErr_SetString(PyExc_TypeError, "execve() arg 2 must be a tuple or list"); ! goto fail_0; } if (!PyMapping_Check(env)) { PyErr_SetString(PyExc_TypeError, "execve() arg 3 must be a mapping object"); ! goto fail_0; } *************** *** 1966,1970 **** PyErr_SetString(PyExc_ValueError, "execve() arg 2 must not be empty"); ! return NULL; } --- 1990,1994 ---- PyErr_SetString(PyExc_ValueError, "execve() arg 2 must not be empty"); ! goto fail_0; } *************** *** 1972,1985 **** if (argvlist == NULL) { PyErr_NoMemory(); ! return NULL; } for (i = 0; i < argc; i++) { if (!PyArg_Parse((*getitem)(argv, i), ! "s;execve() arg 2 must contain only strings", &argvlist[i])) { goto fail_1; } } argvlist[argc] = NULL; --- 1996,2011 ---- if (argvlist == NULL) { PyErr_NoMemory(); ! goto fail_0; } for (i = 0; i < argc; i++) { if (!PyArg_Parse((*getitem)(argv, i), ! "et;execve() arg 2 must contain only strings", &argvlist[i])) { + lastarg = i; goto fail_1; } } + lastarg = argc; argvlist[argc] = NULL; *************** *** 2045,2051 **** PyMem_DEL(envlist); fail_1: ! PyMem_DEL(argvlist); Py_XDECREF(vals); Py_XDECREF(keys); return NULL; } --- 2071,2079 ---- PyMem_DEL(envlist); fail_1: ! free_string_array(argvlist,lastarg); Py_XDECREF(vals); Py_XDECREF(keys); + fail_0: + PyMem_Free(path); return NULL; } *************** *** 2075,2079 **** argv is a list or tuple of strings. */ ! if (!PyArg_ParseTuple(args, "isO:spawnv", &mode, &path, &argv)) return NULL; if (PyList_Check(argv)) { --- 2103,2109 ---- argv is a list or tuple of strings. */ ! if (!PyArg_ParseTuple(args, "ietO:spawnv", &mode, ! Py_FileSystemDefaultEncoding, ! &path, &argv)) return NULL; if (PyList_Check(argv)) { *************** *** 2087,2101 **** else { PyErr_SetString(PyExc_TypeError, "spawnv() arg 2 must be a tuple or list"); return NULL; } argvlist = PyMem_NEW(char *, argc+1); ! if (argvlist == NULL) return NULL; for (i = 0; i < argc; i++) { ! if (!PyArg_Parse((*getitem)(argv, i), "s", &argvlist[i])) { ! PyMem_DEL(argvlist); PyErr_SetString(PyExc_TypeError, "spawnv() arg 2 must contain only strings"); return NULL; } --- 2117,2137 ---- else { PyErr_SetString(PyExc_TypeError, "spawnv() arg 2 must be a tuple or list"); + PyMem_Free(path); return NULL; } argvlist = PyMem_NEW(char *, argc+1); ! if (argvlist == NULL) { ! PyMem_Free(path); return NULL; + } for (i = 0; i < argc; i++) { ! if (!PyArg_Parse((*getitem)(argv, i), "et", ! Py_FileSystemDefaultEncoding, ! &argvlist[i])) { ! free_string_array(argvlist, i); PyErr_SetString(PyExc_TypeError, "spawnv() arg 2 must contain only strings"); + PyMem_Free(path); return NULL; } *************** *** 2116,2120 **** #endif ! PyMem_DEL(argvlist); if (spawnval == -1) --- 2152,2157 ---- #endif ! free_string_array(argvlist, argc); ! PyMem_Free(path); if (spawnval == -1) *************** *** 2149,2152 **** --- 2186,2190 ---- Py_intptr_t spawnval; PyObject *(*getitem)(PyObject *, int); + int lastarg = 0; /* spawnve has four arguments: (mode, path, argv, env), where *************** *** 2154,2158 **** like posix.environ. */ ! if (!PyArg_ParseTuple(args, "isOO:spawnve", &mode, &path, &argv, &env)) return NULL; if (PyList_Check(argv)) { --- 2192,2198 ---- like posix.environ. */ ! if (!PyArg_ParseTuple(args, "ietOO:spawnve", &mode, ! Py_FileSystemDefaultEncoding, ! &path, &argv, &env)) return NULL; if (PyList_Check(argv)) { *************** *** 2166,2174 **** else { PyErr_SetString(PyExc_TypeError, "spawnve() arg 2 must be a tuple or list"); ! return NULL; } if (!PyMapping_Check(env)) { PyErr_SetString(PyExc_TypeError, "spawnve() arg 3 must be a mapping object"); ! return NULL; } --- 2206,2214 ---- else { PyErr_SetString(PyExc_TypeError, "spawnve() arg 2 must be a tuple or list"); ! goto fail_0; } if (!PyMapping_Check(env)) { PyErr_SetString(PyExc_TypeError, "spawnve() arg 3 must be a mapping object"); ! goto fail_0; } *************** *** 2176,2189 **** if (argvlist == NULL) { PyErr_NoMemory(); ! return NULL; } for (i = 0; i < argc; i++) { if (!PyArg_Parse((*getitem)(argv, i), ! "s;spawnve() arg 2 must contain only strings", &argvlist[i])) { goto fail_1; } } argvlist[argc] = NULL; --- 2216,2232 ---- if (argvlist == NULL) { PyErr_NoMemory(); ! goto fail_0; } for (i = 0; i < argc; i++) { if (!PyArg_Parse((*getitem)(argv, i), ! "et;spawnve() arg 2 must contain only strings", ! Py_FileSystemDefaultEncoding, &argvlist[i])) { + lastarg = i; goto fail_1; } } + lastarg = argc; argvlist[argc] = NULL; *************** *** 2252,2258 **** PyMem_DEL(envlist); fail_1: ! PyMem_DEL(argvlist); Py_XDECREF(vals); Py_XDECREF(keys); return res; } --- 2295,2303 ---- PyMem_DEL(envlist); fail_1: ! free_string_array(argvlist, lastarg); Py_XDECREF(vals); Py_XDECREF(keys); + fail_0: + PyMem_Free(path); return res; } From mwh@users.sourceforge.net Mon Oct 7 10:37:29 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 02:37:29 -0700 Subject: [Python-checkins] python/dist/src/Python ceval.c,2.301.4.5,2.301.4.6 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv10762 Modified Files: Tag: release22-maint ceval.c Log Message: This is Armin Rigo's patch: [ 617312 ] debugger-controlled jumps (Psyco #3) Forward port candidate, I guess. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.301.4.5 retrieving revision 2.301.4.6 diff -C2 -d -r2.301.4.5 -r2.301.4.6 *** ceval.c 2 Oct 2002 13:13:47 -0000 2.301.4.5 --- ceval.c 7 Oct 2002 09:37:26 -0000 2.301.4.6 *************** *** 586,597 **** tstate->frame = f; - co = f->f_code; - fastlocals = f->f_localsplus; - freevars = f->f_localsplus + f->f_nlocals; - _PyCode_GETCODEPTR(co, &first_instr); - next_instr = first_instr + f->f_lasti; - stack_pointer = f->f_stacktop; - assert(stack_pointer != NULL); - f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */ if (tstate->use_tracing) { --- 586,589 ---- *************** *** 632,635 **** --- 624,636 ---- } + co = f->f_code; + fastlocals = f->f_localsplus; + freevars = f->f_localsplus + f->f_nlocals; + _PyCode_GETCODEPTR(co, &first_instr); + next_instr = first_instr + f->f_lasti; + stack_pointer = f->f_stacktop; + assert(stack_pointer != NULL); + f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */ + #ifdef LLTRACE lltrace = PyDict_GetItemString(f->f_globals,"__lltrace__") != NULL; *************** *** 1973,1976 **** --- 1974,1978 ---- /* Trace each line of code reached */ f->f_lasti = INSTR_OFFSET(); + f->f_stacktop = stack_pointer; /* Inline call_trace() for performance: */ tstate->tracing++; *************** *** 1981,1984 **** --- 1983,1991 ---- || tstate->c_profilefunc); tstate->tracing--; + /* Reload possibly changed frame fields */ + JUMPTO(f->f_lasti); + stack_pointer = f->f_stacktop; + assert(stack_pointer != NULL); + f->f_stacktop = NULL; break; From mwh@users.sourceforge.net Mon Oct 7 10:40:22 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 02:40:22 -0700 Subject: [Python-checkins] python/dist/src/Include pystate.h,2.18,2.18.16.1 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv11757/Include Modified Files: Tag: release22-maint pystate.h Log Message: This is Armin Rigo's patch: [ 617311 ] Tiny profiling info (Psyco #2) Forward port candidate. Index: pystate.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pystate.h,v retrieving revision 2.18 retrieving revision 2.18.16.1 diff -C2 -d -r2.18 -r2.18.16.1 *** pystate.h 19 Jul 2001 12:19:11 -0000 2.18 --- pystate.h 7 Oct 2002 09:40:20 -0000 2.18.16.1 *************** *** 70,73 **** --- 70,75 ---- PyObject *dict; + int tick_counter; + /* XXX signal handlers should also be here */ From mwh@users.sourceforge.net Mon Oct 7 10:40:22 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 02:40:22 -0700 Subject: [Python-checkins] python/dist/src/Python ceval.c,2.301.4.6,2.301.4.7 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv11757/Python Modified Files: Tag: release22-maint ceval.c Log Message: This is Armin Rigo's patch: [ 617311 ] Tiny profiling info (Psyco #2) Forward port candidate. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.301.4.6 retrieving revision 2.301.4.7 diff -C2 -d -r2.301.4.6 -r2.301.4.7 *** ceval.c 7 Oct 2002 09:37:26 -0000 2.301.4.6 --- ceval.c 7 Oct 2002 09:40:20 -0000 2.301.4.7 *************** *** 658,661 **** --- 658,662 ---- if (things_to_do || --tstate->ticker < 0) { tstate->ticker = tstate->interp->checkinterval; + tstate->tick_counter++; if (things_to_do) { if (Py_MakePendingCalls() < 0) { From mwh@users.sourceforge.net Mon Oct 7 10:47:23 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 02:47:23 -0700 Subject: [Python-checkins] python/dist/src/Include pystate.h,2.18.16.1,2.18.16.2 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv14160/Include Modified Files: Tag: release22-maint pystate.h Log Message: This is Armin Rigo's patch: [ 617309 ] getframe hook (Psyco #1) Forward port candidate. Index: pystate.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pystate.h,v retrieving revision 2.18.16.1 retrieving revision 2.18.16.2 diff -C2 -d -r2.18.16.1 -r2.18.16.2 *** pystate.h 7 Oct 2002 09:40:20 -0000 2.18.16.1 --- pystate.h 7 Oct 2002 09:47:20 -0000 2.18.16.2 *************** *** 110,113 **** --- 110,116 ---- DL_IMPORT(PyThreadState *) PyThreadState_Next(PyThreadState *); + /* hook for PyEval_GetFrame(), requested for Psyco */ + extern DL_IMPORT(unaryfunc) _PyThreadState_GetFrame; + #ifdef __cplusplus } From mwh@users.sourceforge.net Mon Oct 7 10:47:23 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 02:47:23 -0700 Subject: [Python-checkins] python/dist/src/Python ceval.c,2.301.4.7,2.301.4.8 pystate.c,2.20,2.20.16.1 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv14160/Python Modified Files: Tag: release22-maint ceval.c pystate.c Log Message: This is Armin Rigo's patch: [ 617309 ] getframe hook (Psyco #1) Forward port candidate. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.301.4.7 retrieving revision 2.301.4.8 diff -C2 -d -r2.301.4.7 -r2.301.4.8 *** ceval.c 7 Oct 2002 09:40:20 -0000 2.301.4.7 --- ceval.c 7 Oct 2002 09:47:20 -0000 2.301.4.8 *************** *** 2950,2957 **** PyEval_GetBuiltins(void) { ! PyThreadState *tstate = PyThreadState_Get(); ! PyFrameObject *current_frame = tstate->frame; if (current_frame == NULL) ! return tstate->interp->builtins; else return current_frame->f_builtins; --- 2950,2956 ---- PyEval_GetBuiltins(void) { ! PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame(); if (current_frame == NULL) ! return PyThreadState_Get()->interp->builtins; else return current_frame->f_builtins; *************** *** 2961,2965 **** PyEval_GetLocals(void) { ! PyFrameObject *current_frame = PyThreadState_Get()->frame; if (current_frame == NULL) return NULL; --- 2960,2964 ---- PyEval_GetLocals(void) { ! PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame(); if (current_frame == NULL) return NULL; *************** *** 2971,2975 **** PyEval_GetGlobals(void) { ! PyFrameObject *current_frame = PyThreadState_Get()->frame; if (current_frame == NULL) return NULL; --- 2970,2974 ---- PyEval_GetGlobals(void) { ! PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame(); if (current_frame == NULL) return NULL; *************** *** 2981,2986 **** PyEval_GetFrame(void) { ! PyFrameObject *current_frame = PyThreadState_Get()->frame; ! return (PyObject *)current_frame; } --- 2980,2985 ---- PyEval_GetFrame(void) { ! PyThreadState *tstate = PyThreadState_Get(); ! return _PyThreadState_GetFrame((PyObject *)tstate); } *************** *** 2988,2992 **** PyEval_GetRestricted(void) { ! PyFrameObject *current_frame = PyThreadState_Get()->frame; return current_frame == NULL ? 0 : current_frame->f_restricted; } --- 2987,2991 ---- PyEval_GetRestricted(void) { ! PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame(); return current_frame == NULL ? 0 : current_frame->f_restricted; } *************** *** 2995,2999 **** PyEval_MergeCompilerFlags(PyCompilerFlags *cf) { ! PyFrameObject *current_frame = PyThreadState_Get()->frame; int result = 0; --- 2994,2998 ---- PyEval_MergeCompilerFlags(PyCompilerFlags *cf) { ! PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame(); int result = 0; Index: pystate.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/pystate.c,v retrieving revision 2.20 retrieving revision 2.20.16.1 diff -C2 -d -r2.20 -r2.20.16.1 *** pystate.c 19 Jul 2001 12:19:27 -0000 2.20 --- pystate.c 7 Oct 2002 09:47:21 -0000 2.20.16.1 *************** *** 36,39 **** --- 36,40 ---- PyThreadState *_PyThreadState_Current = NULL; + unaryfunc _PyThreadState_GetFrame = NULL; *************** *** 115,122 **** --- 116,132 ---- + /* Default implementation for _PyThreadState_GetFrame */ + static struct _frame * + threadstate_getframe(PyThreadState *self) + { + return self->frame; + } + PyThreadState * PyThreadState_New(PyInterpreterState *interp) { PyThreadState *tstate = PyMem_NEW(PyThreadState, 1); + if (_PyThreadState_GetFrame == NULL) + _PyThreadState_GetFrame = (unaryfunc)threadstate_getframe; if (tstate != NULL) { From mwh@users.sourceforge.net Mon Oct 7 10:47:23 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 02:47:23 -0700 Subject: [Python-checkins] python/dist/src/Modules pyexpat.c,2.57.6.3,2.57.6.4 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv14160/Modules Modified Files: Tag: release22-maint pyexpat.c Log Message: This is Armin Rigo's patch: [ 617309 ] getframe hook (Psyco #1) Forward port candidate. Index: pyexpat.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/pyexpat.c,v retrieving revision 2.57.6.3 retrieving revision 2.57.6.4 diff -C2 -d -r2.57.6.3 -r2.57.6.4 *** pyexpat.c 25 Sep 2002 22:31:35 -0000 2.57.6.3 --- pyexpat.c 7 Oct 2002 09:47:20 -0000 2.57.6.4 *************** *** 393,397 **** tstate, /*back*/ c, /*code*/ ! tstate->frame->f_globals, /*globals*/ NULL /*locals*/ ); --- 393,397 ---- tstate, /*back*/ c, /*code*/ ! PyEval_GetGlobals(), /*globals*/ NULL /*locals*/ ); From mwh@users.sourceforge.net Mon Oct 7 11:38:35 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 03:38:35 -0700 Subject: [Python-checkins] python/dist/src setup.py,1.73.4.9,1.73.4.10 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv2787 Modified Files: Tag: release22-maint setup.py Log Message: Backport fdrake's revision 1.88 of setup.py revision 1.46 of Lib/distutils/sysconfig.py When using a Python that has not been installed to build 3rd-party modules, distutils does not understand that the build version of the source tree is needed. This patch fixes distutils.sysconfig to understand that the running Python is part of the build tree and needs to use the appropriate "shape" of the tree. This does not assume anything about the current directory, so can be used to build 3rd-party modules using Python's build tree as well. This is useful since it allows us to use a non-installed debug-mode Python with 3rd-party modules for testing. It as the side-effect that set_python_build() is no longer needed (the hack which was added to allow distutils to be used to build the "standard" extension modules). This closes SF patch #547734. Index: setup.py =================================================================== RCS file: /cvsroot/python/python/dist/src/setup.py,v retrieving revision 1.73.4.9 retrieving revision 1.73.4.10 diff -C2 -d -r1.73.4.9 -r1.73.4.10 *** setup.py 30 Sep 2002 14:42:29 -0000 1.73.4.9 --- setup.py 7 Oct 2002 10:38:33 -0000 1.73.4.10 *************** *** 790,793 **** # --install-platlib if __name__ == '__main__': - sysconfig.set_python_build() main() --- 790,792 ---- From mwh@users.sourceforge.net Mon Oct 7 11:38:35 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 03:38:35 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils sysconfig.py,1.44,1.44.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/distutils In directory usw-pr-cvs1:/tmp/cvs-serv2787/Lib/distutils Modified Files: Tag: release22-maint sysconfig.py Log Message: Backport fdrake's revision 1.88 of setup.py revision 1.46 of Lib/distutils/sysconfig.py When using a Python that has not been installed to build 3rd-party modules, distutils does not understand that the build version of the source tree is needed. This patch fixes distutils.sysconfig to understand that the running Python is part of the build tree and needs to use the appropriate "shape" of the tree. This does not assume anything about the current directory, so can be used to build 3rd-party modules using Python's build tree as well. This is useful since it allows us to use a non-installed debug-mode Python with 3rd-party modules for testing. It as the side-effect that set_python_build() is no longer needed (the hack which was added to allow distutils to be used to build the "standard" extension modules). This closes SF patch #547734. Index: sysconfig.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/distutils/sysconfig.py,v retrieving revision 1.44 retrieving revision 1.44.6.1 diff -C2 -d -r1.44 -r1.44.6.1 *** sysconfig.py 6 Dec 2001 20:51:35 -0000 1.44 --- sysconfig.py 7 Oct 2002 10:38:33 -0000 1.44.6.1 *************** *** 24,40 **** EXEC_PREFIX = os.path.normpath(sys.exec_prefix) ! # Boolean; if it's true, we're still building Python, so ! # we use different (hard-wired) directories. ! ! python_build = 0 ! ! def set_python_build(): ! """Set the python_build flag to true. ! This means that we're building Python itself. Only called from ! the setup.py script shipped with Python. ! """ ! global python_build python_build = 1 --- 24,41 ---- EXEC_PREFIX = os.path.normpath(sys.exec_prefix) ! # python_build: (Boolean) if true, we're either building Python or ! # building an extension with an un-installed Python, so we use ! # different (hard-wired) directories. ! argv0_path = os.path.dirname(os.path.abspath(sys.executable)) ! landmark = os.path.join(argv0_path, "Modules", "Setup") ! if not os.path.isfile(landmark): ! python_build = 0 ! elif os.path.isfile(os.path.join(argv0_path, "Lib", "os.py")): python_build = 1 + else: + python_build = os.path.isfile(os.path.join(os.path.dirname(argv0_path), + "Lib", "os.py")) + del argv0_path, landmark *************** *** 54,58 **** if os.name == "posix": if python_build: ! return "Include/" return os.path.join(prefix, "include", "python" + sys.version[:3]) elif os.name == "nt": --- 55,66 ---- if os.name == "posix": if python_build: ! base = os.path.dirname(os.path.abspath(sys.executable)) ! if plat_specific: ! inc_dir = base ! else: ! inc_dir = os.path.join(base, "Include") ! if not os.path.exists(inc_dir): ! inc_dir = os.path.join(os.path.dirname(base), "Include") ! return inc_dir return os.path.join(prefix, "include", "python" + sys.version[:3]) elif os.name == "nt": *************** *** 155,159 **** """Return full pathname of installed Makefile from the Python build.""" if python_build: ! return './Makefile' lib_dir = get_python_lib(plat_specific=1, standard_lib=1) return os.path.join(lib_dir, "config", "Makefile") --- 163,167 ---- """Return full pathname of installed Makefile from the Python build.""" if python_build: ! return os.path.join(os.path.dirname(sys.executable), "Makefile") lib_dir = get_python_lib(plat_specific=1, standard_lib=1) return os.path.join(lib_dir, "config", "Makefile") From mwh@users.sourceforge.net Mon Oct 7 12:30:09 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 04:30:09 -0700 Subject: [Python-checkins] python/dist/src/Python compile.c,2.234.4.4,2.234.4.5 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv29524 Modified Files: Tag: release22-maint compile.c Log Message: Backport my checkin of revision 2.264 of Python/compile.c: Clamp code objects' tp_compare result to [-1, 1]. Bugfix candidate. Index: compile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v retrieving revision 2.234.4.4 retrieving revision 2.234.4.5 diff -C2 -d -r2.234.4.4 -r2.234.4.5 *** compile.c 11 Aug 2002 15:40:35 -0000 2.234.4.4 --- compile.c 7 Oct 2002 11:30:07 -0000 2.234.4.5 *************** *** 134,142 **** if (cmp) return cmp; cmp = co->co_argcount - cp->co_argcount; ! if (cmp) return cmp; cmp = co->co_nlocals - cp->co_nlocals; ! if (cmp) return cmp; cmp = co->co_flags - cp->co_flags; ! if (cmp) return cmp; cmp = PyObject_Compare(co->co_code, cp->co_code); if (cmp) return cmp; --- 134,142 ---- if (cmp) return cmp; cmp = co->co_argcount - cp->co_argcount; ! if (cmp) return (cmp<0)?-1:1; cmp = co->co_nlocals - cp->co_nlocals; ! if (cmp) return (cmp<0)?-1:1; cmp = co->co_flags - cp->co_flags; ! if (cmp) return (cmp<0)?-1:1; cmp = PyObject_Compare(co->co_code, cp->co_code); if (cmp) return cmp; From loewis@users.sourceforge.net Mon Oct 7 12:57:08 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 04:57:08 -0700 Subject: [Python-checkins] python/dist/src configure,1.279.6.14,1.279.6.15 configure.in,1.288.6.14,1.288.6.15 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv11763 Modified Files: Tag: release22-maint configure configure.in Log Message: Patch #609700: always build with same $(CC) on Linux. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.279.6.14 retrieving revision 1.279.6.15 diff -C2 -d -r1.279.6.14 -r1.279.6.15 *** configure 7 Oct 2002 06:22:19 -0000 1.279.6.14 --- configure 7 Oct 2002 11:57:02 -0000 1.279.6.15 *************** *** 1,5 **** #! /bin/sh ! # From configure.in Revision: 1.288.6.13 # Guess values for system-dependent variables and create Makefiles. --- 1,5 ---- #! /bin/sh ! # From configure.in Revision: 1.288.6.14 # Guess values for system-dependent variables and create Makefiles. *************** *** 3211,3215 **** LDSHARED="$LDSHARED "'-bundle_loader $(BINDIR)/$(PYTHON)' fi ;; ! Linux*) LDSHARED="gcc -shared";; dgux*) LDSHARED="ld -G";; BSD/OS*/4*) LDSHARED="gcc -shared";; --- 3211,3215 ---- LDSHARED="$LDSHARED "'-bundle_loader $(BINDIR)/$(PYTHON)' fi ;; ! Linux*) LDSHARED='$(CC) -shared';; dgux*) LDSHARED="ld -G";; BSD/OS*/4*) LDSHARED="gcc -shared";; Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.288.6.14 retrieving revision 1.288.6.15 diff -C2 -d -r1.288.6.14 -r1.288.6.15 *** configure.in 7 Oct 2002 06:22:21 -0000 1.288.6.14 --- configure.in 7 Oct 2002 11:57:04 -0000 1.288.6.15 *************** *** 825,829 **** LDSHARED="$LDSHARED "'-bundle_loader $(BINDIR)/$(PYTHON)' fi ;; ! Linux*) LDSHARED="gcc -shared";; dgux*) LDSHARED="ld -G";; BSD/OS*/4*) LDSHARED="gcc -shared";; --- 825,829 ---- LDSHARED="$LDSHARED "'-bundle_loader $(BINDIR)/$(PYTHON)' fi ;; ! Linux*) LDSHARED='$(CC) -shared';; dgux*) LDSHARED="ld -G";; BSD/OS*/4*) LDSHARED="gcc -shared";; From mwh@users.sourceforge.net Mon Oct 7 13:21:11 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 05:21:11 -0700 Subject: [Python-checkins] python/dist/src/Lib/compiler pycodegen.py,1.58.4.2,1.58.4.2.2.1 symbols.py,1.10.8.1,1.10.8.1.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/compiler In directory usw-pr-cvs1:/tmp/cvs-serv24937 Modified Files: Tag: release22-maint pycodegen.py symbols.py Log Message: A couple of fixes for the compiler package: * always write the mtime to a .pyc in little endian format * ensure class's docstrings get attached to the class, not the enclosing scope! Rather more fixes are needed for the trunk; these will be done in due course. Index: pycodegen.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/compiler/pycodegen.py,v retrieving revision 1.58.4.2 retrieving revision 1.58.4.2.2.1 diff -C2 -d -r1.58.4.2 -r1.58.4.2.2.1 *** pycodegen.py 21 Dec 2001 16:11:33 -0000 1.58.4.2 --- pycodegen.py 7 Oct 2002 12:21:09 -0000 1.58.4.2.2.1 *************** *** 137,141 **** # same effect is to call marshal and then skip the code. mtime = os.stat(self.filename)[stat.ST_MTIME] ! mtime = struct.pack('i', mtime) return self.MAGIC + mtime --- 137,141 ---- # same effect is to call marshal and then skip the code. mtime = os.stat(self.filename)[stat.ST_MTIME] ! mtime = struct.pack(' Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv32278/Misc Modified Files: Tag: release22-maint NEWS Log Message: Backport: 2002/08/11 12:23:04 lemburg Python/bltinmodule.c 2.262 2002/08/11 12:23:04 lemburg Objects/unicodeobject.c 2.162 2002/08/11 12:23:03 lemburg Misc/NEWS 1.461 2002/08/11 12:23:03 lemburg Lib/test/test_unicode.py 1.65 2002/08/11 12:23:03 lemburg Include/unicodeobject.h 2.39 Add C API PyUnicode_FromOrdinal() which exposes unichr() at C level. u'%c' will now raise a ValueError in case the argument is an integer outside the valid range of Unicode code point ordinals. Closes SF bug #593581. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.337.2.4.2.37 retrieving revision 1.337.2.4.2.38 diff -C2 -d -r1.337.2.4.2.37 -r1.337.2.4.2.38 *** NEWS 4 Oct 2002 17:57:27 -0000 1.337.2.4.2.37 --- NEWS 7 Oct 2002 12:32:55 -0000 1.337.2.4.2.38 *************** *** 5,8 **** --- 5,11 ---- Core and builtins + - u'%c' will now raise a ValueError in case the argument is an + integer outside the valid range of Unicode code point ordinals. + - When x is an object whose class implements __mul__ and __rmul__, 1.0*x would correctly invoke __rmul__, but 1*x would erroneously *************** *** 87,90 **** --- 90,96 ---- C API + + - New C API PyUnicode_FromOrdinal() which exposes unichr() at C + level. Windows From mwh@users.sourceforge.net Mon Oct 7 13:32:58 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 05:32:58 -0700 Subject: [Python-checkins] python/dist/src/Include unicodeobject.h,2.36.10.1,2.36.10.2 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv32278/Include Modified Files: Tag: release22-maint unicodeobject.h Log Message: Backport: 2002/08/11 12:23:04 lemburg Python/bltinmodule.c 2.262 2002/08/11 12:23:04 lemburg Objects/unicodeobject.c 2.162 2002/08/11 12:23:03 lemburg Misc/NEWS 1.461 2002/08/11 12:23:03 lemburg Lib/test/test_unicode.py 1.65 2002/08/11 12:23:03 lemburg Include/unicodeobject.h 2.39 Add C API PyUnicode_FromOrdinal() which exposes unichr() at C level. u'%c' will now raise a ValueError in case the argument is an integer outside the valid range of Unicode code point ordinals. Closes SF bug #593581. Index: unicodeobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/unicodeobject.h,v retrieving revision 2.36.10.1 retrieving revision 2.36.10.2 diff -C2 -d -r2.36.10.1 -r2.36.10.2 *** unicodeobject.h 22 Apr 2002 18:42:44 -0000 2.36.10.1 --- unicodeobject.h 7 Oct 2002 12:32:56 -0000 2.36.10.2 *************** *** 518,521 **** --- 518,533 ---- #endif + /* --- Unicode ordinals --------------------------------------------------- */ + + /* Create a Unicode Object from the given Unicode code point ordinal. + + The ordinal must be in range(0x10000) on narrow Python builds + (UCS2), and range(0x110000) on wide builds (UCS4). A ValueError is + raised in case it is not. + + */ + + extern DL_IMPORT(PyObject*) PyUnicode_FromOrdinal(int ordinal); + /* === Builtin Codecs ===================================================== From mwh@users.sourceforge.net Mon Oct 7 13:32:58 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 05:32:58 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_unicode.py,1.47.6.6,1.47.6.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv32278/Lib/test Modified Files: Tag: release22-maint test_unicode.py Log Message: Backport: 2002/08/11 12:23:04 lemburg Python/bltinmodule.c 2.262 2002/08/11 12:23:04 lemburg Objects/unicodeobject.c 2.162 2002/08/11 12:23:03 lemburg Misc/NEWS 1.461 2002/08/11 12:23:03 lemburg Lib/test/test_unicode.py 1.65 2002/08/11 12:23:03 lemburg Include/unicodeobject.h 2.39 Add C API PyUnicode_FromOrdinal() which exposes unichr() at C level. u'%c' will now raise a ValueError in case the argument is an integer outside the valid range of Unicode code point ordinals. Closes SF bug #593581. Index: test_unicode.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_unicode.py,v retrieving revision 1.47.6.6 retrieving revision 1.47.6.7 diff -C2 -d -r1.47.6.6 -r1.47.6.7 *** test_unicode.py 24 Sep 2002 14:06:55 -0000 1.47.6.6 --- test_unicode.py 7 Oct 2002 12:32:56 -0000 1.47.6.7 *************** *** 443,446 **** --- 443,454 ---- verify(value == u'abc, def') + for ordinal in (-100, 0x200000): + try: + u"%c" % ordinal + except ValueError: + pass + else: + print '*** formatting u"%%c" %% %i should give a ValueError' % ordinal + # formatting jobs delegated from the string implementation: verify('...%(foo)s...' % {'foo':u"abc"} == u'...abc...') *************** *** 737,740 **** --- 745,756 ---- except ValueError,why: print '*** codec for "%s" failed: %s' % (encoding, why) + + # UTF-8 must be roundtrip safe for all UCS-2 code points + # This excludes surrogates: in the full range, there would be + # a surrogate pair (\udbff\udc00), which gets converted back + # to a non-BMP character (\U0010fc00) + u = u''.join(map(unichr, range(0,0xd800)+range(0xe000,0x10000))) + for encoding in ('utf-8',): + verify(unicode(u.encode(encoding),encoding) == u) print 'done.' From mwh@users.sourceforge.net Mon Oct 7 13:32:59 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 05:32:59 -0700 Subject: [Python-checkins] python/dist/src/Objects unicodeobject.c,2.124.6.15,2.124.6.16 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv32278/Objects Modified Files: Tag: release22-maint unicodeobject.c Log Message: Backport: 2002/08/11 12:23:04 lemburg Python/bltinmodule.c 2.262 2002/08/11 12:23:04 lemburg Objects/unicodeobject.c 2.162 2002/08/11 12:23:03 lemburg Misc/NEWS 1.461 2002/08/11 12:23:03 lemburg Lib/test/test_unicode.py 1.65 2002/08/11 12:23:03 lemburg Include/unicodeobject.h 2.39 Add C API PyUnicode_FromOrdinal() which exposes unichr() at C level. u'%c' will now raise a ValueError in case the argument is an integer outside the valid range of Unicode code point ordinals. Closes SF bug #593581. Index: unicodeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v retrieving revision 2.124.6.15 retrieving revision 2.124.6.16 diff -C2 -d -r2.124.6.15 -r2.124.6.16 *** unicodeobject.c 24 Sep 2002 15:22:30 -0000 2.124.6.15 --- unicodeobject.c 7 Oct 2002 12:32:56 -0000 2.124.6.16 *************** *** 391,394 **** --- 391,433 ---- #endif + PyObject *PyUnicode_FromOrdinal(int ordinal) + { + Py_UNICODE s[2]; + + #ifdef Py_UNICODE_WIDE + if (ordinal < 0 || ordinal > 0x10ffff) { + PyErr_SetString(PyExc_ValueError, + "unichr() arg not in range(0x110000) " + "(wide Python build)"); + return NULL; + } + #else + if (ordinal < 0 || ordinal > 0xffff) { + PyErr_SetString(PyExc_ValueError, + "unichr() arg not in range(0x10000) " + "(narrow Python build)"); + return NULL; + } + #endif + + if (ordinal <= 0xffff) { + /* UCS-2 character */ + s[0] = (Py_UNICODE) ordinal; + return PyUnicode_FromUnicode(s, 1); + } + else { + #ifndef Py_UNICODE_WIDE + /* UCS-4 character. store as two surrogate characters */ + ordinal -= 0x10000L; + s[0] = 0xD800 + (Py_UNICODE) (ordinal >> 10); + s[1] = 0xDC00 + (Py_UNICODE) (ordinal & 0x03FF); + return PyUnicode_FromUnicode(s, 2); + #else + s[0] = (Py_UNICODE)ordinal; + return PyUnicode_FromUnicode(s, 1); + #endif + } + } + PyObject *PyUnicode_FromObject(register PyObject *obj) { *************** *** 5323,5327 **** if (x == -1 && PyErr_Occurred()) goto onError; ! buf[0] = (char) x; } buf[1] = '\0'; --- 5362,5381 ---- if (x == -1 && PyErr_Occurred()) goto onError; ! #ifdef Py_UNICODE_WIDE ! if (x < 0 || x > 0x10ffff) { ! PyErr_SetString(PyExc_ValueError, ! "%c arg not in range(0x110000) " ! "(wide Python build)"); ! return -1; ! } ! #else ! if (x < 0 || x > 0xffff) { ! PyErr_SetString(PyExc_ValueError, ! "%c arg not in range(0x10000) " ! "(narrow Python build)"); ! return -1; ! } ! #endif ! buf[0] = (Py_UNICODE) x; } buf[1] = '\0'; From mwh@users.sourceforge.net Mon Oct 7 13:32:59 2002 From: mwh@users.sourceforge.net (mwh@users.sourceforge.net) Date: Mon, 07 Oct 2002 05:32:59 -0700 Subject: [Python-checkins] python/dist/src/Python bltinmodule.c,2.246.4.5,2.246.4.6 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv32278/Python Modified Files: Tag: release22-maint bltinmodule.c Log Message: Backport: 2002/08/11 12:23:04 lemburg Python/bltinmodule.c 2.262 2002/08/11 12:23:04 lemburg Objects/unicodeobject.c 2.162 2002/08/11 12:23:03 lemburg Misc/NEWS 1.461 2002/08/11 12:23:03 lemburg Lib/test/test_unicode.py 1.65 2002/08/11 12:23:03 lemburg Include/unicodeobject.h 2.39 Add C API PyUnicode_FromOrdinal() which exposes unichr() at C level. u'%c' will now raise a ValueError in case the argument is an integer outside the valid range of Unicode code point ordinals. Closes SF bug #593581. Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.246.4.5 retrieving revision 2.246.4.6 diff -C2 -d -r2.246.4.5 -r2.246.4.6 *** bltinmodule.c 24 Sep 2002 11:23:05 -0000 2.246.4.5 --- bltinmodule.c 7 Oct 2002 12:32:57 -0000 2.246.4.6 *************** *** 302,343 **** { long x; - Py_UNICODE s[2]; if (!PyArg_ParseTuple(args, "l:unichr", &x)) return NULL; ! #ifdef Py_UNICODE_WIDE ! if (x < 0 || x > 0x10ffff) { ! PyErr_SetString(PyExc_ValueError, ! "unichr() arg not in range(0x110000) " ! "(wide Python build)"); ! return NULL; ! } ! #else ! if (x < 0 || x > 0xffff) { ! PyErr_SetString(PyExc_ValueError, ! "unichr() arg not in range(0x10000) " ! "(narrow Python build)"); ! return NULL; ! } ! #endif ! ! if (x <= 0xffff) { ! /* UCS-2 character */ ! s[0] = (Py_UNICODE) x; ! return PyUnicode_FromUnicode(s, 1); ! } ! else { ! #ifndef Py_UNICODE_WIDE ! /* UCS-4 character. store as two surrogate characters */ ! x -= 0x10000L; ! s[0] = 0xD800 + (Py_UNICODE) (x >> 10); ! s[1] = 0xDC00 + (Py_UNICODE) (x & 0x03FF); ! return PyUnicode_FromUnicode(s, 2); ! #else ! s[0] = (Py_UNICODE)x; ! return PyUnicode_FromUnicode(s, 1); ! #endif ! } } --- 302,310 ---- { long x; if (!PyArg_ParseTuple(args, "l:unichr", &x)) return NULL; ! return PyUnicode_FromOrdinal(x); } From gvanrossum@users.sourceforge.net Mon Oct 7 14:09:27 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 06:09:27 -0700 Subject: [Python-checkins] python/dist/src/Lib pickle.py,1.56.4.2,1.56.4.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv13142 Modified Files: Tag: release22-maint pickle.py Log Message: Backport 1.70 and 1.71 (which really go together): 1.70: whichmodule() should skip dummy package entries in sys.modules. This fixes the charming, but unhelpful error message for >>> pickle.dumps(type.__new__) Can't pickle : it's not the same object as datetime.math.__new__ 1.71: Fiddle comments and variable names in whichmodule(). Index: pickle.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pickle.py,v retrieving revision 1.56.4.2 retrieving revision 1.56.4.3 diff -C2 -d -r1.56.4.2 -r1.56.4.3 *** pickle.py 16 Jul 2002 20:02:14 -0000 1.56.4.2 --- pickle.py 7 Oct 2002 13:09:25 -0000 1.56.4.3 *************** *** 553,578 **** ! classmap = {} ! # This is no longer used to find classes, but still for functions ! def whichmodule(cls, clsname): ! """Figure out the module in which a class occurs. Search sys.modules for the module. Cache in classmap. Return a module name. ! If the class cannot be found, return __main__. """ ! if classmap.has_key(cls): ! return classmap[cls] for name, module in sys.modules.items(): if name != '__main__' and \ ! hasattr(module, clsname) and \ ! getattr(module, clsname) is cls: break else: name = '__main__' ! classmap[cls] = name return name --- 553,579 ---- ! classmap = {} # called classmap for backwards compatibility ! def whichmodule(func, funcname): ! """Figure out the module in which a function occurs. Search sys.modules for the module. Cache in classmap. Return a module name. ! If the function cannot be found, return __main__. """ ! if classmap.has_key(classmap): ! return classmap[func] for name, module in sys.modules.items(): + if module is None: + continue # skip dummy package entries if name != '__main__' and \ ! hasattr(module, funcname) and \ ! getattr(module, funcname) is func: break else: name = '__main__' ! classmap[func] = name return name From gvanrossum@users.sourceforge.net Mon Oct 7 14:18:26 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 06:18:26 -0700 Subject: [Python-checkins] python/dist/src/Lib pickle.py,1.56.4.3,1.56.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv19355 Modified Files: Tag: release22-maint pickle.py Log Message: Darn. Fix stupid typo in whichmodule() backport. Index: pickle.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pickle.py,v retrieving revision 1.56.4.3 retrieving revision 1.56.4.4 diff -C2 -d -r1.56.4.3 -r1.56.4.4 *** pickle.py 7 Oct 2002 13:09:25 -0000 1.56.4.3 --- pickle.py 7 Oct 2002 13:18:23 -0000 1.56.4.4 *************** *** 563,567 **** If the function cannot be found, return __main__. """ ! if classmap.has_key(classmap): return classmap[func] --- 563,567 ---- If the function cannot be found, return __main__. """ ! if classmap.has_key(func): return classmap[func] From loewis@users.sourceforge.net Mon Oct 7 14:23:26 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 06:23:26 -0700 Subject: [Python-checkins] python/dist/src/Lib shutil.py,1.23,1.24 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv21395/Lib Modified Files: shutil.py Log Message: Patch #448038: Add move(). Report errors from copytree as in shutil.Error. Index: shutil.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/shutil.py,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** shutil.py 8 Sep 2002 20:43:59 -0000 1.23 --- shutil.py 7 Oct 2002 13:23:24 -0000 1.24 *************** *** 8,14 **** import sys import stat __all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2", ! "copytree","rmtree"] def copyfileobj(fsrc, fdst, length=16*1024): --- 8,18 ---- import sys import stat + import exceptions __all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2", ! "copytree","rmtree","Error"] ! ! class Error(exceptions.EnvironmentError): ! pass def copyfileobj(fsrc, fdst, length=16*1024): *************** *** 96,99 **** --- 100,104 ---- names = os.listdir(src) os.mkdir(dst) + errors = [] for name in names: srcname = os.path.join(src, name) *************** *** 109,113 **** # XXX What about devices, sockets etc.? except (IOError, os.error), why: ! print "Can't copy %s to %s: %s" % (`srcname`, `dstname`, str(why)) def rmtree(path, ignore_errors=0, onerror=None): --- 114,120 ---- # XXX What about devices, sockets etc.? except (IOError, os.error), why: ! errors.append((srcname, dstname, why)) ! if errors: ! raise Error, errors def rmtree(path, ignore_errors=0, onerror=None): *************** *** 142,143 **** --- 149,171 ---- cmdtuples.append((os.remove, real_f)) cmdtuples.append((os.rmdir, path)) + + + def move(src, dst): + """Recursively move a file or directory to another location. + + If the destination is on our current filesystem, then simply use + rename. Otherwise, copy src to the dst and then remove src. + A lot more could be done here... A look at a mv.c shows a lot of + the issues this implementation glosses over. + + """ + + try: + os.rename(src, dst) + except OSError: + if os.path.isdir(src): + copytree(src, dst, symlinks=1) + rmtree(src) + else: + copy2(src,dst) + os.unlink(src) From loewis@users.sourceforge.net Mon Oct 7 14:23:26 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 06:23:26 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.493,1.494 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv21395/Misc Modified Files: NEWS Log Message: Patch #448038: Add move(). Report errors from copytree as in shutil.Error. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.493 retrieving revision 1.494 diff -C2 -d -r1.493 -r1.494 *** NEWS 5 Oct 2002 09:46:48 -0000 1.493 --- NEWS 7 Oct 2002 13:23:24 -0000 1.494 *************** *** 343,346 **** --- 343,349 ---- ------- + - shutil.move was added. shutil.copytree now reports errors as an + exception at the end, instead of printing error messages. + - Encoding name normalization was generalized to not only replace hyphens with underscores, but also all other non-alphanumeric From loewis@users.sourceforge.net Mon Oct 7 14:23:26 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 06:23:26 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libshutil.tex,1.10,1.11 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv21395/Doc/lib Modified Files: libshutil.tex Log Message: Patch #448038: Add move(). Report errors from copytree as in shutil.Error. Index: libshutil.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libshutil.tex,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** libshutil.tex 30 Jun 2002 04:43:20 -0000 1.10 --- libshutil.tex 7 Oct 2002 13:23:24 -0000 1.11 *************** *** 94,97 **** --- 94,113 ---- \end{funcdesc} + \begin{funcdesc}{move}{src, dst} + Recursively move a file or directory to another location. + + If the destination is on our current filesystem, then simply use + rename. Otherwise, copy src to the dst and then remove src. + + \versionadded{2.3} + \end{funcdesc} + + \begin{excdesc}{Error} + This exception collects exceptions that raised during a mult-file + operation. For \function{copytree}, the exception argument is a + list of 3-tuples (\var{srcname}, \var{dstname}, \var{exception}). + + \versionadded{2.3} + \end{excdesc} \subsection{Example \label{shutil-example}} From gvanrossum@users.sourceforge.net Mon Oct 7 14:24:04 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 06:24:04 -0700 Subject: [Python-checkins] python/dist/src/Lib pydoc.py,1.56.8.4,1.56.8.5 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv21949 Modified Files: Tag: release22-maint pydoc.py Log Message: Backport 1.63: In both spilldata() functions, pretend that the docstring for non-callable objects is always None. This makes for less confusing output and fixes the problem reported in SF patch #550290. Index: pydoc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v retrieving revision 1.56.8.4 retrieving revision 1.56.8.5 diff -C2 -d -r1.56.8.4 -r1.56.8.5 *** pydoc.py 26 Sep 2002 21:50:01 -0000 1.56.8.4 --- pydoc.py 7 Oct 2002 13:24:02 -0000 1.56.8.5 *************** *** 675,679 **** for name, kind, homecls, value in ok: base = self.docother(getattr(object, name), name, mod) ! doc = getattr(value, "__doc__", None) if doc is None: push('
%s
\n' % base) --- 675,682 ---- for name, kind, homecls, value in ok: base = self.docother(getattr(object, name), name, mod) ! if callable(value): ! doc = getattr(value, "__doc__", None) ! else: ! doc = None if doc is None: push('
%s
\n' % base) *************** *** 1067,1071 **** push(msg) for name, kind, homecls, value in ok: ! doc = getattr(value, "__doc__", None) push(self.docother(getattr(object, name), name, mod, 70, doc) + '\n') --- 1070,1077 ---- push(msg) for name, kind, homecls, value in ok: ! if callable(value): ! doc = getattr(value, "__doc__", None) ! else: ! doc = None push(self.docother(getattr(object, name), name, mod, 70, doc) + '\n') From gvanrossum@users.sourceforge.net Mon Oct 7 14:40:44 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 06:40:44 -0700 Subject: [Python-checkins] python/nondist/peps pep-0008.txt,1.16,1.17 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv28974 Modified Files: pep-0008.txt Log Message: Add ruling about source code encodings. Index: pep-0008.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0008.txt,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** pep-0008.txt 22 Jun 2002 02:14:49 -0000 1.16 --- pep-0008.txt 7 Oct 2002 13:40:41 -0000 1.17 *************** *** 125,128 **** --- 125,139 ---- pages of related sections of your file. + Encodings (PEP 263) + + Code in the core Python distribution should aways use the ASCII or + Latin-1 encoding (a.k.a. ISO-8859-1). Files using ASCII should + not have a coding cookie. Latin-1 should only be used when a + comment or docstring needs to mention an author name that requires + Latin-1; otherwise, using \x escapes is the preferred way to + include non-ASCII data in string literals. An exception is made + for those files that are part of the test suite for the code + implementing PEP 263. + Imports From loewis@users.sourceforge.net Mon Oct 7 14:55:53 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 06:55:53 -0700 Subject: [Python-checkins] python/dist/src/Objects stringobject.c,2.189,2.190 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv1745/Objects Modified Files: stringobject.c Log Message: Patch #479898: Use multibyte C library for printing strings if available. Index: stringobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v retrieving revision 2.189 retrieving revision 2.190 diff -C2 -d -r2.189 -r2.190 *** stringobject.c 12 Sep 2002 14:43:40 -0000 2.189 --- stringobject.c 7 Oct 2002 13:55:50 -0000 2.190 *************** *** 27,30 **** --- 27,43 ---- + #if defined(HAVE_MBTOWC) && defined(HAVE_WCHAR_H) + # define PRINT_MULTIBYTE_STRING + # include + # include + # if defined(HAVE_ISWPRINT) + # define _isprint iswprint + # else + # define _isprint isprint + # endif + #endif + + static const char *hexchars = "0123456789abcdef"; + /* For both PyString_FromString() and PyString_FromStringAndSize(), the *************** *** 750,755 **** --- 763,774 ---- string_print(PyStringObject *op, FILE *fp, int flags) { + #ifndef PRINT_MULTIBYTE_STRING int i; char c; + #else + char *scur, *send; + wchar_t c; + int cr; + #endif int quote; *************** *** 777,794 **** fputc(quote, fp); for (i = 0; i < op->ob_size; i++) { c = op->ob_sval[i]; if (c == quote || c == '\\') ! fprintf(fp, "\\%c", c); else if (c == '\t') ! fprintf(fp, "\\t"); else if (c == '\n') ! fprintf(fp, "\\n"); else if (c == '\r') ! fprintf(fp, "\\r"); ! else if (c < ' ' || c >= 0x7f) ! fprintf(fp, "\\x%02x", c & 0xff); ! else fputc(c, fp); } fputc(quote, fp); --- 796,829 ---- fputc(quote, fp); + #ifndef PRINT_MULTIBYTE_STRING for (i = 0; i < op->ob_size; i++) { c = op->ob_sval[i]; + #else + for (scur = op->ob_sval, send = op->ob_sval + op->ob_size; + scur < send; scur += cr) { + if ((cr = mbtowc(&c, scur, send - scur)) <= 0) + goto non_printable; + #endif if (c == quote || c == '\\') ! fputc('\\', fp), fputc(c, fp); else if (c == '\t') ! fputs("\\t", fp); else if (c == '\n') ! fputs("\\n", fp); else if (c == '\r') ! fputs("\\r", fp); ! #ifndef PRINT_MULTIBYTE_STRING ! else if (' ' <= c && c < 0x7f) fputc(c, fp); + else + fprintf(fp, "\\x%02x", c & 0xff); + #else + else if (_isprint(c)) + fwrite(scur, cr, 1, fp); + else { + non_printable: cr = 1; /* unit to move cursor */ + fprintf(fp, "\\x%02x", *scur & 0xff); + } + #endif } fputc(quote, fp); *************** *** 811,816 **** --- 846,857 ---- } else { + #ifndef PRINT_MULTIBYTE_STRING register int i; register char c; + #else + register char *scur, *send; + wchar_t c; + int cr; + #endif register char *p; int quote; *************** *** 825,828 **** --- 866,870 ---- p = PyString_AS_STRING(v); *p++ = quote; + #ifndef PRINT_MULTIBYTE_STRING for (i = 0; i < op->ob_size; i++) { /* There's at least enough room for a hex escape *************** *** 830,833 **** --- 872,881 ---- assert(newsize - (p - PyString_AS_STRING(v)) >= 5); c = op->ob_sval[i]; + #else + for (scur = op->ob_sval, send = op->ob_sval + op->ob_size; + scur < send; scur += cr) { + if ((cr = mbtowc(&c, scur, send - scur)) <= 0) + goto non_printable; + #endif if (c == quote || c == '\\') *p++ = '\\', *p++ = c; *************** *** 838,850 **** else if (c == '\r') *p++ = '\\', *p++ = 'r'; ! else if (c < ' ' || c >= 0x7f) { ! /* For performance, we don't want to call ! PyOS_snprintf here (extra layers of ! function call). */ ! sprintf(p, "\\x%02x", c & 0xff); ! p += 4; ! } ! else *p++ = c; } assert(newsize - (p - PyString_AS_STRING(v)) >= 1); --- 886,903 ---- else if (c == '\r') *p++ = '\\', *p++ = 'r'; ! #ifndef PRINT_MULTIBYTE_STRING ! else if (' ' <= c && c < 0x7f) *p++ = c; + else { + #else + else if (_isprint(c)) + memcpy(p, scur, cr), p += cr; + else { + non_printable: cr = 1; c = *scur; + #endif + *p++ = '\\'; *p++ = 'x'; + *p++ = hexchars[(c >> 4) & 0x0f]; + *p++ = hexchars[c & 0x0f]; + } } assert(newsize - (p - PyString_AS_STRING(v)) >= 1); From loewis@users.sourceforge.net Mon Oct 7 14:55:54 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 06:55:54 -0700 Subject: [Python-checkins] python/dist/src configure,1.342,1.343 configure.in,1.353,1.354 pyconfig.h.in,1.50,1.51 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv1745 Modified Files: configure configure.in pyconfig.h.in Log Message: Patch #479898: Use multibyte C library for printing strings if available. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.342 retrieving revision 1.343 diff -C2 -d -r1.342 -r1.343 *** configure 7 Oct 2002 06:21:41 -0000 1.342 --- configure 7 Oct 2002 13:55:30 -0000 1.343 *************** *** 1,4 **** #! /bin/sh ! # From configure.in Revision: 1.352 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. --- 1,4 ---- #! /bin/sh ! # From configure.in Revision: 1.353 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. *************** *** 11661,11669 **** for ac_func in alarm chown chroot clock confstr ctermid ctermid_r execv \ fchdir flock fork fsync fdatasync fpathconf ftime ftruncate \ gai_strerror getgroups getlogin getpeername getpgid getpid getpwent getwd \ ! hstrerror inet_pton kill killpg lchown link lstat mkfifo mknod mktime \ ! mremap nice pathconf pause plock poll pthread_init \ putenv readlink \ select setegid seteuid setgid setgroups \ --- 11661,11671 ---- + + for ac_func in alarm chown chroot clock confstr ctermid ctermid_r execv \ fchdir flock fork fsync fdatasync fpathconf ftime ftruncate \ gai_strerror getgroups getlogin getpeername getpgid getpid getpwent getwd \ ! hstrerror inet_pton iswprint kill killpg lchown link lstat mbtowc mkfifo \ ! mknod mktime mremap nice pathconf pause plock poll pthread_init \ putenv readlink \ select setegid seteuid setgid setgroups \ Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.353 retrieving revision 1.354 diff -C2 -d -r1.353 -r1.354 *** configure.in 7 Oct 2002 06:21:05 -0000 1.353 --- configure.in 7 Oct 2002 13:55:48 -0000 1.354 *************** *** 1680,1685 **** fchdir flock fork fsync fdatasync fpathconf ftime ftruncate \ gai_strerror getgroups getlogin getpeername getpgid getpid getpwent getwd \ ! hstrerror inet_pton kill killpg lchown link lstat mkfifo mknod mktime \ ! mremap nice pathconf pause plock poll pthread_init \ putenv readlink \ select setegid seteuid setgid setgroups \ --- 1680,1685 ---- fchdir flock fork fsync fdatasync fpathconf ftime ftruncate \ gai_strerror getgroups getlogin getpeername getpgid getpid getpwent getwd \ ! hstrerror inet_pton iswprint kill killpg lchown link lstat mbtowc mkfifo \ ! mknod mktime mremap nice pathconf pause plock poll pthread_init \ putenv readlink \ select setegid seteuid setgid setgroups \ Index: pyconfig.h.in =================================================================== RCS file: /cvsroot/python/python/dist/src/pyconfig.h.in,v retrieving revision 1.50 retrieving revision 1.51 diff -C2 -d -r1.50 -r1.51 *** pyconfig.h.in 4 Oct 2002 07:21:24 -0000 1.50 --- pyconfig.h.in 7 Oct 2002 13:55:49 -0000 1.51 *************** *** 197,200 **** --- 197,203 ---- #undef HAVE_INTTYPES_H + /* Define to 1 if you have the `iswprint' function. */ + #undef HAVE_ISWPRINT + /* Define to 1 if you have the `kill' function. */ #undef HAVE_KILL *************** *** 227,233 **** #undef HAVE_LIBINTL_H - /* Define to 1 if you have the `rt' library (-lrt). */ - #undef HAVE_LIBRT - /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H --- 230,233 ---- *************** *** 250,253 **** --- 250,256 ---- /* Define this if you have the makedev macro. */ #undef HAVE_MAKEDEV + + /* Define to 1 if you have the `mbtowc' function. */ + #undef HAVE_MBTOWC /* Define to 1 if you have the `memmove' function. */ From fdrake@users.sourceforge.net Mon Oct 7 17:19:04 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Mon, 07 Oct 2002 09:19:04 -0700 Subject: [Python-checkins] python/dist/src/Doc/perl python.perl,1.116.4.3,1.116.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/perl In directory usw-pr-cvs1:/tmp/cvs-serv30711 Modified Files: Tag: release22-maint python.perl Log Message: Back-port part of 1.128 from the trunk: \productioncont: Replace leading spaces with   so that it's possible to control the indentation of continuation lines. Index: python.perl =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/perl/python.perl,v retrieving revision 1.116.4.3 retrieving revision 1.116.4.4 diff -C2 -d -r1.116.4.3 -r1.116.4.4 *** python.perl 3 Apr 2002 02:46:17 -0000 1.116.4.3 --- python.perl 7 Oct 2002 16:18:57 -0000 1.116.4.4 *************** *** 809,812 **** --- 809,813 ---- local($_) = @_; my $defn = next_argument(); + $defn =~ s/^( +)/' ' x length $1/e; return ("\n" . "  \n" From fdrake@users.sourceforge.net Mon Oct 7 17:26:33 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Mon, 07 Oct 2002 09:26:33 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref5.tex,1.53.4.7,1.53.4.8 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv1987 Modified Files: Tag: release22-maint ref5.tex Log Message: Backport patches from trunk revisions 1.62, 1.63. Modified to be easier to read for both HTML and typeset renderings. Relies on ../perl/python.perl revision 1.116.4.4. Index: ref5.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref5.tex,v retrieving revision 1.53.4.7 retrieving revision 1.53.4.8 diff -C2 -d -r1.53.4.7 -r1.53.4.8 *** ref5.tex 5 Oct 2002 06:51:34 -0000 1.53.4.7 --- ref5.tex 7 Oct 2002 16:26:28 -0000 1.53.4.8 *************** *** 439,446 **** {\token{primary} "(" [\token{argument_list} [","]] ")"} \production{argument_list} ! {\token{positional_arguments} ["," \token{keyword_arguments}} ! \productioncont{ ["," "*" \token{expression} ["," "**" \token{expression}]]]} ! \productioncont{| \token{keyword_arguments} ["," "*" \token{expression}} ! \productioncont{ ["," "**" \token{expression}]]} \productioncont{| "*" \token{expression} ["," "**" \token{expression}]} \productioncont{| "**" \token{expression}} --- 439,447 ---- {\token{primary} "(" [\token{argument_list} [","]] ")"} \production{argument_list} ! {\token{positional_arguments} ["," \token{keyword_arguments}]} ! \productioncont{ ["," "*" \token{expression}]} ! \productioncont{ ["," "**" \token{expression}]} ! \productioncont{| \token{keyword_arguments} ["," "*" \token{expression}]} ! \productioncont{ ["," "**" \token{expression}]} \productioncont{| "*" \token{expression} ["," "**" \token{expression}]} \productioncont{| "**" \token{expression}} From fdrake@users.sourceforge.net Mon Oct 7 17:28:41 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Mon, 07 Oct 2002 09:28:41 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref5.tex,1.64,1.65 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv3033 Modified Files: ref5.tex Log Message: Modified presentation of the grammar for calls to be easier to read for both HTML and typeset renderings. Corresponds to revision 1.53.4.8 on the r22-maint branch. Index: ref5.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref5.tex,v retrieving revision 1.64 retrieving revision 1.65 diff -C2 -d -r1.64 -r1.65 *** ref5.tex 25 Jun 2002 04:04:14 -0000 1.64 --- ref5.tex 7 Oct 2002 16:28:38 -0000 1.65 *************** *** 423,430 **** {\token{primary} "(" [\token{argument_list} [","]] ")"} \production{argument_list} ! {\token{positional_arguments} ["," \token{keyword_arguments}] ! ["," "*" \token{expression}] ["," "**" \token{expression}]} ! \productioncont{| \token{keyword_arguments} ["," "*" \token{expression}] ! ["," "**" \token{expression}]} \productioncont{| "*" \token{expression} ["," "**" \token{expression}]} \productioncont{| "**" \token{expression}} --- 423,431 ---- {\token{primary} "(" [\token{argument_list} [","]] ")"} \production{argument_list} ! {\token{positional_arguments} ["," \token{keyword_arguments}]} ! \productioncont{ ["," "*" \token{expression}]} ! \productioncont{ ["," "**" \token{expression}]} ! \productioncont{| \token{keyword_arguments} ["," "*" \token{expression}]} ! \productioncont{ ["," "**" \token{expression}]} \productioncont{| "*" \token{expression} ["," "**" \token{expression}]} \productioncont{| "**" \token{expression}} From barry@users.sourceforge.net Mon Oct 7 18:02:44 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:02:44 -0700 Subject: [Python-checkins] python/dist/src/Lib/email Parser.py,1.5.10.2,1.5.10.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv17633/Lib/email Modified Files: Tag: release22-maint Parser.py Log Message: _parsebody(): Use get_content_type() instead of the deprecated get_type(). Also, one of the regular expressions is constant so might as well make it a module global. And, when splitting up digests, handle lineseps that are longer than 1 character in length (e.g. \r\n). Index: Parser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Parser.py,v retrieving revision 1.5.10.2 retrieving revision 1.5.10.3 diff -C2 -d -r1.5.10.2 -r1.5.10.3 *** Parser.py 4 Oct 2002 17:24:24 -0000 1.5.10.2 --- Parser.py 7 Oct 2002 17:02:40 -0000 1.5.10.3 *************** *** 21,24 **** --- 21,26 ---- False = 0 + nlcre = re.compile('\r\n|\r|\n') + *************** *** 138,142 **** # boundary if present. boundary = container.get_boundary() ! isdigest = (container.get_type() == 'multipart/digest') # If there's a boundary, split the payload text into its constituent # parts and parse each separately. Otherwise, just parse the rest of --- 140,144 ---- # boundary if present. boundary = container.get_boundary() ! isdigest = (container.get_content_type() == 'multipart/digest') # If there's a boundary, split the payload text into its constituent # parts and parse each separately. Otherwise, just parse the rest of *************** *** 168,173 **** # Find out what kind of line endings we're using start += len(mo.group('sep')) + len(mo.group('ws')) ! cre = re.compile('\r\n|\r|\n') ! mo = cre.search(payload, start) if mo: start += len(mo.group(0)) --- 170,174 ---- # Find out what kind of line endings we're using start += len(mo.group('sep')) + len(mo.group('ws')) ! mo = nlcre.search(payload, start) if mo: start += len(mo.group(0)) *************** *** 210,219 **** for part in parts: if isdigest: ! if part[0] == linesep: # There's no header block so create an empty message # object as the container, and lop off the newline so # we can parse the sub-subobject msgobj = self._class() ! part = part[1:] else: parthdrs, part = part.split(linesep+linesep, 1) --- 211,220 ---- for part in parts: if isdigest: ! if part.startswith(linesep): # There's no header block so create an empty message # object as the container, and lop off the newline so # we can parse the sub-subobject msgobj = self._class() ! part = part[len(linesep):] else: parthdrs, part = part.split(linesep+linesep, 1) From barry@users.sourceforge.net Mon Oct 7 18:05:30 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:05:30 -0700 Subject: [Python-checkins] python/dist/src/Lib/email/test test_email.py,1.17.2.1,1.17.2.2 test_email_torture.py,1.4.2.1,1.4.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email/test In directory usw-pr-cvs1:/tmp/cvs-serv19003/Lib/email/test Modified Files: Tag: release22-maint test_email.py test_email_torture.py Log Message: openfile(): Go back to opening the files in text mode. This undoes the change in revision 1.11 (test_email.py) in response to SF bug #609988. We now think that was the wrong fix and that WinZip was the real culprit there. This and the Parser.py patch will be forward ported into Python 2.3 and email 2.5. Index: test_email.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/test/test_email.py,v retrieving revision 1.17.2.1 retrieving revision 1.17.2.2 diff -C2 -d -r1.17.2.1 -r1.17.2.2 *** test_email.py 4 Oct 2002 17:40:57 -0000 1.17.2.1 --- test_email.py 7 Oct 2002 17:05:28 -0000 1.17.2.2 *************** *** 47,51 **** def openfile(filename): path = os.path.join(os.path.dirname(landmark), 'data', filename) ! return open(path, 'rb') --- 47,51 ---- def openfile(filename): path = os.path.join(os.path.dirname(landmark), 'data', filename) ! return open(path, 'r') Index: test_email_torture.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/test/test_email_torture.py,v retrieving revision 1.4.2.1 retrieving revision 1.4.2.2 diff -C2 -d -r1.4.2.1 -r1.4.2.2 *** test_email_torture.py 4 Oct 2002 17:40:57 -0000 1.4.2.1 --- test_email_torture.py 7 Oct 2002 17:05:28 -0000 1.4.2.2 *************** *** 23,27 **** from os.path import join, dirname, abspath path = abspath(join(dirname(testfile), os.pardir, 'moredata', filename)) ! return open(path, 'rb') # Prevent this test from running in the Python distro --- 23,27 ---- from os.path import join, dirname, abspath path = abspath(join(dirname(testfile), os.pardir, 'moredata', filename)) ! return open(path, 'r') # Prevent this test from running in the Python distro From gvanrossum@users.sourceforge.net Mon Oct 7 18:09:28 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:09:28 -0700 Subject: [Python-checkins] python/dist/src/Lib pydoc.py,1.56.8.5,1.56.8.6 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv20557 Modified Files: Tag: release22-maint pydoc.py Log Message: Backport 1.68: Extend stripid() to handle strings ending in more than one '>'. Add resolve() to handle looking up objects and names (fix SF bug 586931). Add a nicer error message when given a filename that doesn't exist. Index: pydoc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v retrieving revision 1.56.8.5 retrieving revision 1.56.8.6 diff -C2 -d -r1.56.8.5 -r1.56.8.6 *** pydoc.py 7 Oct 2002 13:24:02 -0000 1.56.8.5 --- pydoc.py 7 Oct 2002 17:09:25 -0000 1.56.8.6 *************** *** 107,113 **** """Remove the hexadecimal id from a Python object representation.""" # The behaviour of %p is implementation-dependent; we check two cases. ! for pattern in [' at 0x[0-9a-f]{6,}>$', ' at [0-9A-F]{8,}>$']: if re.search(pattern, repr(Exception)): ! return re.sub(pattern, '>', text) return text --- 107,113 ---- """Remove the hexadecimal id from a Python object representation.""" # The behaviour of %p is implementation-dependent; we check two cases. ! for pattern in [' at 0x[0-9a-f]{6,}(>+)$', ' at [0-9A-F]{8,}(>+)$']: if re.search(pattern, repr(Exception)): ! return re.sub(pattern, '\\1', text) return text *************** *** 1324,1366 **** html = HTMLDoc() ! def doc(thing, title='Python Library Documentation: %s', forceload=0): ! """Display text documentation, given an object or a path to an object.""" ! suffix, name = '', None ! if type(thing) is type(''): ! try: ! object = locate(thing, forceload) ! except ErrorDuringImport, value: ! print value ! return if not object: ! print 'no Python documentation found for %s' % repr(thing) ! return ! parts = split(thing, '.') ! if len(parts) > 1: suffix = ' in ' + join(parts[:-1], '.') ! name = parts[-1] ! thing = object ! desc = describe(thing) ! module = inspect.getmodule(thing) ! if not suffix and module and module is not thing: ! suffix = ' in module ' + module.__name__ ! pager(title % (desc + suffix) + '\n\n' + text.document(thing, name)) ! def writedoc(key, forceload=0): """Write HTML documentation to a file in the current directory.""" try: ! object = locate(key, forceload) ! except ErrorDuringImport, value: print value - else: - if object: - page = html.page(describe(object), - html.document(object, object.__name__)) - file = open(key + '.html', 'w') - file.write(page) - file.close() - print 'wrote', key + '.html' - else: - print 'no Python documentation found for %s' % repr(key) def writedocs(dir, pkgpath='', done=None): --- 1324,1362 ---- html = HTMLDoc() ! def resolve(thing, forceload=0): ! """Given an object or a path to an object, get the object and its name.""" ! if isinstance(thing, str): ! object = locate(thing, forceload) if not object: ! raise ImportError, 'no Python documentation found for %r' % thing ! return object, thing ! else: ! return thing, getattr(thing, '__name__', None) ! def doc(thing, title='Python Library Documentation: %s', forceload=0): ! """Display text documentation, given an object or a path to an object.""" ! try: ! object, name = resolve(thing, forceload) ! desc = describe(object) ! module = inspect.getmodule(object) ! if name and '.' in name: ! desc += ' in ' + name[:name.rfind('.')] ! elif module and module is not object: ! desc += ' in module ' + module.__name__ ! pager(title % desc + '\n\n' + text.document(object, name)) ! except (ImportError, ErrorDuringImport), value: ! print value ! def writedoc(thing, forceload=0): """Write HTML documentation to a file in the current directory.""" try: ! object, name = resolve(thing, forceload) ! page = html.page(describe(object), html.document(object, name)) ! file = open(name + '.html', 'w') ! file.write(page) ! file.close() ! print 'wrote', name + '.html' ! except (ImportError, ErrorDuringImport), value: print value def writedocs(dir, pkgpath='', done=None): *************** *** 2032,2036 **** def ispath(x): ! return type(x) is types.StringType and find(x, os.sep) >= 0 def cli(): --- 2028,2032 ---- def ispath(x): ! return isinstance(x, str) and find(x, os.sep) >= 0 def cli(): *************** *** 2072,2075 **** --- 2068,2074 ---- if not args: raise BadUsage for arg in args: + if ispath(arg) and not os.path.exists(arg): + print 'file %r does not exist' % arg + break try: if ispath(arg) and os.path.isfile(arg): From barry@users.sourceforge.net Mon Oct 7 18:18:54 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:18:54 -0700 Subject: [Python-checkins] python/dist/src/Lib/email __init__.py,1.4.10.1,1.4.10.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv25283 Modified Files: Tag: release22-maint __init__.py Log Message: Bump the version to 2.4.1 (not 2.5 as previously mentioned) to sync it with the standalone mimelib package. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/__init__.py,v retrieving revision 1.4.10.1 retrieving revision 1.4.10.2 diff -C2 -d -r1.4.10.1 -r1.4.10.2 *** __init__.py 4 Oct 2002 17:24:24 -0000 1.4.10.1 --- __init__.py 7 Oct 2002 17:18:52 -0000 1.4.10.2 *************** *** 5,9 **** """ ! __version__ = '2.4' __all__ = [ --- 5,9 ---- """ ! __version__ = '2.4.1' __all__ = [ From barry@users.sourceforge.net Mon Oct 7 18:19:44 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:19:44 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.337.2.4.2.38,1.337.2.4.2.39 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv25602 Modified Files: Tag: release22-maint NEWS Log Message: Update the email package version number. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.337.2.4.2.38 retrieving revision 1.337.2.4.2.39 diff -C2 -d -r1.337.2.4.2.38 -r1.337.2.4.2.39 *** NEWS 7 Oct 2002 12:32:55 -0000 1.337.2.4.2.38 --- NEWS 7 Oct 2002 17:19:41 -0000 1.337.2.4.2.39 *************** *** 58,62 **** - The email package from the Python 2.3 development tree has been backported, including updated documentation. This version ! corresponds to email 2.4 and should be nearly completely backward compatible. However there have been lots of improvements in the API, so you should read the section in the library manual about the --- 58,62 ---- - The email package from the Python 2.3 development tree has been backported, including updated documentation. This version ! corresponds to email 2.4.1 and should be nearly completely backward compatible. However there have been lots of improvements in the API, so you should read the section in the library manual about the From barry@users.sourceforge.net Mon Oct 7 18:20:28 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:20:28 -0700 Subject: [Python-checkins] python/dist/src/Lib/email __init__.py,1.17,1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv25879 Modified Files: __init__.py Log Message: Bump the version to 2.4.1 (not 2.5 as previously mentioned) to sync it with the standalone mimelib package. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/__init__.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** __init__.py 30 Sep 2002 20:41:33 -0000 1.17 --- __init__.py 7 Oct 2002 17:20:25 -0000 1.18 *************** *** 5,9 **** """ ! __version__ = '2.4' __all__ = [ --- 5,9 ---- """ ! __version__ = '2.4.1' __all__ = [ From loewis@users.sourceforge.net Mon Oct 7 18:27:18 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:27:18 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_pep277.py,1.2,1.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv28092 Modified Files: test_pep277.py Log Message: Use escaped Unicode literals, according to PEP 8. Index: test_pep277.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_pep277.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** test_pep277.py 5 Oct 2002 17:54:56 -0000 1.2 --- test_pep277.py 7 Oct 2002 17:27:15 -0000 1.3 *************** *** 1,3 **** - # -*- coding: utf-8 -*- # Test the Unicode versions of normal file functions # open, os.open, os.stat. os.listdir, os.rename, os.remove, os.mkdir, os.chdir, os.rmdir --- 1,2 ---- *************** *** 10,22 **** filenames = [ ! "abc", ! unicode("ascii","utf-8"), ! unicode("Grüß-Gott","utf-8"), ! unicode("Γειά-σας","utf-8"), ! unicode("Здравствуйте","utf-8"), ! unicode("にぽん","utf-8"), ! unicode("השקצץס","utf-8"), ! unicode("曨曩曫","utf-8"), ! unicode("曨שんдΓß","utf-8"), ] --- 9,21 ---- filenames = [ ! 'abc', ! u'ascii', ! u'Gr\xfc\xdf-Gott', ! u'\u0393\u03b5\u03b9\u03ac-\u03c3\u03b1\u03c2', ! u'\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435', ! u'\u306b\u307d\u3093', ! u'\u05d4\u05e9\u05e7\u05e6\u05e5\u05e1', ! u'\u66e8\u66e9\u66eb', ! u'\u66e8\u05e9\u3093\u0434\u0393\xdf', ] *************** *** 93,98 **** def test_directory(self): ! dirname = unicode(os.path.join(TESTFN,"Grüß-曨曩曫"),"utf-8") ! filename = unicode("ß-曨曩曫","utf-8") oldwd = os.getcwd() os.mkdir(dirname) --- 92,97 ---- def test_directory(self): ! dirname = os.path.join(TESTFN,u'Gr\xfc\xdf-\u66e8\u66e9\u66eb') ! filename = u'\xdf-\u66e8\u66e9\u66eb' oldwd = os.getcwd() os.mkdir(dirname) From barry@users.sourceforge.net Mon Oct 7 18:27:37 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:27:37 -0700 Subject: [Python-checkins] python/dist/src/Lib/email Parser.py,1.16,1.17 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv28371/Lib/email Modified Files: Parser.py Log Message: _parsebody(): Use get_content_type() instead of the deprecated get_type(). Also, one of the regular expressions is constant so might as well make it a module global. And, when splitting up digests, handle lineseps that are longer than 1 character in length (e.g. \r\n). Index: Parser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Parser.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** Parser.py 30 Sep 2002 20:07:22 -0000 1.16 --- Parser.py 7 Oct 2002 17:27:35 -0000 1.17 *************** *** 21,24 **** --- 21,26 ---- False = 0 + nlcre = re.compile('\r\n|\r|\n') + *************** *** 138,142 **** # boundary if present. boundary = container.get_boundary() ! isdigest = (container.get_type() == 'multipart/digest') # If there's a boundary, split the payload text into its constituent # parts and parse each separately. Otherwise, just parse the rest of --- 140,144 ---- # boundary if present. boundary = container.get_boundary() ! isdigest = (container.get_content_type() == 'multipart/digest') # If there's a boundary, split the payload text into its constituent # parts and parse each separately. Otherwise, just parse the rest of *************** *** 168,173 **** # Find out what kind of line endings we're using start += len(mo.group('sep')) + len(mo.group('ws')) ! cre = re.compile('\r\n|\r|\n') ! mo = cre.search(payload, start) if mo: start += len(mo.group(0)) --- 170,174 ---- # Find out what kind of line endings we're using start += len(mo.group('sep')) + len(mo.group('ws')) ! mo = nlcre.search(payload, start) if mo: start += len(mo.group(0)) *************** *** 210,219 **** for part in parts: if isdigest: ! if part[0] == linesep: # There's no header block so create an empty message # object as the container, and lop off the newline so # we can parse the sub-subobject msgobj = self._class() ! part = part[1:] else: parthdrs, part = part.split(linesep+linesep, 1) --- 211,220 ---- for part in parts: if isdigest: ! if part.startswith(linesep): # There's no header block so create an empty message # object as the container, and lop off the newline so # we can parse the sub-subobject msgobj = self._class() ! part = part[len(linesep):] else: parthdrs, part = part.split(linesep+linesep, 1) From barry@users.sourceforge.net Mon Oct 7 18:27:58 2002 From: barry@users.sourceforge.net (barry@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:27:58 -0700 Subject: [Python-checkins] python/dist/src/Lib/email/test test_email.py,1.17,1.18 test_email_torture.py,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email/test In directory usw-pr-cvs1:/tmp/cvs-serv28568/Lib/email/test Modified Files: test_email.py test_email_torture.py Log Message: openfile(): Go back to opening the files in text mode. This undoes the change in revision 1.11 (test_email.py) in response to SF bug #609988. We now think that was the wrong fix and that WinZip was the real culprit there. Index: test_email.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/test/test_email.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** test_email.py 1 Oct 2002 17:57:06 -0000 1.17 --- test_email.py 7 Oct 2002 17:27:55 -0000 1.18 *************** *** 47,51 **** def openfile(filename): path = os.path.join(os.path.dirname(landmark), 'data', filename) ! return open(path, 'rb') --- 47,51 ---- def openfile(filename): path = os.path.join(os.path.dirname(landmark), 'data', filename) ! return open(path, 'r') Index: test_email_torture.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/test/test_email_torture.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** test_email_torture.py 18 Sep 2002 22:17:57 -0000 1.4 --- test_email_torture.py 7 Oct 2002 17:27:55 -0000 1.5 *************** *** 23,27 **** from os.path import join, dirname, abspath path = abspath(join(dirname(testfile), os.pardir, 'moredata', filename)) ! return open(path, 'rb') # Prevent this test from running in the Python distro --- 23,27 ---- from os.path import join, dirname, abspath path = abspath(join(dirname(testfile), os.pardir, 'moredata', filename)) ! return open(path, 'r') # Prevent this test from running in the Python distro From loewis@users.sourceforge.net Mon Oct 7 18:45:58 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 10:45:58 -0700 Subject: [Python-checkins] python/dist/src configure,1.343,1.344 configure.in,1.354,1.355 pyconfig.h.in,1.51,1.52 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv3800 Modified Files: configure configure.in pyconfig.h.in Log Message: Check for wctype.h. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.343 retrieving revision 1.344 diff -C2 -d -r1.343 -r1.344 *** configure 7 Oct 2002 13:55:30 -0000 1.343 --- configure 7 Oct 2002 17:45:53 -0000 1.344 *************** *** 1,4 **** #! /bin/sh ! # From configure.in Revision: 1.353 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. --- 1,4 ---- #! /bin/sh ! # From configure.in Revision: 1.354 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53. *************** *** 902,906 **** # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ! ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` --- 902,906 ---- # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ! ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` *************** *** 3891,3894 **** --- 3891,3895 ---- + for ac_header in dlfcn.h fcntl.h grp.h limits.h langinfo.h \ libintl.h locale.h ncurses.h poll.h pthread.h \ *************** *** 3896,3900 **** sys/audioio.h sys/file.h sys/lock.h sys/mkdev.h sys/modem.h \ sys/param.h sys/poll.h sys/select.h sys/socket.h sys/time.h sys/times.h \ ! sys/un.h sys/utsname.h sys/wait.h pty.h term.h libutil.h \ sys/resource.h netpacket/packet.h do --- 3897,3901 ---- sys/audioio.h sys/file.h sys/lock.h sys/mkdev.h sys/modem.h \ sys/param.h sys/poll.h sys/select.h sys/socket.h sys/time.h sys/times.h \ ! sys/un.h sys/utsname.h sys/wait.h pty.h term.h wctype.h libutil.h \ sys/resource.h netpacket/packet.h do *************** *** 16842,16846 **** # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ! ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` --- 16843,16847 ---- # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ! ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.354 retrieving revision 1.355 diff -C2 -d -r1.354 -r1.355 *** configure.in 7 Oct 2002 13:55:48 -0000 1.354 --- configure.in 7 Oct 2002 17:45:55 -0000 1.355 *************** *** 619,623 **** sys/audioio.h sys/file.h sys/lock.h sys/mkdev.h sys/modem.h \ sys/param.h sys/poll.h sys/select.h sys/socket.h sys/time.h sys/times.h \ ! sys/un.h sys/utsname.h sys/wait.h pty.h term.h libutil.h \ sys/resource.h netpacket/packet.h) AC_HEADER_DIRENT --- 619,623 ---- sys/audioio.h sys/file.h sys/lock.h sys/mkdev.h sys/modem.h \ sys/param.h sys/poll.h sys/select.h sys/socket.h sys/time.h sys/times.h \ ! sys/un.h sys/utsname.h sys/wait.h pty.h term.h wctype.h libutil.h \ sys/resource.h netpacket/packet.h) AC_HEADER_DIRENT Index: pyconfig.h.in =================================================================== RCS file: /cvsroot/python/python/dist/src/pyconfig.h.in,v retrieving revision 1.51 retrieving revision 1.52 diff -C2 -d -r1.51 -r1.52 *** pyconfig.h.in 7 Oct 2002 13:55:49 -0000 1.51 --- pyconfig.h.in 7 Oct 2002 17:45:56 -0000 1.52 *************** *** 593,596 **** --- 593,599 ---- #undef HAVE_WCHAR_H + /* Define to 1 if you have the header file. */ + #undef HAVE_WCTYPE_H + /* Define to 1 if you have the `_getpty' function. */ #undef HAVE__GETPTY From gvanrossum@users.sourceforge.net Mon Oct 7 19:08:29 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 11:08:29 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.337.2.4.2.39,1.337.2.4.2.40 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv14033/Misc Modified Files: Tag: release22-maint NEWS Log Message: Backport, at the reqest of Kevin Jacobs: - Changed new-style class instantiation so that when C's __new__ method returns something that's not a C instance, its __init__ is not called. [SF bug #537450] XXX This is arguably a semantic change, but it's hard to imagine a reason for wanting to depend on the old behavior. If problems with this are reported within a week of the release of 2.2.2 beta 1, we may revert this change. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.337.2.4.2.39 retrieving revision 1.337.2.4.2.40 diff -C2 -d -r1.337.2.4.2.39 -r1.337.2.4.2.40 *** NEWS 7 Oct 2002 17:19:41 -0000 1.337.2.4.2.39 --- NEWS 7 Oct 2002 18:08:26 -0000 1.337.2.4.2.40 *************** *** 1,7 **** ! What's New in Python 2.2.2? ! Release date: dd-mmm-2002 ! =========================== Core and builtins - u'%c' will now raise a ValueError in case the argument is an --- 1,14 ---- ! What's New in Python 2.2.2b1? ! Release date: 7-Oct-2002 ! ============================= Core and builtins + + - Changed new-style class instantiation so that when C's __new__ + method returns something that's not a C instance, its __init__ is + not called. [SF bug #537450] (This is arguably a semantic change, + but it's hard to imagine a reason for wanting to depend on the old + behavior. If problems with this are reported within a week of the + release of 2.2.2 beta 1, we may revert this change.) - u'%c' will now raise a ValueError in case the argument is an From gvanrossum@users.sourceforge.net Mon Oct 7 19:08:29 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 11:08:29 -0700 Subject: [Python-checkins] python/dist/src/Objects typeobject.c,2.126.4.23,2.126.4.24 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv14033/Objects Modified Files: Tag: release22-maint typeobject.c Log Message: Backport, at the reqest of Kevin Jacobs: - Changed new-style class instantiation so that when C's __new__ method returns something that's not a C instance, its __init__ is not called. [SF bug #537450] XXX This is arguably a semantic change, but it's hard to imagine a reason for wanting to depend on the old behavior. If problems with this are reported within a week of the release of 2.2.2 beta 1, we may revert this change. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.126.4.23 retrieving revision 2.126.4.24 diff -C2 -d -r2.126.4.23 -r2.126.4.24 *** typeobject.c 14 Aug 2002 17:36:26 -0000 2.126.4.23 --- typeobject.c 7 Oct 2002 18:08:27 -0000 2.126.4.24 *************** *** 190,193 **** --- 190,197 ---- (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) return obj; + /* If the returned object is not an instance of type, + it won't be initialized. */ + if (!PyType_IsSubtype(obj->ob_type, type)) + return obj; type = obj->ob_type; if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS) && From gvanrossum@users.sourceforge.net Mon Oct 7 19:08:28 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 11:08:28 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_descr.py,1.113.4.24,1.113.4.25 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv14033/Lib/test Modified Files: Tag: release22-maint test_descr.py Log Message: Backport, at the reqest of Kevin Jacobs: - Changed new-style class instantiation so that when C's __new__ method returns something that's not a C instance, its __init__ is not called. [SF bug #537450] XXX This is arguably a semantic change, but it's hard to imagine a reason for wanting to depend on the old behavior. If problems with this are reported within a week of the release of 2.2.2 beta 1, we may revert this change. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.113.4.24 retrieving revision 1.113.4.25 diff -C2 -d -r1.113.4.24 -r1.113.4.25 *** test_descr.py 1 Aug 2002 19:03:41 -0000 1.113.4.24 --- test_descr.py 7 Oct 2002 18:08:26 -0000 1.113.4.25 *************** *** 3018,3021 **** --- 3018,3042 ---- del C.__del__ + def funnynew(): + if verbose: print "Testing __new__ returning something unexpected..." + class C(object): + def __new__(cls, arg): + if isinstance(arg, str): return [1, 2, 3] + elif isinstance(arg, int): return object.__new__(D) + else: return object.__new__(cls) + class D(C): + def __init__(self, arg): + self.foo = arg + vereq(C("1"), [1, 2, 3]) + vereq(D("1"), [1, 2, 3]) + d = D(None) + veris(d.foo, None) + d = C(1) + vereq(isinstance(d, D), True) + vereq(d.foo, 1) + d = D(1) + vereq(isinstance(d, D), True) + vereq(d.foo, 1) + def test_main(): class_docstrings() *************** *** 3079,3082 **** --- 3100,3104 ---- copy_setstate() subtype_resurrection() + funnynew() if verbose: print "All OK" From gvanrossum@users.sourceforge.net Mon Oct 7 19:14:21 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 11:14:21 -0700 Subject: [Python-checkins] python/dist/src README,1.136.4.7,1.136.4.8 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv17833 Modified Files: Tag: release22-maint README Log Message: Update version to 2.2.2b1. Index: README =================================================================== RCS file: /cvsroot/python/python/dist/src/README,v retrieving revision 1.136.4.7 retrieving revision 1.136.4.8 diff -C2 -d -r1.136.4.7 -r1.136.4.8 *** README 23 Sep 2002 14:02:44 -0000 1.136.4.7 --- README 7 Oct 2002 18:14:18 -0000 1.136.4.8 *************** *** 1,4 **** ! This is Python version 2.2.1 ! ============================ Copyright (c) 2001, 2002 Python Software Foundation. --- 1,4 ---- ! This is Python version 2.2.2b1 ! ============================== Copyright (c) 2001, 2002 Python Software Foundation. From loewis@users.sourceforge.net Mon Oct 7 19:26:19 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 11:26:19 -0700 Subject: [Python-checkins] python/dist/src/Objects stringobject.c,2.190,2.191 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv23766 Modified Files: stringobject.c Log Message: Include wctype.h. Index: stringobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v retrieving revision 2.190 retrieving revision 2.191 diff -C2 -d -r2.190 -r2.191 *** stringobject.c 7 Oct 2002 13:55:50 -0000 2.190 --- stringobject.c 7 Oct 2002 18:26:16 -0000 2.191 *************** *** 27,34 **** ! #if defined(HAVE_MBTOWC) && defined(HAVE_WCHAR_H) # define PRINT_MULTIBYTE_STRING # include # include # if defined(HAVE_ISWPRINT) # define _isprint iswprint --- 27,35 ---- ! #if defined(HAVE_MBTOWC) && defined(HAVE_WCHAR_H) && defined(HAVE_WCTYPE_H) # define PRINT_MULTIBYTE_STRING # include # include + # include # if defined(HAVE_ISWPRINT) # define _isprint iswprint From loewis@users.sourceforge.net Mon Oct 7 19:34:36 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 11:34:36 -0700 Subject: [Python-checkins] python/nondist/peps pep-0277.txt,1.3,1.4 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv27885 Modified Files: pep-0277.txt Log Message: The PEP is now implemented. Index: pep-0277.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0277.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** pep-0277.txt 12 Aug 2002 11:43:56 -0000 1.3 --- pep-0277.txt 7 Oct 2002 18:34:33 -0000 1.4 *************** *** 4,8 **** Last-Modified: $Date$ Author: neilh@scintilla.org (Neil Hodgson) ! Status: Draft Type: Standards Track Created: 11-Jan-2002 --- 4,8 ---- Last-Modified: $Date$ Author: neilh@scintilla.org (Neil Hodgson) ! Status: Final Type: Standards Track Created: 11-Jan-2002 From loewis@users.sourceforge.net Mon Oct 7 19:38:50 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 11:38:50 -0700 Subject: [Python-checkins] python/nondist/peps pep-0000.txt,1.213,1.214 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv29968 Modified Files: pep-0000.txt Log Message: Update status for PEP 277. Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.213 retrieving revision 1.214 diff -C2 -d -r1.213 -r1.214 *** pep-0000.txt 20 Sep 2002 14:10:49 -0000 1.213 --- pep-0000.txt 7 Oct 2002 18:38:47 -0000 1.214 *************** *** 88,92 **** S 275 Switching on Multiple Values Lemburg S 276 Simple Iterator for ints Althoff - S 277 Unicode file name support for Windows NT Hodgson S 278 Universal Newline Support Jansen S 280 Optimizing access to globals van Rossum --- 88,91 ---- *************** *** 137,140 **** --- 136,140 ---- SF 263 Defining Python Source Code Encodings Lemburg SF 264 Future statements in simulated shells Hudson + SF 277 Unicode file name support for Windows NT Hodgson SF 279 The enumerate() built-in function Hettinger SF 285 Adding a bool type van Rossum *************** *** 269,273 **** S 275 Switching on Multiple Values Lemburg S 276 Simple Iterator for ints Althoff ! S 277 Unicode file name support for Windows NT Hodgson S 278 Universal Newline Support Jansen SF 279 The enumerate() built-in function Hettinger --- 269,273 ---- S 275 Switching on Multiple Values Lemburg S 276 Simple Iterator for ints Althoff ! SF 277 Unicode file name support for Windows NT Hodgson S 278 Universal Newline Support Jansen SF 279 The enumerate() built-in function Hettinger From fdrake@users.sourceforge.net Mon Oct 7 19:47:51 2002 From: fdrake@users.sourceforge.net (fdrake@users.sourceforge.net) Date: Mon, 07 Oct 2002 11:47:51 -0700 Subject: [Python-checkins] python/dist/src/Doc Makefile,1.235.2.1.2.12,1.235.2.1.2.13 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory usw-pr-cvs1:/tmp/cvs-serv3056 Modified Files: Tag: release22-maint Makefile Log Message: Fix up the release number for the 2.2.2b1 documentation release. This is what was actually used. Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile,v retrieving revision 1.235.2.1.2.12 retrieving revision 1.235.2.1.2.13 diff -C2 -d -r1.235.2.1.2.12 -r1.235.2.1.2.13 *** Makefile 4 Oct 2002 20:40:44 -0000 1.235.2.1.2.12 --- Makefile 7 Oct 2002 18:47:48 -0000 1.235.2.1.2.13 *************** *** 67,71 **** # This is the *documentation* release, and is used to construct the file # names of the downloadable tarballs. ! RELEASE=2.2.2 PYTHON= python --- 67,71 ---- # This is the *documentation* release, and is used to construct the file # names of the downloadable tarballs. ! RELEASE=2.2.2b1 PYTHON= python From loewis@users.sourceforge.net Mon Oct 7 19:52:31 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 11:52:31 -0700 Subject: [Python-checkins] python/dist/src/Doc/whatsnew whatsnew23.tex,1.53,1.54 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/whatsnew In directory usw-pr-cvs1:/tmp/cvs-serv5453 Modified Files: whatsnew23.tex Log Message: Document PEP 277 changes. Index: whatsnew23.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/whatsnew/whatsnew23.tex,v retrieving revision 1.53 retrieving revision 1.54 diff -C2 -d -r1.53 -r1.54 *** whatsnew23.tex 4 Oct 2002 22:34:11 -0000 1.53 --- whatsnew23.tex 7 Oct 2002 18:52:29 -0000 1.54 *************** *** 307,312 **** \seepep{263}{Defining Python Source Code Encodings}{Written by ! Marc-Andr\'e Lemburg and Martin von L\"owis; implemented by Martin von ! L\"owis.} \end{seealso} --- 307,312 ---- \seepep{263}{Defining Python Source Code Encodings}{Written by ! Marc-Andr\'e Lemburg and Martin von L\"owis; implemented by SUZUKI ! Hisao and Martin von L\"owis.} \end{seealso} *************** *** 314,320 **** %====================================================================== ! \section{PEP 277: XXX} ! XXX write this section --- 314,346 ---- %====================================================================== ! \section{PEP 277: Unicode file name support for Windows NT} ! On Windows NT, 2000, and XP, the system stores file names as Unicode ! strings. Traditionally, Python has represented file names are byte ! strings, which is inadequate since it renders some file names ! inaccessible. ! ! Python allows now to use arbitrary Unicode strings (within limitations ! of the file system) for all functions that expect file names, in ! particular \function{open}. If a Unicode string is passed to ! \function{os.listdir}, Python returns now a list of Unicode strings. ! A new function \function{getcwdu} returns the current directory as a ! Unicode string. ! ! Byte strings continue to work as file names, the system will ! transparently convert them to Unicode using the \code{mbcs} encoding. ! ! Other systems allow Unicode strings as file names as well, but convert ! them to byte strings before passing them to the system, which may ! cause UnicodeErrors. Applications can test whether arbitrary Unicode ! strings are supported as file names with \code{os.path.unicode_file_names}. ! ! \begin{seealso} ! ! \seepep{277}{Unicode file name support for Windows NT}{Written by Neil ! Hodgson; implemented by Neil Hodgson, Martin von L\"owis, and Mark ! Hammond.} ! ! \end{seealso} From loewis@users.sourceforge.net Mon Oct 7 20:01:10 2002 From: loewis@users.sourceforge.net (loewis@users.sourceforge.net) Date: Mon, 07 Oct 2002 12:01:10 -0700 Subject: [Python-checkins] python/dist/src/Doc/whatsnew whatsnew23.tex,1.54,1.55 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/whatsnew In directory usw-pr-cvs1:/tmp/cvs-serv10373 Modified Files: whatsnew23.tex Log Message: Document PEP 293. Index: whatsnew23.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/whatsnew/whatsnew23.tex,v retrieving revision 1.54 retrieving revision 1.55 diff -C2 -d -r1.54 -r1.55 *** whatsnew23.tex 7 Oct 2002 18:52:29 -0000 1.54 --- whatsnew23.tex 7 Oct 2002 19:01:07 -0000 1.55 *************** *** 493,497 **** \section{PEP 293: Codec Error Handling Callbacks} ! XXX write this section \begin{seealso} --- 493,517 ---- \section{PEP 293: Codec Error Handling Callbacks} ! When encoding a Unicode string into a byte string, unencodable ! characters may be encountered. So far, Python allowed to specify the ! error processing as either ``strict'' (raise \code{UnicodeError}, ! default), ``ignore'' (skip the character), or ``replace'' (with ! question mark). It may be desirable to specify an alternative ! processing of the error, e.g. by inserting an XML character reference ! or HTML entity reference into the converted string. ! ! Python now has a flexible framework to add additional processing ! strategies; new error handlers can be added with ! \function{codecs.register_error}. Codecs then can access the error ! handler with \code{codecs.lookup_error}. An equivalent C API has been ! added for codecs written in C. The error handler gets various state ! information, such as the string being converted, the position in the ! string where the error was detected, and the target encoding. It can ! then either raise an exception, or return a replacement string. ! ! Two additional error handlers have been implemented using this ! framework: ``backslashreplace'' using Python backslash quoting to ! represent the unencodable character, and ``xmlcharrefreplace'' emits ! XML character references. \begin{seealso} From gvanrossum@users.sourceforge.net Mon Oct 7 22:39:02 2002 From: gvanrossum@users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Mon, 07 Oct 2002 14:39:02 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.337.2.4.2.40,1.337.2.4.2.41 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv16554 Modified Files: Tag: release22-maint NEWS Log Message: News for 2.2.2b1. I'm exhausted -- this was a multi-hour job of poring over the logs. Quite likely I've forgotten some things, introduced typos, and organized things less than ideally. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.337.2.4.2.40 retrieving revision 1.337.2.4.2.41 diff -C2 -d -r1.337.2.4.2.40 -r1.337.2.4.2.41 *** NEWS 7 Oct 2002 18:08:26 -0000 1.337.2.4.2.40 --- NEWS 7 Oct 2002 21:38:58 -0000 1.337.2.4.2.41 *************** *** 3,6 **** --- 3,17 ---- ============================= + Almost everything in this release is a pure bugfix and is backported + from a corresponding bugfix alrady applied to Python 2.3. While at + the time of writing, Python 2.3 is still in pre-alpha form, only + accessible via CVS, it receives continuous and extensive testing by + its developers. The list below is not a complete list of fixed bugs; + it only lists fixed bugs that someone might be interested in hearing + about. Documentation fixes are not listed. + + Tip: to quickly find SourceForge bug or patch NNNNNN, use an URL of + the form www.python.org/sf/NNNNNN. + Core and builtins *************** *** 12,18 **** --- 23,64 ---- release of 2.2.2 beta 1, we may revert this change.) + - Fix a core dump in type_new() when looking for the tp_init() slot. + This could call a garbage pointer when e.g. an ExtensionClass was + given. + + - A variety of very obscure end-case bugs in new-style classes were + fixed, some of which could be made to trigger core dumps with absurd + input. + - u'%c' will now raise a ValueError in case the argument is an integer outside the valid range of Unicode code point ordinals. + - Several small patches were applied that aren't bugfixes (and aren't + even backported from 2.3!) but make life easier for tools like Armin + Rigo's Psyco. [SF patches 617309, 617311, 617312] + + - Made conversion failure error message consistent between types. + + - The complex() built-in now finds __complex__() in new-style + classes. [SF bug 563740] + + - Fixed a problem in the UTF-8 decoder where a Unicode literal + containing a "lone surrogate" would cause a .pyc file to be written + that could not be read. [SF bug 610783] + + - Fixed a problem with code objects whose stacksize is >= 2**15. + These cannot be marshalled correctly. As a work-around, don't write + a .pyc file in this case. [SF bug 561858] + + - Fixed several bugs that could cause issubclass() and isinstance() to + leave an exception lingering behind while returning a non-error + value. + + - The Unicode replace() method would do the wrong thing for a unicode + subclass when there were zero string replacements. [SF bug 599128] + + - Fixed some endcase bugs in Unicode rfind()/rindex() and endswith(). + [SF bug 595350] + - When x is an object whose class implements __mul__ and __rmul__, 1.0*x would correctly invoke __rmul__, but 1*x would erroneously *************** *** 20,25 **** type. This has been fixed now. ! - If a dying instance of a new-style class got resurrected by its class's ! __del__ method, Python aborted with a fatal error. - Source that creates parse nodes with an extremely large number of --- 66,73 ---- type. This has been fixed now. ! - The __delete__ method wrapper wasn't supported. [SF patch 588728] ! ! - If a dying instance of a new-style class got resurrected by its ! class's __del__ method, Python aborted with a fatal error. - Source that creates parse nodes with an extremely large number of *************** *** 38,44 **** [SF bug 519621] - Repaired a slow memory leak possible only in programs creating a ! great many cyclic structures involving frames. Reported on ! SourceForge as bug 543148. - A method zfill() was added to str and unicode, that fills a numeric --- 86,96 ---- [SF bug 519621] + - Fixed an inefficiency in clearing the stack frame of new frame + objects. + - Repaired a slow memory leak possible only in programs creating a ! great many cyclic structures involving frames [SF bug 543148]. ! ! - Fixed an esoteric performance glitch in GC. [SF bug 574132] - A method zfill() was added to str and unicode, that fills a numeric *************** *** 50,63 **** deprecated now. ! - String methods lstrip(), rstrip() and strip() now take an optional ! argument that specifies the characters to strip. For example, ! "Foo!!!?!?!?".rstrip("?!") -> "Foo". In addition, "200L".strip("L") ! will return "200". This is useful for replacing code that assumed ! longs will always be printed with a trailing "L". Extension modules ! - If the size passed to mmap.mmap() is larger than the length of the ! file on non-Windows platforms, a ValueError is raised. [SF bug 585792] Library --- 102,137 ---- deprecated now. ! - String and Unicode methods lstrip(), rstrip() and strip() now take ! an optional argument that specifies the characters to strip. For ! example, "Foo!!!?!?!?".rstrip("?!") -> "Foo". In addition, ! "200L".strip("L") will return "200". This is useful for replacing ! code that assumed longs will always be printed with a trailing "L". ! ! - A change to how new-style classes deal with __doc__: you can now ! supply a __doc__ descriptor that returns something different for a ! class than for instances of that class. Extension modules ! - In readline.c: change completion to avoid appending a space ! character; this is usually more useful when editing Python code. ! ! - Fixed a crash in debug builds for marshal.dumps([128] * 1000). [SF ! bug 588452] ! ! - In cPickle.c: more robust test of whether global objects are ! accessible. Added recursion limit to pickling [SF bug 576084]. Try ! the persistent id code *before* calling save_global(). ! ! - In mmapmpdule.c: if the size passed to mmap() is larger than the ! length of the file on non-Windows platforms, a ValueError is ! raised. [SF bug 585792] ! ! - In socketmodule.c: improve robustness of IPv6 code. ! ! - In _hotshot.c: fix broken logic in the logreader object. ! ! - In zlibmodule.c: fix for crash on second flush() call. [SF bug ! 544995] Library *************** *** 70,90 **** changes since email v1. ! - random.gauss() uses a piece of hidden state used by nothing else, ! and the .seed() and .whseed() methods failed to reset it. In other ! words, setting the seed didn't completely determine the sequence of ! results produced by random.gauss(). It does now. Programs repeatedly ! mixing calls to a seed method with calls to gauss() may see different ! results now. ! - Some fixes in the copy module: when an object is copied through its ! __reduce__ method, there was no check for a __setstate__ method on ! the result [SF patch 565085]; deepcopy should treat instances of ! custom metaclasses the same way it treats instances of type 'type' ! [SF patch 560794]. Build - The fpectl module is not built by default; it's dangerous or useless ! except in the hands of experts. - A bug was fixed that could cause COUNT_ALLOCS builds to segfault, or --- 144,295 ---- changes since email v1. ! - In pydoc.py: Extend stripid() to handle strings ending in more than ! one '>'; add resolve() to handle looking up objects and names (fix ! SF bug 586931); add a nicer error message when given a filename that ! doesn't exist. Pretend that the docstring for non-callable objects ! is always None; this makes for less confusing output and fixes the ! problem reported in SF patch 550290. Change the way 'less' is ! invoked as a browser (on Unix) to make it more robust. ! - In pickle.py: Whichmodule() now skips dummy (None) package entries ! in sys.modules. Try the persistent id code *before* calling ! save_global(). ! ! - A variety of fixes were applied to the compiler package. ! ! - In distutils/: Fix distutils.sysconfig to understand that the ! running Python is part of the build tree and needs to use the ! appropriate "shape" of the tree [SF patch 547734]. Prefer rpmbuild ! over rpm if available [SF patch 619493]. util.convert_path() ! failed with empty pathname. [SF bug 574235] ! ! - In posixpath.py and user.py: fixed SF bug 555779, "import user ! doesn't work with CGIs." ! ! - In site.py: fixed a problem which triggered when sys.path was empty. ! ! - In smtpd.py: print the refused list to the DEBUGSTREAM [SF 515021]; ! removed an embarrassing debug line from smtp_RCPT(). ! ! - In smtplib.py: fix multiline string in sendmail example [SF patch ! 586999]; handle empty addresses [SF bug 602029]. ! ! - In urllib.py: treat file://localhost/ as local too (same as file:/ ! and file:///). [SF bug 607789] ! ! - In warnings.py: ignore IOError when writing the message. ! ! - In ConfigParser.py: allow internal whitespace in keys [SF bug ! 583248]; use option name transform consistently in has_option() [SF ! bug 561822]; misc other patches. ! ! - In sre_compile.py (the compile() function for the re module): ! Disable big charsets in UCS-4 builds. [SF bug 599377] ! ! - In pre.py (the deprecated, *old* implementation of the re module): ! fix broken sub() and subn(). [SF bug 570057] ! ! - In weakref.py: The WeakKeyDictionary constructor didn't work when a ! dict arg was given. [SF patch 564549] ! ! - In xml/: various fixes tracking PyXML. ! ! - In urllib2.py: fix proxy config with user+pass authentication. [SF ! patch 527518] ! ! - In pdb.py: Increase the maxstring value of _saferepr. Add exit as ! an alias for quit [SF bug 543674]. Fix crash on input line ! consisting of one or more spaces [SF bug 579701]. ! ! - In t