Convert PEPs 222, 224, 281, 284, 310 (#203)
This commit is contained in:
parent
0966f373b6
commit
c5881cf2b5
233
pep-0222.txt
233
pep-0222.txt
|
@ -5,110 +5,123 @@ Last-Modified: $Date$
|
||||||
Author: A.M. Kuchling <amk@amk.ca>
|
Author: A.M. Kuchling <amk@amk.ca>
|
||||||
Status: Deferred
|
Status: Deferred
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 18-Aug-2000
|
Created: 18-Aug-2000
|
||||||
Python-Version: 2.1
|
Python-Version: 2.1
|
||||||
Post-History: 22-Dec-2000
|
Post-History: 22-Dec-2000
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
This PEP proposes a set of enhancements to the CGI development
|
This PEP proposes a set of enhancements to the CGI development
|
||||||
facilities in the Python standard library. Enhancements might be
|
facilities in the Python standard library. Enhancements might be
|
||||||
new features, new modules for tasks such as cookie support, or
|
new features, new modules for tasks such as cookie support, or
|
||||||
removal of obsolete code.
|
removal of obsolete code.
|
||||||
|
|
||||||
|
The original intent was to make improvements to Python 2.1.
|
||||||
|
However, there seemed little interest from the Python community,
|
||||||
|
and time was lacking, so this PEP has been deferred to some future
|
||||||
|
Python release.
|
||||||
|
|
||||||
The original intent was to make improvements to Python 2.1.
|
|
||||||
However, there seemed little interest from the Python community,
|
|
||||||
and time was lacking, so this PEP has been deferred to some future
|
|
||||||
Python release.
|
|
||||||
|
|
||||||
|
|
||||||
Open Issues
|
Open Issues
|
||||||
|
===========
|
||||||
|
|
||||||
This section lists changes that have been suggested, but about
|
This section lists changes that have been suggested, but about
|
||||||
which no firm decision has yet been made. In the final version of
|
which no firm decision has yet been made. In the final version of
|
||||||
this PEP, this section should be empty, as all the changes should
|
this PEP, this section should be empty, as all the changes should
|
||||||
be classified as accepted or rejected.
|
be classified as accepted or rejected.
|
||||||
|
|
||||||
cgi.py: We should not be told to create our own subclass just so
|
cgi.py: We should not be told to create our own subclass just so
|
||||||
we can handle file uploads. As a practical matter, I have yet to
|
we can handle file uploads. As a practical matter, I have yet to
|
||||||
find the time to do this right, so I end up reading cgi.py's temp
|
find the time to do this right, so I end up reading cgi.py's temp
|
||||||
file into, at best, another file. Some of our legacy code actually
|
file into, at best, another file. Some of our legacy code actually
|
||||||
reads it into a second temp file, then into a final destination!
|
reads it into a second temp file, then into a final destination!
|
||||||
And even if we did, that would mean creating yet another object
|
And even if we did, that would mean creating yet another object
|
||||||
with its __init__ call and associated overhead.
|
with its ``__init__`` call and associated overhead.
|
||||||
|
|
||||||
cgi.py: Currently, query data with no `=' are ignored. Even if
|
cgi.py: Currently, query data with no ``=`` are ignored. Even if
|
||||||
keep_blank_values is set, queries like `...?value=&...' are
|
keep_blank_values is set, queries like ``...?value=&...`` are
|
||||||
returned with blank values but queries like `...?value&...' are
|
returned with blank values but queries like ``...?value&...`` are
|
||||||
completely lost. It would be great if such data were made
|
completely lost. It would be great if such data were made
|
||||||
available through the FieldStorage interface, either as entries
|
available through the ``FieldStorage`` interface, either as entries
|
||||||
with None as values, or in a separate list.
|
with None as values, or in a separate list.
|
||||||
|
|
||||||
Utility function: build a query string from a list of 2-tuples
|
Utility function: build a query string from a list of 2-tuples
|
||||||
|
|
||||||
|
Dictionary-related utility classes: ``NoKeyErrors`` (returns an empty
|
||||||
|
string, never a ``KeyError``), ``PartialStringSubstitution`` (returns
|
||||||
|
the original key string, never a ``KeyError``)
|
||||||
|
|
||||||
Dictionary-related utility classes: NoKeyErrors (returns an empty
|
|
||||||
string, never a KeyError), PartialStringSubstitution (returns
|
|
||||||
the original key string, never a KeyError)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
New Modules
|
New Modules
|
||||||
|
===========
|
||||||
|
|
||||||
This section lists details about entire new packages or modules
|
This section lists details about entire new packages or modules
|
||||||
that should be added to the Python standard library.
|
that should be added to the Python standard library.
|
||||||
|
|
||||||
|
* fcgi.py : A new module adding support for the FastCGI protocol.
|
||||||
|
Robin Dunn's code needs to be ported to Windows, though.
|
||||||
|
|
||||||
* fcgi.py : A new module adding support for the FastCGI protocol.
|
|
||||||
Robin Dunn's code needs to be ported to Windows, though.
|
|
||||||
|
|
||||||
Major Changes to Existing Modules
|
Major Changes to Existing Modules
|
||||||
|
=================================
|
||||||
|
|
||||||
This section lists details of major changes to existing modules,
|
This section lists details of major changes to existing modules,
|
||||||
whether in implementation or in interface. The changes in this
|
whether in implementation or in interface. The changes in this
|
||||||
section therefore carry greater degrees of risk, either in
|
section therefore carry greater degrees of risk, either in
|
||||||
introducing bugs or a backward incompatibility.
|
introducing bugs or a backward incompatibility.
|
||||||
|
|
||||||
|
The cgi.py module would be deprecated. (XXX A new module or
|
||||||
|
package name hasn't been chosen yet: 'web'? 'cgilib'?)
|
||||||
|
|
||||||
The cgi.py module would be deprecated. (XXX A new module or
|
|
||||||
package name hasn't been chosen yet: 'web'? 'cgilib'?)
|
|
||||||
|
|
||||||
Minor Changes to Existing Modules
|
Minor Changes to Existing Modules
|
||||||
|
=================================
|
||||||
|
|
||||||
This section lists details of minor changes to existing modules.
|
This section lists details of minor changes to existing modules.
|
||||||
These changes should have relatively small implementations, and
|
These changes should have relatively small implementations, and
|
||||||
have little risk of introducing incompatibilities with previous
|
have little risk of introducing incompatibilities with previous
|
||||||
versions.
|
versions.
|
||||||
|
|
||||||
|
|
||||||
Rejected Changes
|
Rejected Changes
|
||||||
|
================
|
||||||
|
|
||||||
The changes listed in this section were proposed for Python 2.1,
|
The changes listed in this section were proposed for Python 2.1,
|
||||||
but were rejected as unsuitable. For each rejected change, a
|
but were rejected as unsuitable. For each rejected change, a
|
||||||
rationale is given describing why the change was deemed
|
rationale is given describing why the change was deemed
|
||||||
inappropriate.
|
inappropriate.
|
||||||
|
|
||||||
* An HTML generation module is not part of this PEP. Several such
|
* An HTML generation module is not part of this PEP. Several such
|
||||||
modules exist, ranging from HTMLgen's purely programming
|
modules exist, ranging from HTMLgen's purely programming
|
||||||
interface to ASP-inspired simple templating to DTML's complex
|
interface to ASP-inspired simple templating to DTML's complex
|
||||||
templating. There's no indication of which templating module to
|
templating. There's no indication of which templating module to
|
||||||
enshrine in the standard library, and that probably means that
|
enshrine in the standard library, and that probably means that
|
||||||
no module should be so chosen.
|
no module should be so chosen.
|
||||||
|
|
||||||
|
* cgi.py: Allowing a combination of query data and POST data.
|
||||||
|
This doesn't seem to be standard at all, and therefore is
|
||||||
|
dubious practice.
|
||||||
|
|
||||||
* cgi.py: Allowing a combination of query data and POST data.
|
|
||||||
This doesn't seem to be standard at all, and therefore is
|
|
||||||
dubious practice.
|
|
||||||
|
|
||||||
Proposed Interface
|
Proposed Interface
|
||||||
|
==================
|
||||||
|
|
||||||
XXX open issues: naming convention (studlycaps or
|
XXX open issues: naming convention (studlycaps or
|
||||||
underline-separated?); need to look at the cgi.parse*() functions
|
underline-separated?); need to look at the ``cgi.parse*()`` functions
|
||||||
and see if they can be simplified, too.
|
and see if they can be simplified, too.
|
||||||
|
|
||||||
|
Parsing functions: carry over most of the ``parse*`` functions from
|
||||||
|
cgi.py
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
Parsing functions: carry over most of the parse* functions from
|
|
||||||
cgi.py
|
|
||||||
|
|
||||||
# The Response class borrows most of its methods from Zope's
|
# The Response class borrows most of its methods from Zope's
|
||||||
# HTTPResponse class.
|
# HTTPResponse class.
|
||||||
|
|
||||||
class Response:
|
class Response:
|
||||||
"""
|
"""
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -116,57 +129,57 @@ Proposed Interface
|
||||||
headers: dictionary of response headers
|
headers: dictionary of response headers
|
||||||
body: string containing the body of the HTTP response
|
body: string containing the body of the HTTP response
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, status=200, headers={}, body=""):
|
def __init__(self, status=200, headers={}, body=""):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setStatus(self, status, reason=None):
|
def setStatus(self, status, reason=None):
|
||||||
"Set the numeric HTTP response code"
|
"Set the numeric HTTP response code"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setHeader(self, name, value):
|
def setHeader(self, name, value):
|
||||||
"Set an HTTP header"
|
"Set an HTTP header"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setBody(self, body):
|
def setBody(self, body):
|
||||||
"Set the body of the response"
|
"Set the body of the response"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setCookie(self, name, value,
|
def setCookie(self, name, value,
|
||||||
path = '/',
|
path = '/',
|
||||||
comment = None,
|
comment = None,
|
||||||
domain = None,
|
domain = None,
|
||||||
max-age = None,
|
max-age = None,
|
||||||
expires = None,
|
expires = None,
|
||||||
secure = 0
|
secure = 0
|
||||||
):
|
):
|
||||||
"Set a cookie"
|
"Set a cookie"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def expireCookie(self, name):
|
def expireCookie(self, name):
|
||||||
"Remove a cookie from the user"
|
"Remove a cookie from the user"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def redirect(self, url):
|
def redirect(self, url):
|
||||||
"Redirect the browser to another URL"
|
"Redirect the browser to another URL"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"Convert entire response to a string"
|
"Convert entire response to a string"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def dump(self):
|
def dump(self):
|
||||||
"Return a string representation useful for debugging"
|
"Return a string representation useful for debugging"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# XXX methods for specific classes of error:serverError,
|
# XXX methods for specific classes of error:serverError,
|
||||||
# badRequest, etc.?
|
# badRequest, etc.?
|
||||||
|
|
||||||
|
|
||||||
class Request:
|
class Request:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Attributes:
|
Attributes:
|
||||||
|
|
||||||
XXX should these be dictionaries, or dictionary-like objects?
|
XXX should these be dictionaries, or dictionary-like objects?
|
||||||
.headers : dictionary containing HTTP headers
|
.headers : dictionary containing HTTP headers
|
||||||
|
@ -174,31 +187,31 @@ Proposed Interface
|
||||||
.fields : data from the form
|
.fields : data from the form
|
||||||
.env : environment dictionary
|
.env : environment dictionary
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, environ=os.environ, stdin=sys.stdin,
|
def __init__(self, environ=os.environ, stdin=sys.stdin,
|
||||||
keep_blank_values=1, strict_parsing=0):
|
keep_blank_values=1, strict_parsing=0):
|
||||||
"""Initialize the request object, using the provided environment
|
"""Initialize the request object, using the provided environment
|
||||||
and standard input."""
|
and standard input."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Should people just use the dictionaries directly?
|
# Should people just use the dictionaries directly?
|
||||||
def getHeader(self, name, default=None):
|
def getHeader(self, name, default=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getCookie(self, name, default=None):
|
def getCookie(self, name, default=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getField(self, name, default=None):
|
def getField(self, name, default=None):
|
||||||
"Return field's value as a string (even if it's an uploaded file)"
|
"Return field's value as a string (even if it's an uploaded file)"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getUploadedFile(self, name):
|
def getUploadedFile(self, name):
|
||||||
"""Returns a file object that can be read to obtain the contents
|
"""Returns a file object that can be read to obtain the contents
|
||||||
of an uploaded file. XXX should this report an error if the
|
of an uploaded file. XXX should this report an error if the
|
||||||
field isn't actually an uploaded file? Or should it wrap
|
field isn't actually an uploaded file? Or should it wrap
|
||||||
a StringIO around simple fields for consistency?
|
a StringIO around simple fields for consistency?
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def getURL(self, n=0, query_string=0):
|
def getURL(self, n=0, query_string=0):
|
||||||
"""Return the URL of the current request, chopping off 'n' path
|
"""Return the URL of the current request, chopping off 'n' path
|
||||||
components from the right. Eg. if the URL is
|
components from the right. Eg. if the URL is
|
||||||
|
@ -209,48 +222,50 @@ Proposed Interface
|
||||||
|
|
||||||
def getBaseURL(self, n=0):
|
def getBaseURL(self, n=0):
|
||||||
"""Return the base URL of the current request, adding 'n' path
|
"""Return the base URL of the current request, adding 'n' path
|
||||||
components to the end to recreate more of the whole URL.
|
components to the end to recreate more of the whole URL.
|
||||||
|
|
||||||
Eg. if the request URL is
|
Eg. if the request URL is
|
||||||
"http://foo.com/q/bar/baz/qux", n=0 would return
|
"http://foo.com/q/bar/baz/qux", n=0 would return
|
||||||
"http://foo.com/", and n=2 "http://foo.com/q/bar".
|
"http://foo.com/", and n=2 "http://foo.com/q/bar".
|
||||||
|
|
||||||
Returned URL does not include the query string, if any.
|
Returned URL does not include the query string, if any.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def dump(self):
|
def dump(self):
|
||||||
"String representation suitable for debugging output"
|
"String representation suitable for debugging output"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Possibilities? I don't know if these are worth doing in the
|
# Possibilities? I don't know if these are worth doing in the
|
||||||
# basic objects.
|
# basic objects.
|
||||||
def getBrowser(self):
|
def getBrowser(self):
|
||||||
"Returns Mozilla/IE/Lynx/Opera/whatever"
|
"Returns Mozilla/IE/Lynx/Opera/whatever"
|
||||||
|
|
||||||
def isSecure(self):
|
def isSecure(self):
|
||||||
"Return true if this is an SSLified request"
|
"Return true if this is an SSLified request"
|
||||||
|
|
||||||
|
|
||||||
# Module-level function
|
|
||||||
|
# Module-level function
|
||||||
def wrapper(func, logfile=sys.stderr):
|
def wrapper(func, logfile=sys.stderr):
|
||||||
"""
|
"""
|
||||||
Calls the function 'func', passing it the arguments
|
Calls the function 'func', passing it the arguments
|
||||||
(request, response, logfile). Exceptions are trapped and
|
(request, response, logfile). Exceptions are trapped and
|
||||||
sent to the file 'logfile'.
|
sent to the file 'logfile'.
|
||||||
"""
|
"""
|
||||||
# This wrapper will detect if it's being called from the command-line,
|
# This wrapper will detect if it's being called from the command-line,
|
||||||
# and if so, it will run in a debugging mode; name=value pairs
|
# and if so, it will run in a debugging mode; name=value pairs
|
||||||
# can be entered on standard input to set field values.
|
# can be entered on standard input to set field values.
|
||||||
# (XXX how to do file uploads in this syntax?)
|
# (XXX how to do file uploads in this syntax?)
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
This document has been placed in the public domain.
|
|
||||||
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
End:
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
345
pep-0224.txt
345
pep-0224.txt
|
@ -5,253 +5,272 @@ Last-Modified: $Date$
|
||||||
Author: mal@lemburg.com (Marc-André Lemburg)
|
Author: mal@lemburg.com (Marc-André Lemburg)
|
||||||
Status: Rejected
|
Status: Rejected
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 23-Aug-2000
|
Created: 23-Aug-2000
|
||||||
Python-Version: 2.1
|
Python-Version: 2.1
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
This PEP describes the "attribute docstring" proposal for Python
|
This PEP describes the "attribute docstring" proposal for Python
|
||||||
2.0. This PEP tracks the status and ownership of this feature.
|
2.0. This PEP tracks the status and ownership of this feature.
|
||||||
It contains a description of the feature and outlines changes
|
It contains a description of the feature and outlines changes
|
||||||
necessary to support the feature. The CVS revision history of
|
necessary to support the feature. The CVS revision history of
|
||||||
this file contains the definitive historical record.
|
this file contains the definitive historical record.
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
=========
|
||||||
|
|
||||||
This PEP proposes a small addition to the way Python currently
|
This PEP proposes a small addition to the way Python currently
|
||||||
handles docstrings embedded in Python code.
|
handles docstrings embedded in Python code.
|
||||||
|
|
||||||
Python currently only handles the case of docstrings which appear
|
Python currently only handles the case of docstrings which appear
|
||||||
directly after a class definition, a function definition or as
|
directly after a class definition, a function definition or as
|
||||||
first string literal in a module. The string literals are added
|
first string literal in a module. The string literals are added
|
||||||
to the objects in question under the __doc__ attribute and are
|
to the objects in question under the ``__doc__`` attribute and are
|
||||||
from then on available for introspection tools which can extract
|
from then on available for introspection tools which can extract
|
||||||
the contained information for help, debugging and documentation
|
the contained information for help, debugging and documentation
|
||||||
purposes.
|
purposes.
|
||||||
|
|
||||||
Docstrings appearing in locations other than the ones mentioned
|
Docstrings appearing in locations other than the ones mentioned
|
||||||
are simply ignored and don't result in any code generation.
|
are simply ignored and don't result in any code generation.
|
||||||
|
|
||||||
Here is an example:
|
Here is an example::
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
"class C doc-string"
|
"class C doc-string"
|
||||||
|
|
||||||
a = 1
|
a = 1
|
||||||
"attribute C.a doc-string (1)"
|
"attribute C.a doc-string (1)"
|
||||||
|
|
||||||
b = 2
|
b = 2
|
||||||
"attribute C.b doc-string (2)"
|
"attribute C.b doc-string (2)"
|
||||||
|
|
||||||
The docstrings (1) and (2) are currently being ignored by the
|
The docstrings (1) and (2) are currently being ignored by the
|
||||||
Python byte code compiler, but could obviously be put to good use
|
Python byte code compiler, but could obviously be put to good use
|
||||||
for documenting the named assignments that precede them.
|
for documenting the named assignments that precede them.
|
||||||
|
|
||||||
This PEP proposes to also make use of these cases by proposing
|
|
||||||
semantics for adding their content to the objects in which they
|
|
||||||
appear under new generated attribute names.
|
|
||||||
|
|
||||||
The original idea behind this approach which also inspired the
|
This PEP proposes to also make use of these cases by proposing
|
||||||
above example was to enable inline documentation of class
|
semantics for adding their content to the objects in which they
|
||||||
attributes, which can currently only be documented in the class's
|
appear under new generated attribute names.
|
||||||
docstring or using comments which are not available for
|
|
||||||
introspection.
|
The original idea behind this approach which also inspired the
|
||||||
|
above example was to enable inline documentation of class
|
||||||
|
attributes, which can currently only be documented in the class's
|
||||||
|
docstring or using comments which are not available for
|
||||||
|
introspection.
|
||||||
|
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
==============
|
||||||
|
|
||||||
Docstrings are handled by the byte code compiler as expressions.
|
Docstrings are handled by the byte code compiler as expressions.
|
||||||
The current implementation special cases the few locations
|
The current implementation special cases the few locations
|
||||||
mentioned above to make use of these expressions, but otherwise
|
mentioned above to make use of these expressions, but otherwise
|
||||||
ignores the strings completely.
|
ignores the strings completely.
|
||||||
|
|
||||||
To enable use of these docstrings for documenting named
|
To enable use of these docstrings for documenting named
|
||||||
assignments (which is the natural way of defining e.g. class
|
assignments (which is the natural way of defining e.g. class
|
||||||
attributes), the compiler will have to keep track of the last
|
attributes), the compiler will have to keep track of the last
|
||||||
assigned name and then use this name to assign the content of the
|
assigned name and then use this name to assign the content of the
|
||||||
docstring to an attribute of the containing object by means of
|
docstring to an attribute of the containing object by means of
|
||||||
storing it in as a constant which is then added to the object's
|
storing it in as a constant which is then added to the object's
|
||||||
namespace during object construction time.
|
namespace during object construction time.
|
||||||
|
|
||||||
In order to preserve features like inheritance and hiding of
|
In order to preserve features like inheritance and hiding of
|
||||||
Python's special attributes (ones with leading and trailing double
|
Python's special attributes (ones with leading and trailing double
|
||||||
underscores), a special name mangling has to be applied which
|
underscores), a special name mangling has to be applied which
|
||||||
uniquely identifies the docstring as belonging to the name
|
uniquely identifies the docstring as belonging to the name
|
||||||
assignment and allows finding the docstring later on by inspecting
|
assignment and allows finding the docstring later on by inspecting
|
||||||
the namespace.
|
the namespace.
|
||||||
|
|
||||||
The following name mangling scheme achieves all of the above:
|
The following name mangling scheme achieves all of the above::
|
||||||
|
|
||||||
__doc_<attributename>__
|
__doc_<attributename>__
|
||||||
|
|
||||||
To keep track of the last assigned name, the byte code compiler
|
To keep track of the last assigned name, the byte code compiler
|
||||||
stores this name in a variable of the compiling structure. This
|
stores this name in a variable of the compiling structure. This
|
||||||
variable defaults to NULL. When it sees a docstring, it then
|
variable defaults to NULL. When it sees a docstring, it then
|
||||||
checks the variable and uses the name as basis for the above name
|
checks the variable and uses the name as basis for the above name
|
||||||
mangling to produce an implicit assignment of the docstring to the
|
mangling to produce an implicit assignment of the docstring to the
|
||||||
mangled name. It then resets the variable to NULL to avoid
|
mangled name. It then resets the variable to NULL to avoid
|
||||||
duplicate assignments.
|
duplicate assignments.
|
||||||
|
|
||||||
If the variable does not point to a name (i.e. is NULL), no
|
If the variable does not point to a name (i.e. is NULL), no
|
||||||
assignments are made. These will continue to be ignored like
|
assignments are made. These will continue to be ignored like
|
||||||
before. All classical docstrings fall under this case, so no
|
before. All classical docstrings fall under this case, so no
|
||||||
duplicate assignments are done.
|
duplicate assignments are done.
|
||||||
|
|
||||||
In the above example this would result in the following new class
|
In the above example this would result in the following new class
|
||||||
attributes to be created:
|
attributes to be created::
|
||||||
|
|
||||||
C.__doc_a__ == "attribute C.a doc-string (1)"
|
C.__doc_a__ == "attribute C.a doc-string (1)"
|
||||||
C.__doc_b__ == "attribute C.b doc-string (2)"
|
C.__doc_b__ == "attribute C.b doc-string (2)"
|
||||||
|
|
||||||
A patch to the current CVS version of Python 2.0 which implements
|
A patch to the current CVS version of Python 2.0 which implements
|
||||||
the above is available on SourceForge at [1].
|
the above is available on SourceForge at [1]_.
|
||||||
|
|
||||||
|
|
||||||
Caveats of the Implementation
|
Caveats of the Implementation
|
||||||
|
=============================
|
||||||
Since the implementation does not reset the compiling structure
|
|
||||||
variable when processing a non-expression, e.g. a function
|
|
||||||
definition, the last assigned name remains active until either the
|
|
||||||
next assignment or the next occurrence of a docstring.
|
|
||||||
|
|
||||||
This can lead to cases where the docstring and assignment may be
|
Since the implementation does not reset the compiling structure
|
||||||
separated by other expressions:
|
variable when processing a non-expression, e.g. a function
|
||||||
|
definition, the last assigned name remains active until either the
|
||||||
|
next assignment or the next occurrence of a docstring.
|
||||||
|
|
||||||
class C:
|
This can lead to cases where the docstring and assignment may be
|
||||||
"C doc string"
|
separated by other expressions::
|
||||||
|
|
||||||
b = 2
|
class C:
|
||||||
|
"C doc string"
|
||||||
|
|
||||||
def x(self):
|
b = 2
|
||||||
"C.x doc string"
|
|
||||||
y = 3
|
|
||||||
return 1
|
|
||||||
|
|
||||||
"b's doc string"
|
def x(self):
|
||||||
|
"C.x doc string"
|
||||||
|
y = 3
|
||||||
|
return 1
|
||||||
|
|
||||||
Since the definition of method "x" currently does not reset the
|
"b's doc string"
|
||||||
used assignment name variable, it is still valid when the compiler
|
|
||||||
reaches the docstring "b's doc string" and thus assigns the string
|
|
||||||
to __doc_b__.
|
|
||||||
|
|
||||||
A possible solution to this problem would be resetting the name
|
Since the definition of method "x" currently does not reset the
|
||||||
variable for all non-expression nodes in the compiler.
|
used assignment name variable, it is still valid when the compiler
|
||||||
|
reaches the docstring "b's doc string" and thus assigns the string
|
||||||
|
to ``__doc_b__``.
|
||||||
|
|
||||||
|
A possible solution to this problem would be resetting the name
|
||||||
|
variable for all non-expression nodes in the compiler.
|
||||||
|
|
||||||
|
|
||||||
Possible Problems
|
Possible Problems
|
||||||
|
=================
|
||||||
|
|
||||||
Even though highly unlikely, attribute docstrings could get
|
Even though highly unlikely, attribute docstrings could get
|
||||||
accidentally concatenated to the attribute's value:
|
accidentally concatenated to the attribute's value::
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
x = "text" \
|
x = "text" \
|
||||||
"x's docstring"
|
"x's docstring"
|
||||||
|
|
||||||
The trailing slash would cause the Python compiler to concatenate
|
The trailing slash would cause the Python compiler to concatenate
|
||||||
the attribute value and the docstring.
|
the attribute value and the docstring.
|
||||||
|
|
||||||
A modern syntax highlighting editor would easily make this
|
A modern syntax highlighting editor would easily make this
|
||||||
accident visible, though, and by simply inserting emtpy lines
|
accident visible, though, and by simply inserting emtpy lines
|
||||||
between the attribute definition and the docstring you can avoid
|
between the attribute definition and the docstring you can avoid
|
||||||
the possible concatenation completely, so the problem is
|
the possible concatenation completely, so the problem is
|
||||||
negligible.
|
negligible.
|
||||||
|
|
||||||
Another possible problem is that of using triple quoted strings as
|
Another possible problem is that of using triple quoted strings as
|
||||||
a way to uncomment parts of your code.
|
a way to uncomment parts of your code.
|
||||||
|
|
||||||
If there happens to be an assignment just before the start of the
|
If there happens to be an assignment just before the start of the
|
||||||
comment string, then the compiler will treat the comment as
|
comment string, then the compiler will treat the comment as
|
||||||
docstring attribute and apply the above logic to it.
|
docstring attribute and apply the above logic to it.
|
||||||
|
|
||||||
Besides generating a docstring for an otherwise undocumented
|
Besides generating a docstring for an otherwise undocumented
|
||||||
attribute there is no breakage.
|
attribute there is no breakage.
|
||||||
|
|
||||||
|
|
||||||
Comments from our BDFL
|
Comments from our BDFL
|
||||||
|
======================
|
||||||
|
|
||||||
Early comments on the PEP from Guido:
|
Early comments on the PEP from Guido:
|
||||||
|
|
||||||
I "kinda" like the idea of having attribute docstrings (meaning
|
I "kinda" like the idea of having attribute docstrings (meaning
|
||||||
it's not of great importance to me) but there are two things I
|
it's not of great importance to me) but there are two things I
|
||||||
don't like in your current proposal:
|
don't like in your current proposal:
|
||||||
|
|
||||||
1. The syntax you propose is too ambiguous: as you say,
|
1. The syntax you propose is too ambiguous: as you say,
|
||||||
stand-alone string literal are used for other purposes and could
|
stand-alone string literal are used for other purposes and could
|
||||||
suddenly become attribute docstrings.
|
suddenly become attribute docstrings.
|
||||||
|
|
||||||
2. I don't like the access method either (__doc_<attrname>__).
|
2. I don't like the access method either (``__doc_<attrname>__``).
|
||||||
|
|
||||||
The author's reply:
|
The author's reply
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
> 1. The syntax you propose is too ambiguous: as you say, stand-alone
|
> 1. The syntax you propose is too ambiguous: as you say, stand-alone
|
||||||
> string literal are used for other purposes and could suddenly
|
> string literal are used for other purposes and could suddenly
|
||||||
> become attribute docstrings.
|
> become attribute docstrings.
|
||||||
|
|
||||||
This can be fixed by introducing some extra checks in the
|
|
||||||
compiler to reset the "doc attribute" flag in the compiler
|
|
||||||
struct.
|
|
||||||
|
|
||||||
> 2. I don't like the access method either (__doc_<attrname>__).
|
This can be fixed by introducing some extra checks in the
|
||||||
|
compiler to reset the "doc attribute" flag in the compiler
|
||||||
|
struct.
|
||||||
|
|
||||||
Any other name will do. It will only have to match these
|
::
|
||||||
criteria:
|
|
||||||
|
|
||||||
* must start with two underscores (to match __doc__)
|
> 2. I don't like the access method either (``__doc_<attrname>__``).
|
||||||
* must be extractable using some form of inspection (e.g. by using
|
|
||||||
a naming convention which includes some fixed name part)
|
|
||||||
* must be compatible with class inheritance (i.e. should be
|
|
||||||
stored as attribute)
|
|
||||||
|
|
||||||
Later on in March, Guido pronounced on this PEP in March 2001 (on
|
Any other name will do. It will only have to match these
|
||||||
python-dev). Here are his reasons for rejection mentioned in
|
criteria:
|
||||||
private mail to the author of this PEP:
|
|
||||||
|
|
||||||
...
|
* must start with two underscores (to match ``__doc__``)
|
||||||
|
* must be extractable using some form of inspection (e.g. by using
|
||||||
|
a naming convention which includes some fixed name part)
|
||||||
|
* must be compatible with class inheritance (i.e. should be
|
||||||
|
stored as attribute)
|
||||||
|
|
||||||
It might be useful, but I really hate the proposed syntax.
|
Later on in March, Guido pronounced on this PEP in March 2001 (on
|
||||||
|
python-dev). Here are his reasons for rejection mentioned in
|
||||||
|
private mail to the author of this PEP:
|
||||||
|
|
||||||
a = 1
|
...
|
||||||
"foo bar"
|
|
||||||
b = 1
|
|
||||||
|
|
||||||
I really have no way to know whether "foo bar" is a docstring
|
It might be useful, but I really hate the proposed syntax.
|
||||||
for a or for b.
|
|
||||||
|
|
||||||
...
|
::
|
||||||
|
|
||||||
You can use this convention:
|
|
||||||
|
|
||||||
a = 1
|
a = 1
|
||||||
__doc_a__ = "doc string for a"
|
"foo bar"
|
||||||
|
b = 1
|
||||||
|
|
||||||
This makes it available at runtime.
|
I really have no way to know whether "foo bar" is a docstring
|
||||||
|
for a or for b.
|
||||||
|
|
||||||
> Are you completely opposed to adding attribute documentation
|
...
|
||||||
> to Python or is it just the way the implementation works ? I
|
|
||||||
> find the syntax proposed in the PEP very intuitive and many
|
You can use this convention::
|
||||||
> other users on c.l.p and in private emails have supported it
|
|
||||||
> at the time I wrote the PEP.
|
a = 1
|
||||||
|
__doc_a__ = "doc string for a"
|
||||||
|
|
||||||
|
This makes it available at runtime.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
> Are you completely opposed to adding attribute documentation
|
||||||
|
> to Python or is it just the way the implementation works ? I
|
||||||
|
> find the syntax proposed in the PEP very intuitive and many
|
||||||
|
> other users on c.l.p and in private emails have supported it
|
||||||
|
> at the time I wrote the PEP.
|
||||||
|
|
||||||
|
It's not the implementation, it's the syntax. It doesn't
|
||||||
|
convey a clear enough coupling between the variable and the
|
||||||
|
doc string.
|
||||||
|
|
||||||
It's not the implementation, it's the syntax. It doesn't
|
|
||||||
convey a clear enough coupling between the variable and the
|
|
||||||
doc string.
|
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the Public Domain.
|
This document has been placed in the Public Domain.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
[1] http://sourceforge.net/patch/?func=detailpatch&patch_id=101264&group_id=5470
|
.. [1] http://sourceforge.net/patch/?func=detailpatch&patch_id=101264&group_id=5470
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
End:
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
133
pep-0281.txt
133
pep-0281.txt
|
@ -5,56 +5,62 @@ Last-Modified: $Date$
|
||||||
Author: magnus@hetland.org (Magnus Lie Hetland)
|
Author: magnus@hetland.org (Magnus Lie Hetland)
|
||||||
Status: Rejected
|
Status: Rejected
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 11-Feb-2002
|
Created: 11-Feb-2002
|
||||||
Python-Version: 2.3
|
Python-Version: 2.3
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
|
This PEP describes yet another way of exposing the loop counter in
|
||||||
|
for-loops. It basically proposes that the functionality of the
|
||||||
|
function ``indices()`` from PEP 212 [1]_ be included in the existing
|
||||||
|
functions ``range()`` and ``xrange()``.
|
||||||
|
|
||||||
This PEP describes yet another way of exposing the loop counter in
|
|
||||||
for-loops. It basically proposes that the functionality of the
|
|
||||||
function indices() from PEP 212 [1] be included in the existing
|
|
||||||
functions range() and xrange().
|
|
||||||
|
|
||||||
Pronouncement
|
Pronouncement
|
||||||
|
=============
|
||||||
|
|
||||||
In commenting on PEP 279's enumerate() function, this PEP's author
|
In commenting on PEP 279's ``enumerate()`` function, this PEP's author
|
||||||
offered, "I'm quite happy to have it make PEP 281 obsolete."
|
offered, "I'm quite happy to have it make PEP 281 obsolete."
|
||||||
Subsequently, PEP 279 was accepted into Python 2.3.
|
Subsequently, PEP 279 was accepted into Python 2.3.
|
||||||
|
|
||||||
On 17 June 2005, the BDFL concurred with it being obsolete and
|
On 17 June 2005, the BDFL concurred with it being obsolete and
|
||||||
hereby rejected the PEP. For the record, he found some of the
|
hereby rejected the PEP. For the record, he found some of the
|
||||||
examples to somewhat jarring in appearance:
|
examples to somewhat jarring in appearance::
|
||||||
|
|
||||||
>>> range(range(5), range(10), range(2))
|
>>> range(range(5), range(10), range(2))
|
||||||
[5, 7, 9]
|
[5, 7, 9]
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
Motivation
|
||||||
|
==========
|
||||||
|
|
||||||
It is often desirable to loop over the indices of a sequence. PEP
|
It is often desirable to loop over the indices of a sequence. PEP
|
||||||
212 describes several ways of doing this, including adding a
|
212 describes several ways of doing this, including adding a
|
||||||
built-in function called indices, conceptually defined as
|
built-in function called indices, conceptually defined as::
|
||||||
|
|
||||||
def indices(sequence):
|
def indices(sequence):
|
||||||
return range(len(sequence))
|
return range(len(sequence))
|
||||||
|
|
||||||
On the assumption that adding functionality to an existing built-in
|
On the assumption that adding functionality to an existing built-in
|
||||||
function may be less intrusive than adding a new built-in function,
|
function may be less intrusive than adding a new built-in function,
|
||||||
this PEP proposes adding this functionality to the existing
|
this PEP proposes adding this functionality to the existing
|
||||||
functions range() and xrange().
|
functions ``range()`` and ``xrange()``.
|
||||||
|
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
|
=============
|
||||||
|
|
||||||
It is proposed that all three arguments to the built-in functions
|
It is proposed that all three arguments to the built-in functions
|
||||||
range() and xrange() are allowed to be objects with a length
|
``range()`` and ``xrange()`` are allowed to be objects with a length
|
||||||
(i.e. objects implementing the __len__ method). If an argument
|
(i.e. objects implementing the ``__len__`` method). If an argument
|
||||||
cannot be interpreted as an integer (i.e. it has no __int__
|
cannot be interpreted as an integer (i.e. it has no ``__int__``
|
||||||
method), its length will be used instead.
|
method), its length will be used instead.
|
||||||
|
|
||||||
Examples:
|
Examples::
|
||||||
|
|
||||||
>>> range(range(10))
|
>>> range(range(10))
|
||||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
@ -74,18 +80,19 @@ Specification
|
||||||
|
|
||||||
|
|
||||||
Alternatives
|
Alternatives
|
||||||
|
============
|
||||||
|
|
||||||
A natural alternative to the above specification is allowing
|
A natural alternative to the above specification is allowing
|
||||||
xrange() to access its arguments in a lazy manner. Thus, instead
|
``xrange()`` to access its arguments in a lazy manner. Thus, instead
|
||||||
of using their length explicitly, xrange can return one index for
|
of using their length explicitly, ``xrange`` can return one index for
|
||||||
each element of the stop argument until the end is reached. A
|
each element of the stop argument until the end is reached. A
|
||||||
similar lazy treatment makes little sense for the start and step
|
similar lazy treatment makes little sense for the start and step
|
||||||
arguments since their length must be calculated before iteration
|
arguments since their length must be calculated before iteration
|
||||||
can begin. (Actually, the length of the step argument isn't needed
|
can begin. (Actually, the length of the step argument isn't needed
|
||||||
until the second element is returned.)
|
until the second element is returned.)
|
||||||
|
|
||||||
A pseudo-implementation (using only the stop argument, and assuming
|
A pseudo-implementation (using only the stop argument, and assuming
|
||||||
that it is iterable) is:
|
that it is iterable) is::
|
||||||
|
|
||||||
def xrange(stop):
|
def xrange(stop):
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -93,26 +100,26 @@ Alternatives
|
||||||
yield i
|
yield i
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
Testing whether to use int() or lazy iteration could be done by
|
Testing whether to use ``int()`` or lazy iteration could be done by
|
||||||
checking for an __iter__ attribute. (This example assumes the
|
checking for an ``__iter__`` attribute. (This example assumes the
|
||||||
presence of generators, but could easily have been implemented as a
|
presence of generators, but could easily have been implemented as a
|
||||||
plain iterator object.)
|
plain iterator object.)
|
||||||
|
|
||||||
It may be questionable whether this feature is truly useful, since
|
It may be questionable whether this feature is truly useful, since
|
||||||
one would not be able to access the elements of the iterable object
|
one would not be able to access the elements of the iterable object
|
||||||
inside the for loop through indexing.
|
inside the for loop through indexing.
|
||||||
|
|
||||||
Example:
|
Example::
|
||||||
|
|
||||||
# Printing the numbers of the lines of a file:
|
# Printing the numbers of the lines of a file:
|
||||||
for num in range(file):
|
for num in range(file):
|
||||||
print num # The line itself is not accessible
|
print num # The line itself is not accessible
|
||||||
|
|
||||||
A more controversial alternative (to deal with this) would be to
|
A more controversial alternative (to deal with this) would be to
|
||||||
let range() behave like the function irange() of PEP 212 when
|
let ``range()`` behave like the function ``irange()`` of PEP 212 when
|
||||||
supplied with a sequence.
|
supplied with a sequence.
|
||||||
|
|
||||||
Example:
|
Example::
|
||||||
|
|
||||||
>>> range(5)
|
>>> range(5)
|
||||||
[0, 1, 2, 3, 4]
|
[0, 1, 2, 3, 4]
|
||||||
|
@ -121,27 +128,31 @@ Alternatives
|
||||||
|
|
||||||
|
|
||||||
Backwards Compatibility
|
Backwards Compatibility
|
||||||
|
=======================
|
||||||
|
|
||||||
The proposal could cause backwards incompatibilities if arguments
|
The proposal could cause backwards incompatibilities if arguments
|
||||||
are used which implement both __int__ and __len__ (or __iter__ in
|
are used which implement both ``__int__`` and ``__len__`` (or ``__iter__`` in
|
||||||
the case of lazy iteration with xrange). The author does not
|
the case of lazy iteration with ``xrange``). The author does not
|
||||||
believe that this is a significant problem.
|
believe that this is a significant problem.
|
||||||
|
|
||||||
|
|
||||||
References and Footnotes
|
References and Footnotes
|
||||||
|
========================
|
||||||
|
|
||||||
[1] PEP 212, Loop Counter Iteration
|
.. [1] PEP 212, Loop Counter Iteration
|
||||||
http://www.python.org/dev/peps/pep-0212/
|
http://www.python.org/dev/peps/pep-0212/
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
fill-column: 70
|
indent-tabs-mode: nil
|
||||||
End:
|
fill-column: 70
|
||||||
|
End:
|
||||||
|
|
381
pep-0284.txt
381
pep-0284.txt
|
@ -3,270 +3,285 @@ Title: Integer for-loops
|
||||||
Version: $Revision$
|
Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: David Eppstein <eppstein@ics.uci.edu>,
|
Author: David Eppstein <eppstein@ics.uci.edu>,
|
||||||
Greg Ewing <greg.ewing@canterbury.ac.nz>
|
Greg Ewing <greg.ewing@canterbury.ac.nz>
|
||||||
Status: Rejected
|
Status: Rejected
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 1-Mar-2002
|
Created: 1-Mar-2002
|
||||||
Python-Version: 2.3
|
Python-Version: 2.3
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
This PEP proposes to simplify iteration over intervals of
|
This PEP proposes to simplify iteration over intervals of
|
||||||
integers, by extending the range of expressions allowed after a
|
integers, by extending the range of expressions allowed after a
|
||||||
"for" keyword to allow three-way comparisons such as
|
"for" keyword to allow three-way comparisons such as::
|
||||||
|
|
||||||
for lower <= var < upper:
|
for lower <= var < upper:
|
||||||
|
|
||||||
in place of the current
|
in place of the current::
|
||||||
|
|
||||||
for item in list:
|
for item in list:
|
||||||
|
|
||||||
|
syntax. The resulting loop or list iteration will loop over all
|
||||||
|
values of var that make the comparison true, starting from the
|
||||||
|
left endpoint of the given interval.
|
||||||
|
|
||||||
syntax. The resulting loop or list iteration will loop over all
|
|
||||||
values of var that make the comparison true, starting from the
|
|
||||||
left endpoint of the given interval.
|
|
||||||
|
|
||||||
Pronouncement
|
Pronouncement
|
||||||
|
=============
|
||||||
|
|
||||||
|
This PEP is rejected. There were a number of fixable issues with
|
||||||
|
the proposal (see the fixups listed in Raymond Hettinger's
|
||||||
|
python-dev post on 18 June 2005 [5]_). However, even with the fixups the
|
||||||
|
proposal did not garner support. Specifically, Guido did not buy
|
||||||
|
the premise that the ``range()`` format needed fixing, "The whole point
|
||||||
|
(15 years ago) of ``range()`` was to *avoid* needing syntax to specify a
|
||||||
|
loop over numbers. I think it's worked out well and there's nothing
|
||||||
|
that needs to be fixed (except ``range()`` needs to become an iterator,
|
||||||
|
which it will in Python 3.0)."
|
||||||
|
|
||||||
This PEP is rejected. There were a number of fixable issues with
|
|
||||||
the proposal (see the fixups listed in Raymond Hettinger's
|
|
||||||
python-dev post on 18 June 2005). However, even with the fixups the
|
|
||||||
proposal did not garner support. Specifically, Guido did not buy
|
|
||||||
the premise that the range() format needed fixing, "The whole point
|
|
||||||
(15 years ago) of range() was to *avoid* needing syntax to specify a
|
|
||||||
loop over numbers. I think it's worked out well and there's nothing
|
|
||||||
that needs to be fixed (except range() needs to become an iterator,
|
|
||||||
which it will in Python 3.0)."
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
=========
|
||||||
|
|
||||||
One of the most common uses of for-loops in Python is to iterate
|
One of the most common uses of for-loops in Python is to iterate
|
||||||
over an interval of integers. Python provides functions range()
|
over an interval of integers. Python provides functions ``range()``
|
||||||
and xrange() to generate lists and iterators for such intervals,
|
and ``xrange()`` to generate lists and iterators for such intervals,
|
||||||
which work best for the most frequent case: half-open intervals
|
which work best for the most frequent case: half-open intervals
|
||||||
increasing from zero. However, the range() syntax is more awkward
|
increasing from zero. However, the ``range()`` syntax is more awkward
|
||||||
for open or closed intervals, and lacks symmetry when reversing
|
for open or closed intervals, and lacks symmetry when reversing
|
||||||
the order of iteration. In addition, the call to an unfamiliar
|
the order of iteration. In addition, the call to an unfamiliar
|
||||||
function makes it difficult for newcomers to Python to understand
|
function makes it difficult for newcomers to Python to understand
|
||||||
code that uses range() or xrange().
|
code that uses ``range()`` or ``xrange()``.
|
||||||
|
|
||||||
The perceived lack of a natural, intuitive integer iteration
|
The perceived lack of a natural, intuitive integer iteration
|
||||||
syntax has led to heated debate on python-list, and spawned at
|
syntax has led to heated debate on python-list, and spawned at
|
||||||
least four PEPs before this one. PEP 204 [1] (rejected) proposed
|
least four PEPs before this one. PEP 204 [1]_ (rejected) proposed
|
||||||
to re-use Python's slice syntax for integer ranges, leading to a
|
to re-use Python's slice syntax for integer ranges, leading to a
|
||||||
terser syntax but not solving the readability problem of
|
terser syntax but not solving the readability problem of
|
||||||
multi-argument range(). PEP 212 [2] (deferred) proposed several
|
multi-argument ``range()``. PEP 212 [2]_ (deferred) proposed several
|
||||||
syntaxes for directly converting a list to a sequence of integer
|
syntaxes for directly converting a list to a sequence of integer
|
||||||
indices, in place of the current idiom
|
indices, in place of the current idiom::
|
||||||
|
|
||||||
range(len(list))
|
range(len(list))
|
||||||
|
|
||||||
for such conversion, and PEP 281 [3] proposes to simplify the same
|
for such conversion, and PEP 281 [3]_ proposes to simplify the same
|
||||||
idiom by allowing it to be written as
|
idiom by allowing it to be written as::
|
||||||
|
|
||||||
range(list).
|
range(list).
|
||||||
|
|
||||||
PEP 276 [4] proposes to allow automatic conversion of integers to
|
PEP 276 [4]_ proposes to allow automatic conversion of integers to
|
||||||
iterators, simplifying the most common half-open case but not
|
iterators, simplifying the most common half-open case but not
|
||||||
addressing the complexities of other types of interval.
|
addressing the complexities of other types of interval.
|
||||||
Additional alternatives have been discussed on python-list.
|
Additional alternatives have been discussed on python-list.
|
||||||
|
|
||||||
The solution described here is to allow a three-way comparison
|
The solution described here is to allow a three-way comparison
|
||||||
after a "for" keyword, both in the context of a for-loop and of a
|
after a "for" keyword, both in the context of a for-loop and of a
|
||||||
list comprehension:
|
list comprehension::
|
||||||
|
|
||||||
for lower <= var < upper:
|
for lower <= var < upper:
|
||||||
|
|
||||||
This would cause iteration over an interval of consecutive
|
This would cause iteration over an interval of consecutive
|
||||||
integers, beginning at the left bound in the comparison and ending
|
integers, beginning at the left bound in the comparison and ending
|
||||||
at the right bound. The exact comparison operations used would
|
at the right bound. The exact comparison operations used would
|
||||||
determine whether the interval is open or closed at either end and
|
determine whether the interval is open or closed at either end and
|
||||||
whether the integers are considered in ascending or descending
|
whether the integers are considered in ascending or descending
|
||||||
order.
|
order.
|
||||||
|
|
||||||
This syntax closely matches standard mathematical notation, so is
|
This syntax closely matches standard mathematical notation, so is
|
||||||
likely to be more familiar to Python novices than the current
|
likely to be more familiar to Python novices than the current
|
||||||
range() syntax. Open and closed interval endpoints are equally
|
``range()`` syntax. Open and closed interval endpoints are equally
|
||||||
easy to express, and the reversal of an integer interval can be
|
easy to express, and the reversal of an integer interval can be
|
||||||
formed simply by swapping the two endpoints and reversing the
|
formed simply by swapping the two endpoints and reversing the
|
||||||
comparisons. In addition, the semantics of such a loop would
|
comparisons. In addition, the semantics of such a loop would
|
||||||
closely resemble one way of interpreting the existing Python
|
closely resemble one way of interpreting the existing Python
|
||||||
for-loops:
|
for-loops::
|
||||||
|
|
||||||
for item in list
|
for item in list
|
||||||
|
|
||||||
iterates over exactly those values of item that cause the
|
iterates over exactly those values of item that cause the
|
||||||
expression
|
expression::
|
||||||
|
|
||||||
item in list
|
item in list
|
||||||
|
|
||||||
to be true. Similarly, the new format
|
to be true. Similarly, the new format::
|
||||||
|
|
||||||
for lower <= var < upper:
|
for lower <= var < upper:
|
||||||
|
|
||||||
would iterate over exactly those integer values of var that cause
|
would iterate over exactly those integer values of var that cause
|
||||||
the expression
|
the expression::
|
||||||
|
|
||||||
lower <= var < upper
|
lower <= var < upper
|
||||||
|
|
||||||
to be true.
|
to be true.
|
||||||
|
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
|
=============
|
||||||
|
|
||||||
We propose to extend the syntax of a for statement, currently
|
We propose to extend the syntax of a for statement, currently::
|
||||||
|
|
||||||
for_stmt: "for" target_list "in" expression_list ":" suite
|
for_stmt: "for" target_list "in" expression_list ":" suite
|
||||||
["else" ":" suite]
|
["else" ":" suite]
|
||||||
|
|
||||||
as described below:
|
as described below::
|
||||||
|
|
||||||
for_stmt: "for" for_test ":" suite ["else" ":" suite]
|
for_stmt: "for" for_test ":" suite ["else" ":" suite]
|
||||||
for_test: target_list "in" expression_list |
|
for_test: target_list "in" expression_list |
|
||||||
or_expr less_comp or_expr less_comp or_expr |
|
or_expr less_comp or_expr less_comp or_expr |
|
||||||
or_expr greater_comp or_expr greater_comp or_expr
|
or_expr greater_comp or_expr greater_comp or_expr
|
||||||
less_comp: "<" | "<="
|
less_comp: "<" | "<="
|
||||||
greater_comp: ">" | ">="
|
greater_comp: ">" | ">="
|
||||||
|
|
||||||
Similarly, we propose to extend the syntax of list comprehensions,
|
Similarly, we propose to extend the syntax of list comprehensions,
|
||||||
currently
|
currently::
|
||||||
|
|
||||||
list_for: "for" expression_list "in" testlist [list_iter]
|
list_for: "for" expression_list "in" testlist [list_iter]
|
||||||
|
|
||||||
by replacing it with:
|
by replacing it with::
|
||||||
|
|
||||||
list_for: "for" for_test [list_iter]
|
list_for: "for" for_test [list_iter]
|
||||||
|
|
||||||
In all cases the expression formed by for_test would be subject to
|
In all cases the expression formed by for_test would be subject to
|
||||||
the same precedence rules as comparisons in expressions. The two
|
the same precedence rules as comparisons in expressions. The two
|
||||||
comp_operators in a for_test must be required to be both of
|
comp_operators in a for_test must be required to be both of
|
||||||
similar types, unlike chained comparisons in expressions which do
|
similar types, unlike chained comparisons in expressions which do
|
||||||
not have such a restriction.
|
not have such a restriction.
|
||||||
|
|
||||||
We refer to the two or_expr's occurring on the left and right
|
We refer to the two or_expr's occurring on the left and right
|
||||||
sides of the for-loop syntax as the bounds of the loop, and the
|
sides of the for-loop syntax as the bounds of the loop, and the
|
||||||
middle or_expr as the variable of the loop. When a for-loop using
|
middle or_expr as the variable of the loop. When a for-loop using
|
||||||
the new syntax is executed, the expressions for both bounds will
|
the new syntax is executed, the expressions for both bounds will
|
||||||
be evaluated, and an iterator object created that iterates through
|
be evaluated, and an iterator object created that iterates through
|
||||||
all integers between the two bounds according to the comparison
|
all integers between the two bounds according to the comparison
|
||||||
operations used. The iterator will begin with an integer equal or
|
operations used. The iterator will begin with an integer equal or
|
||||||
near to the left bound, and then step through the remaining
|
near to the left bound, and then step through the remaining
|
||||||
integers with a step size of +1 or -1 if the comparison operation
|
integers with a step size of +1 or -1 if the comparison operation
|
||||||
is in the set described by less_comp or greater_comp respectively.
|
is in the set described by less_comp or greater_comp respectively.
|
||||||
The execution will then proceed as if the expression had been
|
The execution will then proceed as if the expression had been::
|
||||||
|
|
||||||
for variable in iterator
|
for variable in iterator
|
||||||
|
|
||||||
where "variable" refers to the variable of the loop and "iterator"
|
where "variable" refers to the variable of the loop and "iterator"
|
||||||
refers to the iterator created for the given integer interval.
|
refers to the iterator created for the given integer interval.
|
||||||
|
|
||||||
The values taken by the loop variable in an integer for-loop may
|
The values taken by the loop variable in an integer for-loop may
|
||||||
be either plain integers or long integers, according to the
|
be either plain integers or long integers, according to the
|
||||||
magnitude of the bounds. Both bounds of an integer for-loop must
|
magnitude of the bounds. Both bounds of an integer for-loop must
|
||||||
evaluate to a real numeric type (integer, long, or float). Any
|
evaluate to a real numeric type (integer, long, or float). Any
|
||||||
other value will cause the for-loop statement to raise a TypeError
|
other value will cause the for-loop statement to raise a ``TypeError``
|
||||||
exception.
|
exception.
|
||||||
|
|
||||||
|
|
||||||
Issues
|
Issues
|
||||||
|
======
|
||||||
|
|
||||||
The following issues were raised in discussion of this and related
|
The following issues were raised in discussion of this and related
|
||||||
proposals on the Python list.
|
proposals on the Python list.
|
||||||
|
|
||||||
- Should the right bound be evaluated once, or every time through
|
- Should the right bound be evaluated once, or every time through
|
||||||
the loop? Clearly, it only makes sense to evaluate the left
|
the loop? Clearly, it only makes sense to evaluate the left
|
||||||
bound once. For reasons of consistency and efficiency, we have
|
bound once. For reasons of consistency and efficiency, we have
|
||||||
chosen the same convention for the right bound.
|
chosen the same convention for the right bound.
|
||||||
|
|
||||||
- Although the new syntax considerably simplifies integer
|
- Although the new syntax considerably simplifies integer
|
||||||
for-loops, list comprehensions using the new syntax are not as
|
for-loops, list comprehensions using the new syntax are not as
|
||||||
simple. We feel that this is appropriate since for-loops are
|
simple. We feel that this is appropriate since for-loops are
|
||||||
more frequent than comprehensions.
|
more frequent than comprehensions.
|
||||||
|
|
||||||
- The proposal does not allow access to integer iterator objects
|
- The proposal does not allow access to integer iterator objects
|
||||||
such as would be created by xrange. True, but we see this as a
|
such as would be created by ``xrange``. True, but we see this as a
|
||||||
shortcoming in the general list-comprehension syntax, beyond the
|
shortcoming in the general list-comprehension syntax, beyond the
|
||||||
scope of this proposal. In addition, xrange() will still be
|
scope of this proposal. In addition, ``xrange()`` will still be
|
||||||
available.
|
available.
|
||||||
|
|
||||||
- The proposal does not allow increments other than 1 and -1.
|
- The proposal does not allow increments other than 1 and -1.
|
||||||
More general arithmetic progressions would need to be created by
|
More general arithmetic progressions would need to be created by
|
||||||
range() or xrange(), or by a list comprehension syntax such as
|
``range()`` or ``xrange()``, or by a list comprehension syntax such as::
|
||||||
|
|
||||||
[2*x for 0 <= x <= 100]
|
[2*x for 0 <= x <= 100]
|
||||||
|
|
||||||
- The position of the loop variable in the middle of a three-way
|
- The position of the loop variable in the middle of a three-way
|
||||||
comparison is not as apparent as the variable in the present
|
comparison is not as apparent as the variable in the present::
|
||||||
|
|
||||||
for item in list
|
for item in list
|
||||||
|
|
||||||
syntax, leading to a possible loss of readability. We feel that
|
syntax, leading to a possible loss of readability. We feel that
|
||||||
this loss is outweighed by the increase in readability from a
|
this loss is outweighed by the increase in readability from a
|
||||||
natural integer iteration syntax.
|
natural integer iteration syntax.
|
||||||
|
|
||||||
- To some extent, this PEP addresses the same issues as PEP 276
|
- To some extent, this PEP addresses the same issues as PEP 276
|
||||||
[4]. We feel that the two PEPs are not in conflict since PEP
|
[4]_. We feel that the two PEPs are not in conflict since PEP
|
||||||
276 is primarily concerned with half-open ranges starting in 0
|
276 is primarily concerned with half-open ranges starting in 0
|
||||||
(the easy case of range()) while this PEP is primarily concerned
|
(the easy case of ``range()``) while this PEP is primarily concerned
|
||||||
with simplifying all other cases. However, if this PEP is
|
with simplifying all other cases. However, if this PEP is
|
||||||
approved, its new simpler syntax for integer loops could to some
|
approved, its new simpler syntax for integer loops could to some
|
||||||
extent reduce the motivation for PEP 276.
|
extent reduce the motivation for PEP 276.
|
||||||
|
|
||||||
- It is not clear whether it makes sense to allow floating point
|
- It is not clear whether it makes sense to allow floating point
|
||||||
bounds for an integer loop: if a float represents an inexact
|
bounds for an integer loop: if a float represents an inexact
|
||||||
value, how can it be used to determine an exact sequence of
|
value, how can it be used to determine an exact sequence of
|
||||||
integers? On the other hand, disallowing float bounds would
|
integers? On the other hand, disallowing float bounds would
|
||||||
make it difficult to use floor() and ceiling() in integer
|
make it difficult to use ``floor()`` and ``ceiling()`` in integer
|
||||||
for-loops, as it is difficult to use them now with range(). We
|
for-loops, as it is difficult to use them now with ``range()``. We
|
||||||
have erred on the side of flexibility, but this may lead to some
|
have erred on the side of flexibility, but this may lead to some
|
||||||
implementation difficulties in determining the smallest and
|
implementation difficulties in determining the smallest and
|
||||||
largest integer values that would cause a given comparison to be
|
largest integer values that would cause a given comparison to be
|
||||||
true.
|
true.
|
||||||
|
|
||||||
- Should types other than int, long, and float be allowed as
|
- Should types other than int, long, and float be allowed as
|
||||||
bounds? Another choice would be to convert all bounds to
|
bounds? Another choice would be to convert all bounds to
|
||||||
integers by int(), and allow as bounds anything that can be so
|
integers by ``int()``, and allow as bounds anything that can be so
|
||||||
converted instead of just floats. However, this would change
|
converted instead of just floats. However, this would change
|
||||||
the semantics: 0.3 <= x is not the same as int(0.3) <= x, and it
|
the semantics: ``0.3 <= x`` is not the same as ``int(0.3) <= x``, and it
|
||||||
would be confusing for a loop with 0.3 as lower bound to start
|
would be confusing for a loop with 0.3 as lower bound to start
|
||||||
at zero. Also, in general int(f) can be very far from f.
|
at zero. Also, in general ``int(f)`` can be very far from ``f``.
|
||||||
|
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
==============
|
||||||
|
|
||||||
An implementation is not available at this time. Implementation
|
An implementation is not available at this time. Implementation
|
||||||
is not expected to pose any great difficulties: the new syntax
|
is not expected to pose any great difficulties: the new syntax
|
||||||
could, if necessary, be recognized by parsing a general expression
|
could, if necessary, be recognized by parsing a general expression
|
||||||
after each "for" keyword and testing whether the top level
|
after each "for" keyword and testing whether the top level
|
||||||
operation of the expression is "in" or a three-way comparison.
|
operation of the expression is "in" or a three-way comparison.
|
||||||
The Python compiler would convert any instance of the new syntax
|
The Python compiler would convert any instance of the new syntax
|
||||||
into a loop over the items in a special iterator object.
|
into a loop over the items in a special iterator object.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
[1] PEP 204, Range Literals
|
.. [1] PEP 204, Range Literals
|
||||||
http://www.python.org/dev/peps/pep-0204/
|
http://www.python.org/dev/peps/pep-0204/
|
||||||
|
|
||||||
[2] PEP 212, Loop Counter Iteration
|
.. [2] PEP 212, Loop Counter Iteration
|
||||||
http://www.python.org/dev/peps/pep-0212/
|
http://www.python.org/dev/peps/pep-0212/
|
||||||
|
|
||||||
[3] PEP 281, Loop Counter Iteration with range and xrange
|
.. [3] PEP 281, Loop Counter Iteration with range and xrange
|
||||||
http://www.python.org/dev/peps/pep-0281/
|
http://www.python.org/dev/peps/pep-0281/
|
||||||
|
|
||||||
[4] PEP 276, Simple Iterator for ints
|
.. [4] PEP 276, Simple Iterator for ints
|
||||||
http://www.python.org/dev/peps/pep-0276/
|
http://www.python.org/dev/peps/pep-0276/
|
||||||
|
|
||||||
|
.. [5] Raymond Hettinger, Propose updating PEP 284 -- Integer for-loops
|
||||||
|
https://mail.python.org/pipermail/python-dev/2005-June/054316.html
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
fill-column: 70
|
indent-tabs-mode: nil
|
||||||
End:
|
fill-column: 70
|
||||||
|
End:
|
||||||
|
|
306
pep-0310.txt
306
pep-0310.txt
|
@ -3,241 +3,259 @@ Title: Reliable Acquisition/Release Pairs
|
||||||
Version: $Revision$
|
Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: Michael Hudson <mwh@python.net>,
|
Author: Michael Hudson <mwh@python.net>,
|
||||||
Paul Moore <p.f.moore@gmail.com>
|
Paul Moore <p.f.moore@gmail.com>
|
||||||
Status: Rejected
|
Status: Rejected
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
Content-Type: text/plain
|
Content-Type: text/x-rst
|
||||||
Created: 18-Dec-2002
|
Created: 18-Dec-2002
|
||||||
Python-Version: 2.4
|
Python-Version: 2.4
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
It would be nice to have a less typing-intense way of writing:
|
It would be nice to have a less typing-intense way of writing::
|
||||||
|
|
||||||
the_lock.acquire()
|
the_lock.acquire()
|
||||||
try:
|
try:
|
||||||
....
|
....
|
||||||
finally:
|
finally:
|
||||||
the_lock.release()
|
the_lock.release()
|
||||||
|
|
||||||
|
This PEP proposes a piece of syntax (a 'with' block) and a
|
||||||
|
"small-i" interface that generalizes the above.
|
||||||
|
|
||||||
This PEP proposes a piece of syntax (a 'with' block) and a
|
|
||||||
"small-i" interface that generalizes the above.
|
|
||||||
|
|
||||||
Pronouncement
|
Pronouncement
|
||||||
|
=============
|
||||||
|
|
||||||
|
This PEP is rejected in favor of PEP 343.
|
||||||
|
|
||||||
This PEP is rejected in favor of PEP 343.
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
=========
|
||||||
|
|
||||||
One of the advantages of Python's exception handling philosophy is
|
One of the advantages of Python's exception handling philosophy is
|
||||||
that it makes it harder to do the "wrong" thing (e.g. failing to
|
that it makes it harder to do the "wrong" thing (e.g. failing to
|
||||||
check the return value of some system call). Currently, this does
|
check the return value of some system call). Currently, this does
|
||||||
not apply to resource cleanup. The current syntax for acquisition
|
not apply to resource cleanup. The current syntax for acquisition
|
||||||
and release of a resource (for example, a lock) is
|
and release of a resource (for example, a lock) is::
|
||||||
|
|
||||||
the_lock.acquire()
|
the_lock.acquire()
|
||||||
try:
|
try:
|
||||||
....
|
....
|
||||||
finally:
|
finally:
|
||||||
the_lock.release()
|
the_lock.release()
|
||||||
|
|
||||||
This syntax separates the acquisition and release by a (possibly
|
This syntax separates the acquisition and release by a (possibly
|
||||||
large) block of code, which makes it difficult to confirm "at a
|
large) block of code, which makes it difficult to confirm "at a
|
||||||
glance" that the code manages the resource correctly. Another
|
glance" that the code manages the resource correctly. Another
|
||||||
common error is to code the "acquire" call within the try block,
|
common error is to code the "acquire" call within the try block,
|
||||||
which incorrectly releases the lock if the acquire fails.
|
which incorrectly releases the lock if the acquire fails.
|
||||||
|
|
||||||
|
|
||||||
Basic Syntax and Semantics
|
Basic Syntax and Semantics
|
||||||
|
==========================
|
||||||
|
|
||||||
The syntax of a 'with' statement is as follows::
|
The syntax of a 'with' statement is as follows::
|
||||||
|
|
||||||
'with' [ var '=' ] expr ':'
|
'with' [ var '=' ] expr ':'
|
||||||
suite
|
suite
|
||||||
|
|
||||||
This statement is defined as being equivalent to the following
|
This statement is defined as being equivalent to the following
|
||||||
sequence of statements:
|
sequence of statements::
|
||||||
|
|
||||||
var = expr
|
var = expr
|
||||||
|
|
||||||
if hasattr(var, "__enter__"):
|
if hasattr(var, "__enter__"):
|
||||||
var.__enter__()
|
var.__enter__()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
suite
|
suite
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
var.__exit__()
|
var.__exit__()
|
||||||
|
|
||||||
(The presence of an __exit__ method is *not* checked like that of
|
(The presence of an ``__exit__`` method is *not* checked like that of
|
||||||
__enter__ to ensure that using inappropriate objects in with:
|
``__enter__`` to ensure that using inappropriate objects in with:
|
||||||
statements gives an error).
|
statements gives an error).
|
||||||
|
|
||||||
If the variable is omitted, an unnamed object is allocated on the
|
If the variable is omitted, an unnamed object is allocated on the
|
||||||
stack. In that case, the suite has no access to the unnamed object.
|
stack. In that case, the suite has no access to the unnamed object.
|
||||||
|
|
||||||
|
|
||||||
Possible Extensions
|
Possible Extensions
|
||||||
|
===================
|
||||||
|
|
||||||
A number of potential extensions to the basic syntax have been
|
A number of potential extensions to the basic syntax have been
|
||||||
discussed on the Python Developers list. None of these extensions
|
discussed on the Python Developers list. None of these extensions
|
||||||
are included in the solution proposed by this PEP. In many cases,
|
are included in the solution proposed by this PEP. In many cases,
|
||||||
the arguments are nearly equally strong in both directions. In
|
the arguments are nearly equally strong in both directions. In
|
||||||
such cases, the PEP has always chosen simplicity, simply because
|
such cases, the PEP has always chosen simplicity, simply because
|
||||||
where extra power is needed, the existing try block is available.
|
where extra power is needed, the existing try block is available.
|
||||||
|
|
||||||
Multiple expressions
|
Multiple expressions
|
||||||
|
--------------------
|
||||||
|
|
||||||
One proposal was for allowing multiple expressions within one
|
One proposal was for allowing multiple expressions within one
|
||||||
'with' statement. The __enter__ methods would be called left to
|
'with' statement. The ``__enter__`` methods would be called left to
|
||||||
right, and the __exit__ methods right to left. The advantage of
|
right, and the ``__exit__`` methods right to left. The advantage of
|
||||||
doing so is that where more than one resource is being managed,
|
doing so is that where more than one resource is being managed,
|
||||||
nested 'with' statements will result in code drifting towards the
|
nested 'with' statements will result in code drifting towards the
|
||||||
right margin. The solution to this problem is the same as for any
|
right margin. The solution to this problem is the same as for any
|
||||||
other deep nesting - factor out some of the code into a separate
|
other deep nesting - factor out some of the code into a separate
|
||||||
function. Furthermore, the question of what happens if one of the
|
function. Furthermore, the question of what happens if one of the
|
||||||
__exit__ methods raises an exception (should the other __exit__
|
``__exit__`` methods raises an exception (should the other ``__exit__``
|
||||||
methods be called?) needs to be addressed.
|
methods be called?) needs to be addressed.
|
||||||
|
|
||||||
Exception handling
|
Exception handling
|
||||||
|
------------------
|
||||||
|
|
||||||
An extension to the protocol to include an optional __except__
|
An extension to the protocol to include an optional ``__except__``
|
||||||
handler, which is called when an exception is raised, and which
|
handler, which is called when an exception is raised, and which
|
||||||
can handle or re-raise the exception, has been suggested. It is
|
can handle or re-raise the exception, has been suggested. It is
|
||||||
not at all clear that the semantics of this extension can be made
|
not at all clear that the semantics of this extension can be made
|
||||||
precise and understandable. For example, should the equivalent
|
precise and understandable. For example, should the equivalent
|
||||||
code be try ... except ... else if an exception handler is
|
code be ``try ... except ... else`` if an exception handler is
|
||||||
defined, and try ... finally if not? How can this be determined
|
defined, and ``try ... finally`` if not? How can this be determined
|
||||||
at compile time, in general? The alternative is to define the
|
at compile time, in general? The alternative is to define the
|
||||||
code as expanding to a try ... except inside a try ... finally.
|
code as expanding to a ``try ... except`` inside a ``try ... finally``.
|
||||||
But this may not do the right thing in real life.
|
But this may not do the right thing in real life.
|
||||||
|
|
||||||
The only use case identified for exception handling is with
|
The only use case identified for exception handling is with
|
||||||
transactional processing (commit on a clean finish, and rollback
|
transactional processing (commit on a clean finish, and rollback
|
||||||
on an exception). This is probably just as easy to handle with a
|
on an exception). This is probably just as easy to handle with a
|
||||||
conventional try ... except ... else block, and so the PEP does
|
conventional ``try ... except ... else`` block, and so the PEP does
|
||||||
not include any support for exception handlers.
|
not include any support for exception handlers.
|
||||||
|
|
||||||
|
|
||||||
Implementation Notes
|
Implementation Notes
|
||||||
|
====================
|
||||||
|
|
||||||
There is a potential race condition in the code specified as
|
There is a potential race condition in the code specified as
|
||||||
equivalent to the with statement. For example, if a
|
equivalent to the with statement. For example, if a
|
||||||
KeyboardInterrupt exception is raised between the completion of
|
``KeyboardInterrupt`` exception is raised between the completion of
|
||||||
the __enter__ method call and the start of the try block, the
|
the ``__enter__`` method call and the start of the try block, the
|
||||||
__exit__ method will not be called. This can lead to resource
|
``__exit__`` method will not be called. This can lead to resource
|
||||||
leaks, or to deadlocks. [XXX Guido has stated that he cares about
|
leaks, or to deadlocks. [XXX Guido has stated that he cares about
|
||||||
this sort of race condition, and intends to write some C magic to
|
this sort of race condition, and intends to write some C magic to
|
||||||
handle them. The implementation of the 'with' statement should
|
handle them. The implementation of the 'with' statement should
|
||||||
copy this.]
|
copy this.]
|
||||||
|
|
||||||
|
|
||||||
Open Issues
|
Open Issues
|
||||||
|
===========
|
||||||
|
|
||||||
Should existing classes (for example, file-like objects and locks)
|
Should existing classes (for example, file-like objects and locks)
|
||||||
gain appropriate __enter__ and __exit__ methods? The obvious
|
gain appropriate ``__enter__`` and ``__exit__`` methods? The obvious
|
||||||
reason in favour is convenience (no adapter needed). The argument
|
reason in favour is convenience (no adapter needed). The argument
|
||||||
against is that if built-in files have this but (say) StringIO
|
against is that if built-in files have this but (say) ``StringIO``
|
||||||
does not, then code that uses "with" on a file object can't be
|
does not, then code that uses "with" on a file object can't be
|
||||||
reused with a StringIO object. So __exit__ = close becomes a part
|
reused with a ``StringIO`` object. So ``__exit__ = close`` becomes a part
|
||||||
of the "file-like object" protocol, which user-defined classes may
|
of the "file-like object" protocol, which user-defined classes may
|
||||||
need to support.
|
need to support.
|
||||||
|
|
||||||
The __enter__ hook may be unnecessary - for many use cases, an
|
The ``__enter__`` hook may be unnecessary - for many use cases, an
|
||||||
adapter class is needed and in that case, the work done by the
|
adapter class is needed and in that case, the work done by the
|
||||||
__enter__ hook can just as easily be done in the __init__ hook.
|
``__enter__`` hook can just as easily be done in the ``__init__`` hook.
|
||||||
|
|
||||||
If a way of controlling object lifetimes explicitly was available,
|
If a way of controlling object lifetimes explicitly was available,
|
||||||
the function of the __exit__ hook could be taken over by the
|
the function of the ``__exit__`` hook could be taken over by the
|
||||||
existing __del__ hook. An email exchange[1] with a proponent of
|
existing ``__del__`` hook. An email exchange [1]_ with a proponent of
|
||||||
this approach left one of the authors even more convinced that
|
this approach left one of the authors even more convinced that
|
||||||
it isn't the right idea...
|
it isn't the right idea...
|
||||||
|
|
||||||
It has been suggested[2] that the "__exit__" method be called
|
It has been suggested [2]_ that the "__exit__" method be called
|
||||||
"close", or that a "close" method should be considered if no
|
"close", or that a "close" method should be considered if no
|
||||||
__exit__ method is found, to increase the "out-of-the-box utility"
|
``__exit__`` method is found, to increase the "out-of-the-box utility"
|
||||||
of the "with ..." construct.
|
of the "with ..." construct.
|
||||||
|
|
||||||
There are some similarities in concept between 'with ...' blocks
|
There are some similarities in concept between 'with ...' blocks
|
||||||
and generators, which have led to proposals that for loops could
|
and generators, which have led to proposals that for loops could
|
||||||
implement the with block functionality[3]. While neat on some
|
implement the with block functionality [3]_. While neat on some
|
||||||
levels, we think that for loops should stick to being loops.
|
levels, we think that for loops should stick to being loops.
|
||||||
|
|
||||||
|
|
||||||
Alternative Ideas
|
Alternative Ideas
|
||||||
|
=================
|
||||||
|
|
||||||
IEXEC: Holger Krekel -- generalised approach with XML-like syntax
|
IEXEC: Holger Krekel -- generalised approach with XML-like syntax
|
||||||
(no URL found...)
|
(no URL found...)
|
||||||
|
|
||||||
Holger has much more far-reaching ideas about "execution monitors"
|
Holger has much more far-reaching ideas about "execution monitors"
|
||||||
that are informed about details of control flow in the monitored
|
that are informed about details of control flow in the monitored
|
||||||
block. While interesting, these ideas could change the language
|
block. While interesting, these ideas could change the language
|
||||||
in deep and subtle ways and as such belong to a different PEP.
|
in deep and subtle ways and as such belong to a different PEP.
|
||||||
|
|
||||||
Any Smalltalk/Ruby anonymous block style extension obviously
|
Any Smalltalk/Ruby anonymous block style extension obviously
|
||||||
subsumes this one.
|
subsumes this one.
|
||||||
|
|
||||||
PEP 319 is in the same area, but did not win support when aired on
|
PEP 319 is in the same area, but did not win support when aired on
|
||||||
python-dev.
|
python-dev.
|
||||||
|
|
||||||
|
|
||||||
Backwards Compatibility
|
Backwards Compatibility
|
||||||
|
=======================
|
||||||
|
|
||||||
This PEP proposes a new keyword, so the __future__ game will need
|
This PEP proposes a new keyword, so the ``__future__`` game will need
|
||||||
to be played.
|
to be played.
|
||||||
|
|
||||||
|
|
||||||
Cost of Adoption
|
Cost of Adoption
|
||||||
|
================
|
||||||
|
|
||||||
Those who claim the language is getting larger and more
|
Those who claim the language is getting larger and more
|
||||||
complicated have something else to complain about. It's something
|
complicated have something else to complain about. It's something
|
||||||
else to teach.
|
else to teach.
|
||||||
|
|
||||||
For the proposal to be useful, many file-like and lock-like
|
For the proposal to be useful, many file-like and lock-like
|
||||||
classes in the standard library and other code will have to have
|
classes in the standard library and other code will have to have::
|
||||||
|
|
||||||
__exit__ = close
|
__exit__ = close
|
||||||
|
|
||||||
or similar added.
|
or similar added.
|
||||||
|
|
||||||
|
|
||||||
Cost of Non-Adoption
|
Cost of Non-Adoption
|
||||||
|
====================
|
||||||
|
|
||||||
Writing correct code continues to be more effort than writing
|
Writing correct code continues to be more effort than writing
|
||||||
incorrect code.
|
incorrect code.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
There are various python-list and python-dev discussions that
|
There are various python-list and python-dev discussions that
|
||||||
could be mentioned here.
|
could be mentioned here.
|
||||||
|
|
||||||
[1] Off-list conversation between Michael Hudson and Bill Soudan
|
.. [1] Off-list conversation between Michael Hudson and Bill Soudan
|
||||||
(made public with permission)
|
(made public with permission)
|
||||||
http://starship.python.net/crew/mwh/pep310/
|
http://starship.python.net/crew/mwh/pep310/
|
||||||
|
|
||||||
[2] Samuele Pedroni on python-dev
|
.. [2] Samuele Pedroni on python-dev
|
||||||
http://mail.python.org/pipermail/python-dev/2003-August/037795.html
|
http://mail.python.org/pipermail/python-dev/2003-August/037795.html
|
||||||
|
|
||||||
[3] Thread on python-dev with subject
|
.. [3] Thread on python-dev with subject
|
||||||
|
|
||||||
[Python-Dev] pre-PEP: Resource-Release Support for Generators
|
.. [Python-Dev] pre-PEP: Resource-Release Support for Generators
|
||||||
|
|
||||||
starting at
|
starting at
|
||||||
|
|
||||||
http://mail.python.org/pipermail/python-dev/2003-August/037803.html
|
http://mail.python.org/pipermail/python-dev/2003-August/037803.html
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
sentence-end-double-space: t
|
indent-tabs-mode: nil
|
||||||
fill-column: 70
|
sentence-end-double-space: t
|
||||||
End:
|
fill-column: 70
|
||||||
|
End:
|
||||||
|
|
Loading…
Reference in New Issue