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