[Python-checkins] r45366 - peps/trunk/pep-0000.txt peps/trunk/pep-0359.txt peps/trunk/pep-3002.txt

david.goodger python-checkins at python.org
Thu Apr 13 15:36:24 CEST 2006


Author: david.goodger
Date: Thu Apr 13 15:36:24 2006
New Revision: 45366

Added:
   peps/trunk/pep-0359.txt   (contents, props changed)
   peps/trunk/pep-3002.txt   (contents, props changed)
Modified:
   peps/trunk/pep-0000.txt
Log:
added PEPs 359 (The "make Statement) and 3002 (Procedure for Backwards-Incompatible Changes) by Steven Bethard

Modified: peps/trunk/pep-0000.txt
==============================================================================
--- peps/trunk/pep-0000.txt	(original)
+++ peps/trunk/pep-0000.txt	Thu Apr 13 15:36:24 2006
@@ -45,6 +45,7 @@
  P   347  Migrating the Python CVS to Subversion       von Löwis
  P  3000  Python 3000                                  GvR
  P  3001  Reviewing and improving stdlib modules       Brandl
+ P  3002  Procedure for Backwards-Incompatible Changes Bethard
  I  3099  Things that will Not Change in Python 3000   Brandl
 
  Other Informational PEPs
@@ -102,6 +103,7 @@
  S   354  Enumerations in Python                       Finney
  S   355  Path - Object oriented filesystem paths      Lindqvist
  S   358  The "bytes" Object                           Schemenauer
+ S   359  The "make" Statement                         Bethard
  S   754  IEEE 754 Floating Point Special Values       Warnes
 
  Finished PEPs (done, implemented in Subversion)
@@ -415,10 +417,12 @@
  I   356  Python 2.5 Release Schedule                  Norwitz, et al
  SF  357  Allowing Any Object to be Used for Slicing   Oliphant
  S   358  The "bytes" Object                           Schemenauer
+ S   359  The "make" Statement                         Bethard
  SR  666  Reject Foolish Indentation                   Creighton
  S   754  IEEE 754 Floating Point Special Values       Warnes
  P  3000  Python 3000                                  GvR
  P  3001  Reviewing and improving stdlib modules       Brandl
+ P  3002  Procedure for Backwards-Incompatible Changes Bethard
  I  3099  Things that will Not Change in Python 3000   Brandl
  I  3100  Python 3.0 Plans                             Kuchling, Cannon
 
@@ -449,6 +453,7 @@
     Batista, Facundo         facundo at taniquetil.com.ar
     Baxter, Anthony          anthony at interlink.com.au
     Bellman, Thomas          bellman+pep-divmod at lysator.liu.se
+    Bethard, Steven          steven.bethard at gmail.com
     Brandl, Georg            g.brandl at gmx.net
     Cannon, Brett            brett at python.org
     Carlson, Josiah          jcarlson at uci.edu

Added: peps/trunk/pep-0359.txt
==============================================================================
--- (empty file)
+++ peps/trunk/pep-0359.txt	Thu Apr 13 15:36:24 2006
@@ -0,0 +1,274 @@
+PEP: 359
+Title: The "make" Statement
+Version: $Revision$
+Last-Modified: $Date$
+Author: Steven Bethard <steven.bethard at gmail.com>
+Status: Draft
+Type: Standards Track
+Content-Type: text/x-rst
+Created: 05-Apr-2006
+Python-Version: 2.6
+Post-History: 05-Apr-2006, 06-Apr-2006
+
+
+Abstract
+========
+
+This PEP proposes a generalization of the class-declaration syntax,
+the ``make`` statement.  The proposed syntax and semantics parallel
+the syntax for class definition, and so::
+
+   make <callable> <name> <tuple>:
+       <block>
+
+is translated into the assignment::
+
+   <name> = <callable>("<name>", <tuple>, <namespace>)
+
+where ``<namespace>`` is the dict created by executing ``<block>``.
+The PEP is based on a suggestion [1]_ from Michele Simionato on the
+python-dev list.
+
+
+Motivation
+==========
+
+Class statements provide two nice facilities to Python:
+
+  (1) They are the standard Python means of creating a namespace.  All
+      statements within a class body are executed, and the resulting
+      local name bindings are passed as a dict to the metaclass.
+
+  (2) They encourage DRY (don't repeat yourself) by allowing the class
+      being created to know the name it is being assigned.
+
+Thus in a simple class statement like::
+
+     class C(object):
+         x = 1
+         def foo(self):
+             return 'bar'
+
+the metaclass (``type``) gets called with something like::
+
+    C = type('C', (object,), {'x':1, 'foo':<function foo at ...>})
+
+The class statement is just syntactic sugar for the above assignment
+statement, but clearly a very useful sort of syntactic sugar.  It
+avoids not only the repetition of ``C``, but also simplifies the
+creation of the dict by allowing it to be expressed as a series of
+statements.
+
+Historically, type instances (a.k.a. class objects) have been the only
+objects blessed with this sort of syntactic support.  But other sorts
+of objects could benefit from such support.  For example, property
+objects take three function arguments, but because the property type
+cannot be passed a namespace, these functions, though relevant only to
+the property, must be declared before it and then passed as arguments
+to the property call, e.g.::
+
+    class C(object):
+        ...
+        def get_x(self):
+            ...
+        def set_x(self):
+            ...
+        x = property(get_x, set_x, ...)
+
+There have been a few recipes [2]_ trying to work around this
+behavior, but with the new make statement (and an appropriate
+definition of property), the getter and setter functions can be
+defined in the property's namespace like::
+
+    class C(object):
+        ...
+        make property x:
+            def get(self):
+                ...
+            def set(self):
+                ...
+
+The definition of such a property callable could be as simple as::
+
+    def property(name, args, namespace):
+        fget = namespace.get('get')
+        fset = namespace.get('set')
+        fdel = namespace.get('delete')
+        doc = namespace.get('__doc__')
+        return __builtin__.property(fget, fset, fdel, doc)
+
+Of course, properties are only one of the many possible uses of the
+make statement.  The make statement is useful in essentially any
+situation where a name is associated with a namespace.  So, for
+example, namespaces could be created as simply as::
+
+    make namespace ns:
+        """This creates a namespace named ns with a badger attribute
+        and a spam function"""
+
+        badger = 42
+
+        def spam():
+            ...
+
+And if Python acquires interfaces, given an appropriately defined
+``interface`` callable, the make statement can support interface
+creation through the syntax::
+
+    make interface C(...):
+        ...
+
+This would mean that interface systems like that of Zope would no
+longer have to abuse the class syntax to create proper interface
+instances.
+
+
+Specification
+=============
+
+Python will translate a make statement::
+
+    make <callable> <name> <tuple>:
+        <block>
+
+into the assignment::
+
+    <name> = <callable>("<name>", <tuple>, <namespace>)
+
+where ``<namespace>`` is the dict created by executing ``<block>``.
+The ``<tuple>`` expression is optional; if not present, an empty tuple
+will be assumed.
+
+A patch is available implementing these semantics [3]_.
+
+The make statement introduces a new keyword, ``make``.  Thus in Python
+2.6, the make statement will have to be enabled using ``from
+__future__ import make_statement``.
+
+
+Open Issues
+===========
+
+Does the ``make`` keyword break too much code?  Originally, the make
+statement used the keyword ``create`` (a suggestion due to Nick
+Coghlan).  However, investigations into the standard library [4]_ and
+Zope+Plone code [5]_ revealed that ``create`` would break a lot more
+code, so ``make`` was adopted as the keyword instead.  However, there
+are still a few instances where ``make`` would break code.  Is there a
+better keyword for the statement?
+
+**********
+
+Currently, there are not many functions which have the signature
+``(name, args, kwargs)``.  That means that something like::
+
+    make dict params:
+        x = 1
+        y = 2
+
+is currently impossible because the dict constructor has a different
+signature.  Does this sort of thing need to be supported?  One
+suggestion, by Carl Banks, would be to add a ``__make__`` magic method
+that would be called before ``__call__``.  For types, the ``__make__``
+method would be identical to ``__call__`` (and thus unnecessary), but
+dicts could support the make statement by defining a ``__make__``
+method on the dict type that looks something like::
+
+    def __make__(cls, name, args, kwargs):
+        return cls(**kwargs)
+
+Of course, rather than adding another magic method, the dict type
+could just grow a classmethod something like ``dict.fromblock`` that
+could be used like::
+
+    make dict.fromblock params:
+        x = 1
+        y = 2
+
+
+Optional Extensions
+===================
+
+Remove the make keyword
+-------------------------
+
+It might be possible to remove the make keyword so that such
+statements would begin with the callable being called, e.g.::
+
+    namespace ns:
+        badger = 42
+        def spam():
+            ...
+
+    interface C(...):
+        ...
+
+However, almost all other Python statements begin with a keyword, and
+removing the keyword would make it harder to look up this construct in
+the documentation.  Additionally, this would add some complexity in
+the grammar and so far I (Steven Bethard) have not been able to
+implement the feature without the keyword.
+
+
+Removing __metaclass__ in Python 3000
+-------------------------------------
+
+As a side-effect of its generality, the make statement mostly
+eliminates the need for the ``__metaclass__`` attribute in class
+objects.  Thus in Python 3000, instead of::
+
+   class <name> <bases-tuple>:
+       __metaclass__ = <metaclass>
+       <block>
+
+metaclasses could be supported by using the metaclass as the callable
+in a make statement::
+
+   make <metaclass> <name> <bases-tuple>:
+       <block>
+
+Removing the ``__metaclass__`` hook would simplify the BUILD_CLASS
+opcode a bit.
+
+
+Removing class statements in Python 3000
+----------------------------------------
+
+In the most extreme application of make statements, the class
+statement itself could be deprecated in favor of ``make type``
+statements.
+
+
+References
+==========
+
+.. [1] Michele Simionato's original suggestion
+   (http://mail.python.org/pipermail/python-dev/2005-October/057435.html)
+
+.. [2] Namespace-based property recipe
+   (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442418)
+
+.. [3] Make Statement patch
+   (http://ucsu.colorado.edu/~bethard/py/make_statement.patch)
+
+.. [4] Instances of create in the stdlib
+   (http://mail.python.org/pipermail/python-list/2006-April/335159.html)
+
+.. [5] Instances of create in Zope+Plone
+   (http://mail.python.org/pipermail/python-list/2006-April/335284.html)
+
+
+Copyright
+=========
+
+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
+   coding: utf-8
+   End:

Added: peps/trunk/pep-3002.txt
==============================================================================
--- (empty file)
+++ peps/trunk/pep-3002.txt	Thu Apr 13 15:36:24 2006
@@ -0,0 +1,164 @@
+PEP: 3002
+Title: Procedure for Backwards-Incompatible Changes
+Version: $Revision$
+Last-Modified: $Date$
+Author: Steven Bethard <steven.bethard at gmail.com>
+Status: Draft
+Type: Process
+Content-Type: text/x-rst
+Created: 03-Mar-2006
+Post-History: 03-Mar-2006
+
+
+Abstract
+========
+
+This PEP describes the procedure for changes to Python that are
+backwards-incompatible between the Python 2.X series and Python 3000.
+All such changes must be documented by an appropriate Python 3000 PEP
+and must be accompanied by code that can identify when pieces of
+Python 2.X code may be problematic in Python 3000.
+
+
+Rationale
+=========
+
+Python 3000 will introduce a number of backwards-incompatible changes
+to Python, mainly to streamline the language and to remove some
+previous design mistakes.  But Python 3000 is not intended to be a new
+and completely different language from the Python 2.X series, and it
+is expected that much of the Python user community will make the
+transition to Python 3000 when it becomes available.
+
+To encourage this transition, it is crucial to provide a clear and
+complete guide on how to upgrade Python 2.X code to Python 3000 code.
+Thus, for any backwards-incompatible change, two things are required:
+
+* An official Python Enhancement Proposal (PEP)
+* Code that can identify pieces of Python 2.X code that may be
+  problematic in Python 3000
+
+
+Python Enchancement Proposals
+=============================
+
+Every backwards-incompatible change must be accompanied by a PEP.
+This PEP should follow the usual PEP guidelines and explain the
+purpose and reasoning behind the backwards incompatible change.  In
+addition to the usual PEP sections, all PEPs proposing
+backwards-incompatible changes must include an additional section:
+Compatibility Issues.  This section should describe what is backwards
+incompatible about the proposed change to Python, and the major sorts
+of breakage to be expected.
+
+While PEPs must still be evaluated on a case-by-case basis, a PEP may
+be inappropriate for Python 3000 if its Compatibility Issues section
+implies any of the following:
+
+* Most or all instances of a Python 2.X construct are incorrect in
+  Python 3000, and most or all instances of the Python 3000 construct
+  are incorrect in Python 2.X.
+
+  So for example, changing the meaning of the for-loop else-clause
+  from "executed when the loop was not broken out of" to "executed
+  when the loop had zero iterations" would mean that all Python 2.X
+  for-loop else-clauses would be broken, and there would be no way to
+  use a for-loop else-clause in a Python-3000-appropriate manner.
+  Thus a PEP for such an idea would likely be rejected.
+
+* Many instances of a Python 2.X construct are incorrect in Python
+  3000 and the PEP fails to demonstrate real-world use-cases for the
+  changes.
+
+  Backwards incompatible changes are allowed in Python 3000, but not
+  to excess.  A PEP that proposes backwards-incompatible changes
+  should provide good examples of code that visibly benefits from the
+  changes.
+
+PEP-writing is time-consuming, so when a number of
+backwards-incompatible changes are closely related, they should be
+proposed in the same PEP.  Such PEPs will likely have longer
+Compatibility Issues sections however, since they must now describe
+the sorts of breakage expected from *all* the proposed changes.
+
+
+Identifying Problematic Code
+============================
+
+In addition to the PEP requirement, backwards incompatible changes to
+Python must also be accompanied by code that can identify pieces of
+Python 2.X code that may be problematic in Python 3.0.
+
+This PEP proposes to house this code in tools/scripts/python3warn.py.
+Thus PEPs for backwards incompatible changes should include a patch to
+this file that produces the appropriate warnings.  Code in
+python3warn.py should be written to the latest version of Python 2.X
+(not Python 3000) so that Python 2.X users will be able to run the
+program without having Python 3000 installed.
+
+Currently, it seems too stringent to require that the code in
+python3warn.py identify all changes perfectly.  Thus it is permissable
+if a backwards-incompatible PEP's python3warn.py code produces a
+number of false-positives (warning that a piece of code might be
+invalid in Python 3000 when it's actually still okay).  However,
+false-negatives (not issuing a warning for code that will do the
+wrong thing in Python 3000) should be avoided whenever possible --
+users of python3warn.py should be reasonably confident that they have
+been warned about the vast majority of incompatibilities.
+
+So for example, a PEP proposing that ``dict.items()`` be modified to
+return an iterator instead of a list might add code like the following
+to python3warn.py::
+
+    items_in_for = re.compile(r'for\s+\w+\s+in\s+\w+\.items\(\):')
+    ...
+    for i, line in enumerate(file_lines):
+        ...
+        if '.items()' in line and not items_in_for.search(line):
+            message = 'dict.items() call may expect list at line %i'
+            warnings.warn(message % i)
+
+This would issue a warning any time a ``.items()`` method was called
+and not immediately iterated over in a for-loop.  Clearly this will
+issue a number of false-positive warnings (e.g. ``d2 =
+dict(d.items())``), but the number of false-negative warnings should
+be relatively low.
+
+
+Optional Extensions
+===================
+
+Instead of the python3warn.py script, a branch of Python 3000 could be
+maintained that added warnings at all the appropriate points in the
+code-base.  PEPs proposing backwards-incompatible changes would then
+provide patches to the Python-3000-warn branch instead of to
+python3warn.py.  With such a branch, the warnings issued could be
+near-perfect and Python users could be confident that their code was
+correct Python 3000 code by first running it on the Python-3000-warn
+branch and fixing all the warnings.
+
+At the moment, however, this PEP opts for the weaker measure
+(python3warn.py) as it is expected that maintaining a Python-3000-warn
+branch will be too much of a time drain.
+
+
+References
+==========
+
+TBD
+
+
+Copyright
+=========
+
+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
+   coding: utf-8
+   End:


More information about the Python-checkins mailing list