Convert PEPs 204, 248, 283, 314, 3115 (#215)

This commit is contained in:
Mariatta 2017-02-24 16:07:48 -08:00 committed by GitHub
parent 1e727b0662
commit 73e6ac628e
5 changed files with 1177 additions and 1112 deletions

View File

@ -5,293 +5,304 @@ Last-Modified: $Date$
Author: thomas@python.org (Thomas Wouters)
Status: Rejected
Type: Standards Track
Content-Type: text/x-rst
Created: 14-Jul-2000
Python-Version: 2.0
Post-History:
Introduction
============
This PEP describes the `range literal' proposal for Python 2.0.
This PEP tracks the status and ownership of this feature, slated
for introduction in Python 2.0. It contains a description of the
feature and outlines changes necessary to support the feature.
This PEP summarizes discussions held in mailing list forums, and
provides URLs for further information, where appropriate. The CVS
revision history of this file contains the definitive historical
record.
This PEP describes the "range literal" proposal for Python 2.0.
This PEP tracks the status and ownership of this feature, slated
for introduction in Python 2.0. It contains a description of the
feature and outlines changes necessary to support the feature.
This PEP summarizes discussions held in mailing list forums, and
provides URLs for further information, where appropriate. The CVS
revision history of this file contains the definitive historical
record.
List ranges
===========
Ranges are sequences of numbers of a fixed stepping, often used in
for-loops. The Python for-loop is designed to iterate over a
sequence directly:
>>> l = ['a', 'b', 'c', 'd']
>>> for item in l:
... print item
a
b
c
d
However, this solution is not always prudent. Firstly, problems
arise when altering the sequence in the body of the for-loop,
resulting in the for-loop skipping items. Secondly, it is not
possible to iterate over, say, every second element of the
sequence. And thirdly, it is sometimes necessary to process an
element based on its index, which is not readily available in the
above construct.
For these instances, and others where a range of numbers is
desired, Python provides the `range' builtin function, which
creates a list of numbers. The `range' function takes three
arguments, `start', `end' and `step'. `start' and `step' are
optional, and default to 0 and 1, respectively.
The `range' function creates a list of numbers, starting at
`start', with a step of `step', up to, but not including `end', so
that `range(10)' produces a list that has exactly 10 items, the
numbers 0 through 9.
Using the `range' function, the above example would look like
this:
>>> for i in range(len(l)):
... print l[i]
a
b
c
d
Or, to start at the second element of `l' and processing only
every second element from then on:
>>> for i in range(1, len(l), 2):
... print l[i]
b
d
There are several disadvantages with this approach:
- Clarity of purpose: Adding another function call, possibly with
extra arithmetic to determine the desired length and step of the
list, does not improve readability of the code. Also, it is
possible to `shadow' the builtin `range' function by supplying a
local or global variable with the same name, effectively
replacing it. This may or may not be a desired effect.
- Efficiency: because the `range' function can be overridden, the
Python compiler cannot make assumptions about the for-loop, and
has to maintain a separate loop counter.
- Consistency: There already is a syntax that is used to denote
ranges, as shown below. This syntax uses the exact same
arguments, though all optional, in the exact same way. It seems
logical to extend this syntax to ranges, to form `range
literals'.
Ranges are sequences of numbers of a fixed stepping, often used in
for-loops. The Python for-loop is designed to iterate over a
sequence directly::
>>> l = ['a', 'b', 'c', 'd']
>>> for item in l:
... print item
a
b
c
d
However, this solution is not always prudent. Firstly, problems
arise when altering the sequence in the body of the for-loop,
resulting in the for-loop skipping items. Secondly, it is not
possible to iterate over, say, every second element of the
sequence. And thirdly, it is sometimes necessary to process an
element based on its index, which is not readily available in the
above construct.
For these instances, and others where a range of numbers is
desired, Python provides the ``range`` builtin function, which
creates a list of numbers. The ``range`` function takes three
arguments, ``start``, ``end`` and ``step``. ``start`` and ``step`` are
optional, and default to 0 and 1, respectively.
The ``range`` function creates a list of numbers, starting at
``start``, with a step of ``step``, up to, but not including ``end``, so
that ``range(10)`` produces a list that has exactly 10 items, the
numbers 0 through 9.
Using the ``range`` function, the above example would look like
this::
>>> for i in range(len(l)):
... print l[i]
a
b
c
d
Or, to start at the second element of ``l`` and processing only
every second element from then on::
>>> for i in range(1, len(l), 2):
... print l[i]
b
d
There are several disadvantages with this approach:
- Clarity of purpose: Adding another function call, possibly with
extra arithmetic to determine the desired length and step of the
list, does not improve readability of the code. Also, it is
possible to "shadow" the builtin ``range`` function by supplying a
local or global variable with the same name, effectively
replacing it. This may or may not be a desired effect.
- Efficiency: because the ``range`` function can be overridden, the
Python compiler cannot make assumptions about the for-loop, and
has to maintain a separate loop counter.
- Consistency: There already is a syntax that is used to denote
ranges, as shown below. This syntax uses the exact same
arguments, though all optional, in the exact same way. It seems
logical to extend this syntax to ranges, to form "range
literals".
Slice Indices
=============
In Python, a sequence can be indexed in one of two ways:
retrieving a single item, or retrieving a range of items.
Retrieving a range of items results in a new object of the same
type as the original sequence, containing zero or more items from
the original sequence. This is done using a `range notation':
>>> l[2:4]
['c', 'd']
This range notation consists of zero, one or two indices separated
by a colon. The first index is the `start' index, the second the
`end'. When either is left out, they default to respectively the
start and the end of the sequence.
There is also an extended range notation, which incorporates
`step' as well. Though this notation is not currently supported
by most builtin types, if it were, it would work as follows:
>>> l[1:4:2]
['b', 'd']
In Python, a sequence can be indexed in one of two ways:
retrieving a single item, or retrieving a range of items.
Retrieving a range of items results in a new object of the same
type as the original sequence, containing zero or more items from
the original sequence. This is done using a "range notation"::
The third `argument' to the slice syntax is exactly the same as
the `step' argument to range(). The underlying mechanisms of the
standard, and these extended slices, are sufficiently different
and inconsistent that many classes and extensions outside of
mathematical packages do not implement support for the extended
variant. While this should be resolved, it is beyond the scope of
this PEP.
Extended slices do show, however, that there is already a
perfectly valid and applicable syntax to denote ranges in a way
that solve all of the earlier stated disadvantages of the use of
the range() function:
- It is clearer, more concise syntax, which has already proven to
be both intuitive and easy to learn.
- It is consistent with the other use of ranges in Python
(e.g. slices).
- Because it is built-in syntax, instead of a builtin function, it
cannot be overridden. This means both that a viewer can be
certain about what the code does, and that an optimizer will not
have to worry about range() being `shadowed'.
>>> l[2:4]
['c', 'd']
This range notation consists of zero, one or two indices separated
by a colon. The first index is the ``start`` index, the second the
``end``. When either is left out, they default to respectively the
start and the end of the sequence.
There is also an extended range notation, which incorporates
``step`` as well. Though this notation is not currently supported
by most builtin types, if it were, it would work as follows::
>>> l[1:4:2]
['b', 'd']
The third "argument" to the slice syntax is exactly the same as
the ``step`` argument to ``range()``. The underlying mechanisms of the
standard, and these extended slices, are sufficiently different
and inconsistent that many classes and extensions outside of
mathematical packages do not implement support for the extended
variant. While this should be resolved, it is beyond the scope of
this PEP.
Extended slices do show, however, that there is already a
perfectly valid and applicable syntax to denote ranges in a way
that solve all of the earlier stated disadvantages of the use of
the ``range()`` function:
- It is clearer, more concise syntax, which has already proven to
be both intuitive and easy to learn.
- It is consistent with the other use of ranges in Python
(e.g. slices).
- Because it is built-in syntax, instead of a builtin function, it
cannot be overridden. This means both that a viewer can be
certain about what the code does, and that an optimizer will not
have to worry about ``range()`` being "shadowed".
The Proposed Solution
=====================
The proposed implementation of range-literals combines the syntax
for list literals with the syntax for (extended) slices, to form
range literals:
>>> [1:10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [:5]
[0, 1, 2, 3, 4]
>>> [5:1:-1]
[5, 4, 3, 2]
There is one minor difference between range literals and the slice
syntax: though it is possible to omit all of `start', `end' and
`step' in slices, it does not make sense to omit `end' in range
literals. In slices, `end' would default to the end of the list,
but this has no meaning in range literals.
The proposed implementation of range-literals combines the syntax
for list literals with the syntax for (extended) slices, to form
range literals::
>>> [1:10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [:5]
[0, 1, 2, 3, 4]
>>> [5:1:-1]
[5, 4, 3, 2]
There is one minor difference between range literals and the slice
syntax: though it is possible to omit all of ``start``, ``end`` and
``step`` in slices, it does not make sense to omit ``end`` in range
literals. In slices, ``end`` would default to the end of the list,
but this has no meaning in range literals.
Reference Implementation
========================
The proposed implementation can be found on SourceForge[1]. It
adds a new bytecode, BUILD_RANGE, that takes three arguments from
the stack and builds a list on the bases of those. The list is
pushed back on the stack.
The use of a new bytecode is necessary to be able to build ranges
based on other calculations, whose outcome is not known at compile
time.
The code introduces two new functions to listobject.c, which are
currently hovering between private functions and full-fledged API
calls.
The proposed implementation can be found on SourceForge [1]_. It
adds a new bytecode, ``BUILD_RANGE``, that takes three arguments from
the stack and builds a list on the bases of those. The list is
pushed back on the stack.
PyList_FromRange() builds a list from start, end and step,
returning NULL if an error occurs. Its prototype is:
The use of a new bytecode is necessary to be able to build ranges
based on other calculations, whose outcome is not known at compile
time.
PyObject * PyList_FromRange(long start, long end, long step)
PyList_GetLenOfRange() is a helper function used to determine the
length of a range. Previously, it was a static function in
bltinmodule.c, but is now necessary in both listobject.c and
bltinmodule.c (for xrange). It is made non-static solely to avoid
code duplication. Its prototype is:
The code introduces two new functions to listobject.c, which are
currently hovering between private functions and full-fledged API
calls.
long PyList_GetLenOfRange(long start, long end, long step)
``PyList_FromRange()`` builds a list from start, end and step,
returning NULL if an error occurs. Its prototype is::
PyObject * PyList_FromRange(long start, long end, long step)
``PyList_GetLenOfRange()`` is a helper function used to determine the
length of a range. Previously, it was a static function in
bltinmodule.c, but is now necessary in both listobject.c and
bltinmodule.c (for ``xrange``). It is made non-static solely to avoid
code duplication. Its prototype is::
long PyList_GetLenOfRange(long start, long end, long step)
Open issues
===========
- One possible solution to the discrepancy of requiring the `end'
argument in range literals is to allow the range syntax to
create a `generator', rather than a list, such as the `xrange'
builtin function does. However, a generator would not be a
list, and it would be impossible, for instance, to assign to
items in the generator, or append to it.
- One possible solution to the discrepancy of requiring the ``end``
argument in range literals is to allow the range syntax to
create a "generator", rather than a list, such as the ``xrange``
builtin function does. However, a generator would not be a
list, and it would be impossible, for instance, to assign to
items in the generator, or append to it.
The range syntax could conceivably be extended to include tuples
(i.e. immutable lists), which could then be safely implemented
as generators. This may be a desirable solution, especially for
large number arrays: generators require very little in the way
of storage and initialization, and there is only a small
performance impact in calculating and creating the appropriate
number on request. (TBD: is there any at all? Cursory testing
suggests equal performance even in the case of ranges of length
1)
The range syntax could conceivably be extended to include tuples
(i.e. immutable lists), which could then be safely implemented
as generators. This may be a desirable solution, especially for
large number arrays: generators require very little in the way
of storage and initialization, and there is only a small
performance impact in calculating and creating the appropriate
number on request. (TBD: is there any at all? Cursory testing
suggests equal performance even in the case of ranges of length
1)
However, even if idea was adopted, would it be wise to `special
case' the second argument, making it optional in one instance of
the syntax, and non-optional in other cases ?
However, even if idea was adopted, would it be wise to "special
case" the second argument, making it optional in one instance of
the syntax, and non-optional in other cases ?
- Should it be possible to mix range syntax with normal list
literals, creating a single list? E.g.:
- Should it be possible to mix range syntax with normal list
literals, creating a single list? E.g.::
>>> [5, 6, 1:6, 7, 9]
>>> [5, 6, 1:6, 7, 9]
to create
to create::
[5, 6, 1, 2, 3, 4, 5, 7, 9]
[5, 6, 1, 2, 3, 4, 5, 7, 9]
- How should range literals interact with another proposed new
feature, `list comprehensions'[2]? Specifically, should it be
possible to create lists in list comprehensions? E.g.:
>>> [x:y for x in (1, 2) y in (3, 4)]
- How should range literals interact with another proposed new
feature, "list comprehensions" [2]_? Specifically, should it be
possible to create lists in list comprehensions? E.g.::
Should this example return a single list with multiple ranges:
>>> [x:y for x in (1, 2) y in (3, 4)]
[1, 2, 1, 2, 3, 2, 2, 3]
Should this example return a single list with multiple ranges::
Or a list of lists, like so:
[1, 2, 1, 2, 3, 2, 2, 3]
[[1, 2], [1, 2, 3], [2], [2, 3]]
Or a list of lists, like so::
However, as the syntax and semantics of list comprehensions are
still subject of hot debate, these issues are probably best
addressed by the `list comprehensions' PEP.
[[1, 2], [1, 2, 3], [2]_, [2, 3]]
- Range literals accept objects other than integers: it performs
PyInt_AsLong() on the objects passed in, so as long as the
objects can be coerced into integers, they will be accepted.
The resulting list, however, is always composed of standard
integers.
However, as the syntax and semantics of list comprehensions are
still subject of hot debate, these issues are probably best
addressed by the "list comprehensions" PEP.
Should range literals create a list of the passed-in type? It
might be desirable in the cases of other builtin types, such as
longs and strings:
- Range literals accept objects other than integers: it performs
``PyInt_AsLong()`` on the objects passed in, so as long as the
objects can be coerced into integers, they will be accepted.
The resulting list, however, is always composed of standard
integers.
>>> [ 1L : 2L<<64 : 2<<32L ]
>>> ["a":"z":"b"]
>>> ["a":"z":2]
Should range literals create a list of the passed-in type? It
might be desirable in the cases of other builtin types, such as
longs and strings::
However, this might be too much `magic' to be obvious. It might
also present problems with user-defined classes: even if the
base class can be found and a new instance created, the instance
may require additional arguments to __init__, causing the
creation to fail.
- The PyList_FromRange() and PyList_GetLenOfRange() functions need
to be classified: are they part of the API, or should they be
made private functions?
>>> [ 1L : 2L<<64 : 2<<32L ]
>>> ["a":"z":"b"]
>>> ["a":"z":2]
However, this might be too much "magic" to be obvious. It might
also present problems with user-defined classes: even if the
base class can be found and a new instance created, the instance
may require additional arguments to ``__init__``, causing the
creation to fail.
- The ``PyList_FromRange()`` and ``PyList_GetLenOfRange()`` functions need
to be classified: are they part of the API, or should they be
made private functions?
Rejection
=========
After careful consideration, and a period of meditation, this
proposal has been rejected. The open issues, as well as some
confusion between ranges and slice syntax, raised enough questions
for Guido not to accept it for Python 2.0, and later to reject the
proposal altogether. The new syntax and its intentions were deemed
not obvious enough.
After careful consideration, and a period of meditation, this
proposal has been rejected. The open issues, as well as some
confusion between ranges and slice syntax, raised enough questions
for Guido not to accept it for Python 2.0, and later to reject the
proposal altogether. The new syntax and its intentions were deemed
not obvious enough.
[ TBD: Guido, amend/confirm this, please. Preferably both; this
is a PEP, it should contain *all* the reasons for rejection
and/or reconsideration, for future reference. ]
[ TBD: Guido, amend/confirm this, please. Preferably both; this
is a PEP, it should contain *all* the reasons for rejection
and/or reconsideration, for future reference. ]
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=100902&group_id=5470
[2] PEP 202, List Comprehensions
.. [1] http://sourceforge.net/patch/?func=detailpatch&patch_id=100902&group_id=5470
.. [2] PEP 202, List Comprehensions
Local Variables:
mode: indented-text
indent-tabs-mode: nil
End:
..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
End:

View File

@ -6,321 +6,308 @@ Author: mal@lemburg.com (Marc-André Lemburg)
Discussions-To: db-sig@python.org
Status: Final
Type: Informational
Content-Type: text/x-rst
Created:
Post-History:
Superseded-By: 249
Introduction
============
This API has been defined to encourage similarity between the
Python modules that are used to access databases. By doing this,
we hope to achieve a consistency leading to more easily understood
modules, code that is generally more portable across databases,
and a broader reach of database connectivity from Python.
This interface specification consists of several items:
This API has been defined to encourage similarity between the
Python modules that are used to access databases. By doing this,
we hope to achieve a consistency leading to more easily understood
modules, code that is generally more portable across databases,
and a broader reach of database connectivity from Python.
* Module Interface
* Connection Objects
* Cursor Objects
* DBI Helper Objects
Comments and questions about this specification may be directed to
the SIG on Tabular Databases in Python
(http://www.python.org/sigs/db-sig).
This interface specification consists of several items:
This specification document was last updated on: April 9, 1996.
It will be known as Version 1.0 of this specification.
* Module Interface
* Connection Objects
* Cursor Objects
* DBI Helper Objects
Comments and questions about this specification may be directed to
the SIG on Tabular Databases in Python
(http://www.python.org/sigs/db-sig).
This specification document was last updated on: April 9, 1996.
It will be known as Version 1.0 of this specification.
Module Interface
================
The database interface modules should typically be named with
something terminated by 'db'. Existing examples are: 'oracledb',
'informixdb', and 'pg95db'. These modules should export several
names:
modulename(connection_string)
The database interface modules should typically be named with
something terminated by ``db``. Existing examples are: ``oracledb``,
``informixdb``, and ``pg95db``. These modules should export several
names:
Constructor for creating a connection to the database.
Returns a Connection Object.
error
Exception raised for errors from the database module.
modulename(connection_string)
Constructor for creating a connection to the database.
Returns a Connection Object.
error
Exception raised for errors from the database module.
Connection Objects
==================
Connection Objects should respond to the following methods:
close()
Connection Objects should respond to the following methods:
Close the connection now (rather than whenever __del__ is
called). The connection will be unusable from this point
forward; an exception will be raised if any operation is
attempted with the connection.
commit()
close()
Close the connection now (rather than whenever ``__del__`` is
called). The connection will be unusable from this point
forward; an exception will be raised if any operation is
attempted with the connection.
Commit any pending transaction to the database.
rollback()
commit()
Commit any pending transaction to the database.
Roll the database back to the start of any pending
transaction.
cursor()
rollback()
Roll the database back to the start of any pending
transaction.
Return a new Cursor Object. An exception may be thrown if
the database does not support a cursor concept.
callproc([params])
cursor()
Return a new Cursor Object. An exception may be thrown if
the database does not support a cursor concept.
(Note: this method is not well-defined yet.) Call a
stored database procedure with the given (optional)
parameters. Returns the result of the stored procedure.
(all Cursor Object attributes and methods)
callproc([params])
(Note: this method is not well-defined yet.) Call a
stored database procedure with the given (optional)
parameters. Returns the result of the stored procedure.
(all Cursor Object attributes and methods)
For databases that do not have cursors and for simple
applications that do not require the complexity of a
cursor, a Connection Object should respond to each of the
attributes and methods of the Cursor Object. Databases
that have cursor can implement this by using an implicit,
internal cursor.
For databases that do not have cursors and for simple
applications that do not require the complexity of a
cursor, a Connection Object should respond to each of the
attributes and methods of the Cursor Object. Databases
that have cursor can implement this by using an implicit,
internal cursor.
Cursor Objects
==============
These objects represent a database cursor, which is used to manage
the context of a fetch operation.
Cursor Objects should respond to the following methods and
attributes:
arraysize
These objects represent a database cursor, which is used to manage
the context of a fetch operation.
This read/write attribute specifies the number of rows to
fetch at a time with fetchmany(). This value is also used
when inserting multiple rows at a time (passing a
tuple/list of tuples/lists as the params value to
execute()). This attribute will default to a single row.
Note that the arraysize is optional and is merely provided
for higher performance database interactions.
Implementations should observe it with respect to the
fetchmany() method, but are free to interact with the
database a single row at a time.
description
Cursor Objects should respond to the following methods and
attributes:
This read-only attribute is a tuple of 7-tuples. Each
7-tuple contains information describing each result
column: (name, type_code, display_size, internal_size,
precision, scale, null_ok). This attribute will be None
for operations that do not return rows or if the cursor
has not had an operation invoked via the execute() method
yet.
The 'type_code' is one of the 'dbi' values specified in
the section below.
Note: this is a bit in flux. Generally, the first two
items of the 7-tuple will always be present; the others
may be database specific.
close()
arraysize
This read/write attribute specifies the number of rows to
fetch at a time with ``fetchmany()``. This value is also used
when inserting multiple rows at a time (passing a
tuple/list of tuples/lists as the params value to
``execute()``). This attribute will default to a single row.
Close the cursor now (rather than whenever __del__ is
called). The cursor will be unusable from this point
forward; an exception will be raised if any operation is
attempted with the cursor.
execute(operation [,params])
Note that the arraysize is optional and is merely provided
for higher performance database interactions.
Implementations should observe it with respect to the
``fetchmany()`` method, but are free to interact with the
database a single row at a time.
Execute (prepare) a database operation (query or command).
Parameters may be provided (as a sequence
(e.g. tuple/list)) and will be bound to variables in the
operation. Variables are specified in a database-specific
notation that is based on the index in the parameter tuple
(position-based rather than name-based).
The parameters may also be specified as a sequence of
sequences (e.g. a list of tuples) to insert multiple rows
in a single operation.
A reference to the operation will be retained by the
cursor. If the same operation object is passed in again,
then the cursor can optimize its behavior. This is most
effective for algorithms where the same operation is used,
but different parameters are bound to it (many times).
For maximum efficiency when reusing an operation, it is
best to use the setinputsizes() method to specify the
parameter types and sizes ahead of time. It is legal for
a parameter to not match the predefined information; the
implementation should compensate, possibly with a loss of
efficiency.
Using SQL terminology, these are the possible result
values from the execute() method:
description
This read-only attribute is a tuple of 7-tuples. Each
7-tuple contains information describing each result
column: (name, type_code, display_size, internal_size,
precision, scale, null_ok). This attribute will be None
for operations that do not return rows or if the cursor
has not had an operation invoked via the ``execute()`` method
yet.
If the statement is DDL (e.g. CREATE TABLE), then 1 is
returned.
The 'type_code' is one of the 'dbi' values specified in
the section below.
If the statement is DML (e.g. UPDATE or INSERT), then the
number of rows affected is returned (0 or a positive
integer).
Note: this is a bit in flux. Generally, the first two
items of the 7-tuple will always be present; the others
may be database specific.
If the statement is DQL (e.g. SELECT), None is returned,
indicating that the statement is not really complete until
you use one of the 'fetch' methods.
close()
Close the cursor now (rather than whenever ``__del__`` is
called). The cursor will be unusable from this point
forward; an exception will be raised if any operation is
attempted with the cursor.
fetchone()
execute(operation [,params])
Execute (prepare) a database operation (query or command).
Parameters may be provided (as a sequence
(e.g. tuple/list)) and will be bound to variables in the
operation. Variables are specified in a database-specific
notation that is based on the index in the parameter tuple
(position-based rather than name-based).
Fetch the next row of a query result, returning a single
tuple.
The parameters may also be specified as a sequence of
sequences (e.g. a list of tuples) to insert multiple rows
in a single operation.
fetchmany([size])
A reference to the operation will be retained by the
cursor. If the same operation object is passed in again,
then the cursor can optimize its behavior. This is most
effective for algorithms where the same operation is used,
but different parameters are bound to it (many times).
Fetch the next set of rows of a query result, returning as
a list of tuples. An empty list is returned when no more
rows are available. The number of rows to fetch is
specified by the parameter. If it is None, then the
cursor's arraysize determines the number of rows to be
fetched.
Note there are performance considerations involved with
the size parameter. For optimal performance, it is
usually best to use the arraysize attribute. If the size
parameter is used, then it is best for it to retain the
same value from one fetchmany() call to the next.
fetchall()
For maximum efficiency when reusing an operation, it is
best to use the ``setinputsizes()`` method to specify the
parameter types and sizes ahead of time. It is legal for
a parameter to not match the predefined information; the
implementation should compensate, possibly with a loss of
efficiency.
Fetch all rows of a query result, returning as a list of
tuples. Note that the cursor's arraysize attribute can
affect the performance of this operation.
setinputsizes(sizes)
Using SQL terminology, these are the possible result
values from the ``execute()`` method:
(Note: this method is not well-defined yet.) This can be
used before a call to 'execute()' to predefine memory
areas for the operation's parameters. sizes is specified
as a tuple -- one item for each input parameter. The item
should be a Type object that corresponds to the input that
will be used, or it should be an integer specifying the
maximum length of a string parameter. If the item is
'None', then no predefined memory area will be reserved
for that column (this is useful to avoid predefined areas
for large inputs).
This method would be used before the execute() method is
invoked.
Note that this method is optional and is merely provided
for higher performance database interaction.
Implementations are free to do nothing and users are free
to not use it.
setoutputsize(size [,col])
- If the statement is DDL (e.g. CREATE TABLE), then 1 is
returned.
(Note: this method is not well-defined yet.)
- If the statement is DML (e.g. UPDATE or INSERT), then the
number of rows affected is returned (0 or a positive
integer).
- If the statement is DQL (e.g. SELECT), None is returned,
indicating that the statement is not really complete until
you use one of the 'fetch' methods.
fetchone()
Fetch the next row of a query result, returning a single
tuple.
fetchmany([size])
Fetch the next set of rows of a query result, returning as
a list of tuples. An empty list is returned when no more
rows are available. The number of rows to fetch is
specified by the parameter. If it is None, then the
cursor's arraysize determines the number of rows to be
fetched.
Note there are performance considerations involved with
the size parameter. For optimal performance, it is
usually best to use the arraysize attribute. If the size
parameter is used, then it is best for it to retain the
same value from one ``fetchmany()`` call to the next.
fetchall()
Fetch all rows of a query result, returning as a list of
tuples. Note that the cursor's arraysize attribute can
affect the performance of this operation.
setinputsizes(sizes)
(Note: this method is not well-defined yet.) This can be
used before a call to ``execute()`` to predefine memory
areas for the operation's parameters. sizes is specified
as a tuple -- one item for each input parameter. The item
should be a Type object that corresponds to the input that
will be used, or it should be an integer specifying the
maximum length of a string parameter. If the item is
'None', then no predefined memory area will be reserved
for that column (this is useful to avoid predefined areas
for large inputs).
This method would be used before the ``execute()`` method is
invoked.
Note that this method is optional and is merely provided
for higher performance database interaction.
Implementations are free to do nothing and users are free
to not use it.
setoutputsize(size [,col])
(Note: this method is not well-defined yet.)
Set a column buffer size for fetches of large columns
(e.g. LONG). The column is specified as an index into the
result tuple. Using a column of None will set the default
size for all large columns in the cursor.
This method would be used before the ``execute()`` method is
invoked.
Note that this method is optional and is merely provided
for higher performance database interaction.
Implementations are free to do nothing and users are free
to not use it.
Set a column buffer size for fetches of large columns
(e.g. LONG). The column is specified as an index into the
result tuple. Using a column of None will set the default
size for all large columns in the cursor.
This method would be used before the 'execute()' method is
invoked.
Note that this method is optional and is merely provided
for higher performance database interaction.
Implementations are free to do nothing and users are free
to not use it.
DBI Helper Objects
==================
Many databases need to have the input in a particular format for
binding to an operation's input parameters. For example, if an
input is destined for a DATE column, then it must be bound to the
database in a particular string format. Similar problems exist
for "Row ID" columns or large binary items (e.g. blobs or RAW
columns). This presents problems for Python since the parameters
to the 'execute()' method are untyped. When the database module
sees a Python string object, it doesn't know if it should be bound
as a simple CHAR column, as a raw binary item, or as a DATE.
To overcome this problem, the 'dbi' module was created. This
module specifies some basic database interface types for working
with databases. There are two classes: 'dbiDate' and 'dbiRaw'.
These are simple container classes that wrap up a value. When
passed to the database modules, the module can then detect that
the input parameter is intended as a DATE or a RAW. For symmetry,
the database modules will return DATE and RAW columns as instances
of these classes.
A Cursor Object's 'description' attribute returns information
about each of the result columns of a query. The 'type_code is
defined to be one of five types exported by this module: 'STRING',
'RAW', 'NUMBER', 'DATE', or 'ROWID'.
The module exports the following names:
dbiDate(value)
Many databases need to have the input in a particular format for
binding to an operation's input parameters. For example, if an
input is destined for a DATE column, then it must be bound to the
database in a particular string format. Similar problems exist
for "Row ID" columns or large binary items (e.g. blobs or RAW
columns). This presents problems for Python since the parameters
to the ``execute()`` method are untyped. When the database module
sees a Python string object, it doesn't know if it should be bound
as a simple CHAR column, as a raw binary item, or as a DATE.
This function constructs a 'dbiDate' instance that holds a
date value. The value should be specified as an integer
number of seconds since the "epoch" (e.g. time.time()).
dbiRaw(value)
To overcome this problem, the 'dbi' module was created. This
module specifies some basic database interface types for working
with databases. There are two classes: 'dbiDate' and 'dbiRaw'.
These are simple container classes that wrap up a value. When
passed to the database modules, the module can then detect that
the input parameter is intended as a DATE or a RAW. For symmetry,
the database modules will return DATE and RAW columns as instances
of these classes.
This function constructs a 'dbiRaw' instance that holds a
raw (binary) value. The value should be specified as a
Python string.
A Cursor Object's 'description' attribute returns information
about each of the result columns of a query. The 'type_code is
defined to be one of five types exported by this module: 'STRING',
'RAW', 'NUMBER', 'DATE', or 'ROWID'.
STRING
The module exports the following names:
This object is used to describe columns in a database that
are string-based (e.g. CHAR).
RAW
dbiDate(value)
This function constructs a 'dbiDate' instance that holds a
date value. The value should be specified as an integer
number of seconds since the "epoch" (e.g. ``time.time()``).
This object is used to describe (large) binary columns in
a database (e.g. LONG RAW, blobs).
NUMBER
dbiRaw(value)
This function constructs a 'dbiRaw' instance that holds a
raw (binary) value. The value should be specified as a
Python string.
This object is used to describe numeric columns in a
database.
DATE
STRING
This object is used to describe columns in a database that
are string-based (e.g. CHAR).
This object is used to describe date columns in a
database.
ROWID
RAW
This object is used to describe (large) binary columns in
a database (e.g. LONG RAW, blobs).
NUMBER
This object is used to describe numeric columns in a
database.
DATE
This object is used to describe date columns in a
database.
ROWID
This object is used to describe the "Row ID" column in a
database.
This object is used to describe the "Row ID" column in a
database.
Acknowledgements
================
Many thanks go to Andrew Kuchling who converted the Python
Database API Specification 1.0 from the original HTML format into
the PEP format.
Many thanks go to Andrew Kuchling who converted the Python
Database API Specification 1.0 from the original HTML format into
the PEP format.
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:

View File

@ -5,303 +5,325 @@ Last-Modified: $Date$
Author: Guido van Rossum
Status: Final
Type: Informational
Content-Type: text/x-rst
Created: 27-Feb-2002
Python-Version: 2.3
Post-History: 27-Feb-2002
Abstract
========
This document describes the development and release schedule for
Python 2.3. The schedule primarily concerns itself with PEP-sized
items. Small features may be added up to and including the first
beta release. Bugs may be fixed until the final release.
This document describes the development and release schedule for
Python 2.3. The schedule primarily concerns itself with PEP-sized
items. Small features may be added up to and including the first
beta release. Bugs may be fixed until the final release.
There will be at least two alpha releases, two beta releases, and
one release candidate. Alpha and beta releases will be spaced at
least 4 weeks apart (except if an emergency release must be made
to correct a blunder in the previous release; then the blunder
release does not count). Release candidates will be spaced at
least one week apart (excepting again blunder corrections).
There will be at least two alpha releases, two beta releases, and
one release candidate. Alpha and beta releases will be spaced at
least 4 weeks apart (except if an emergency release must be made
to correct a blunder in the previous release; then the blunder
release does not count). Release candidates will be spaced at
least one week apart (excepting again blunder corrections).
alpha 1 -- 31 Dec 2002
alpha 2 -- 19 Feb 2003
beta 1 -- 25 Apr 2003
beta 2 -- 29 Jun 2003
candidate 1 -- 18 Jul 2003
candidate 2 -- 24 Jul 2003
final -- 29 Jul 2003
=========== ===========
alpha 1 31 Dec 2002
alpha 2 19 Feb 2003
beta 1 25 Apr 2003
beta 2 29 Jun 2003
candidate 1 18 Jul 2003
candidate 2 24 Jul 2003
final 29 Jul 2003
=========== ===========
Release Manager
===============
Barry Warsaw, Jeremy Hylton, Tim Peters
Barry Warsaw, Jeremy Hylton, Tim Peters
Completed features for 2.3
==========================
This list is not complete. See Doc/whatsnew/whatsnew23.tex in CVS
for more, and of course Misc/NEWS for the full list.
This list is not complete. See Doc/whatsnew/whatsnew23.tex in CVS
for more, and of course Misc/NEWS for the full list.
- Tk 8.4 update.
- Tk 8.4 update.
- The bool type and its constants, True and False (PEP 285).
- The bool type and its constants, True and False (PEP 285).
- PyMalloc was greatly enhanced and is enabled by default.
- ``PyMalloc`` was greatly enhanced and is enabled by default.
- Universal newline support (PEP 278).
- Universal newline support (PEP 278).
- PEP 263 Defining Python Source Code Encodings Lemburg
- PEP 263 Defining Python Source Code Encodings, Lemburg
Implemented (at least phase 1, which is all that's planned for
2.3).
Implemented (at least phase 1, which is all that's planned for
2.3).
- Extended slice notation for all built-in sequences. The patch
by Michael Hudson is now all checked in.
- Extended slice notation for all built-in sequences. The patch
by Michael Hudson is now all checked in.
- Speed up list iterations by filling tp_iter and other tweaks.
See http://www.python.org/sf/560736; also done for xrange and
tuples.
- Speed up list iterations by filling ``tp_iter`` and other tweaks.
See http://www.python.org/sf/560736; also done for ``xrange`` and
tuples.
- Timeout sockets. http://www.python.org/sf/555085
- Timeout sockets. http://www.python.org/sf/555085
- Stage B0 of the int/long integration (PEP 237). This means
issuing a FutureWarning about situations where hex or oct
conversions or left shifts returns a different value for an int
than for a long with the same value. The semantics do *not*
change in Python 2.3; that will happen in Python 2.4.
- Stage B0 of the int/long integration (PEP 237). This means
issuing a ``FutureWarning`` about situations where hex or oct
conversions or left shifts returns a different value for an int
than for a long with the same value. The semantics do *not*
change in Python 2.3; that will happen in Python 2.4.
- Nuke SET_LINENO from all code objects (providing a different way
to set debugger breakpoints). This can boost pystone by >5%.
http://www.python.org/sf/587993, now checked in. (Unfortunately
the pystone boost didn't happen. What happened?)
- Nuke ``SET_LINENO`` from all code objects (providing a different way
to set debugger breakpoints). This can boost ``pystone`` by >5%.
http://www.python.org/sf/587993, now checked in. (Unfortunately
the ``pystone`` boost didn't happen. What happened?)
- Write a pymemcompat.h that people can bundle with their
extensions and then use the 2.3 memory interface with all
Pythons in the range 1.5.2 to 2.3. (Michael Hudson checked in
Misc/pymemcompat.h.)
- Write a pymemcompat.h that people can bundle with their
extensions and then use the 2.3 memory interface with all
Pythons in the range 1.5.2 to 2.3. (Michael Hudson checked in
Misc/pymemcompat.h.)
- Add a new concept, "pending deprecation", with associated
warning PendingDeprecationWarning. This warning is normally
suppressed, but can be enabled by a suitable -W option. Only a
few things use this at this time.
- Add a new concept, "pending deprecation", with associated
warning ``PendingDeprecationWarning``. This warning is normally
suppressed, but can be enabled by a suitable ``-W`` option. Only a
few things use this at this time.
- Warn when an extension type's tp_compare returns anything except
-1, 0 or 1. http://www.python.org/sf/472523
- Warn when an extension type's ``tp_compare`` returns anything except
-1, 0 or 1. http://www.python.org/sf/472523
- Warn for assignment to None (in various forms).
- Warn for assignment to None (in various forms).
- PEP 218 Adding a Built-In Set Object Type Wilson
- PEP 218 Adding a Built-In Set Object Type, Wilson
Alex Martelli contributed a new version of Greg Wilson's
prototype, and I've reworked that quite a bit. It's in the
standard library now as the module "sets", although some details
may still change until the first beta release. (There are no
plans to make this a built-in type, for now.)
Alex Martelli contributed a new version of Greg Wilson's
prototype, and I've reworked that quite a bit. It's in the
standard library now as the module "sets", although some details
may still change until the first beta release. (There are no
plans to make this a built-in type, for now.)
- PEP 293 Codec error handling callbacks Dörwald
- PEP 293 Codec error handling callbacks, Dörwald
Fully implemented. Error handling in unicode.encode or
str.decode can now be customized.
Fully implemented. Error handling in ``unicode.encode`` or
``str.decode`` can now be customized.
- PEP 282 A Logging System Mick
- PEP 282 A Logging System, Mick
Vinay Sajip's implementation has been packagized and imported.
(Documentation and unit tests still pending.)
http://www.python.org/sf/578494
Vinay Sajip's implementation has been packagized and imported.
(Documentation and unit tests still pending.)
http://www.python.org/sf/578494
- A modified MRO (Method Resolution Order) algorithm. Consensus
is that we should adopt C3. Samuele Pedroni has contributed a
draft implementation in C, see http://www.python.org/sf/619475
This has now been checked in.
- A modified MRO (Method Resolution Order) algorithm. Consensus
is that we should adopt C3. Samuele Pedroni has contributed a
draft implementation in C, see http://www.python.org/sf/619475
This has now been checked in.
- A new command line option parser. Greg Ward's Optik package
(http://optik.sf.net) has been adopted, converted to a single
module named optparse. See also
http://www.python.org/sigs/getopt-sig/
- A new command line option parser. Greg Ward's Optik package
(http://optik.sf.net) has been adopted, converted to a single
module named ``optparse``. See also
http://www.python.org/sigs/getopt-sig/
- A standard datetime type. This started as a wiki:
http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage . A
prototype was coded in nondist/sandbox/datetime/. Tim Peters
has finished the C implementation and checked it in.
- A standard ``datetime`` type. This started as a wiki:
http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage. A
prototype was coded in nondist/sandbox/datetime/. Tim Peters
has finished the C implementation and checked it in.
- PEP 273 Import Modules from Zip Archives Ahlstrom
- PEP 273 Import Modules from Zip Archives, Ahlstrom
Implemented as a part of the PEP 302 implementation work.
Implemented as a part of the PEP 302 implementation work.
- PEP 302 New Import Hooks JvR
- PEP 302 New Import Hooks, JvR
Implemented (though the 2.3a1 release contained some bugs that
have been fixed post-release).
Implemented (though the 2.3a1 release contained some bugs that
have been fixed post-release).
- A new pickling protocol. See PEP 307.
- A new pickling protocol. See PEP 307.
- PEP 305 (CSV File API, by Skip Montanaro et al.) is in; this is
the csv module.
- PEP 305 (CSV File API, by Skip Montanaro et al.) is in; this is
the csv module.
- Raymond Hettinger's itertools module is in.
- Raymond Hettinger's ``itertools`` module is in.
- PEP 311 (Simplified GIL Acquisition for Extensions, by Mark
Hammond) has been included in beta 1.
- PEP 311 (Simplified GIL Acquisition for Extensions, by Mark
Hammond) has been included in beta 1.
- Two new PyArg_Parse*() format codes, 'k' returns an unsigned C
long int that receives the lower LONG_BIT bits of the Python
argument, truncating without range checking. 'K' returns an
unsigned C long long int that receives the lower LONG_LONG_BIT
bits, truncating without range checking. (SF 595026; Thomas
Heller did this work.)
- Two new ``PyArg_Parse*()`` format codes, 'k' returns an unsigned C
long int that receives the lower ``LONG_BIT`` bits of the Python
argument, truncating without range checking. 'K' returns an
unsigned C long long int that receives the lower ``LONG_LONG_BIT``
bits, truncating without range checking. (SF 595026; Thomas
Heller did this work.)
- A new version of IDLE was imported from the IDLEfork project
(http://idlefork.sf.net). The code now lives in the idlelib
package in the standard library and the idle script is installed
by setup.py.
- A new version of IDLE was imported from the IDLEfork project
(http://idlefork.sf.net). The code now lives in the idlelib
package in the standard library and the idle script is installed
by setup.py.
Planned features for 2.3
========================
Too late for anything more to get done here.
Too late for anything more to get done here.
Ongoing tasks
=============
The following are ongoing TO-DO items which we should attempt to
work on without hoping for completion by any particular date.
The following are ongoing TO-DO items which we should attempt to
work on without hoping for completion by any particular date.
- Documentation: complete the distribution and installation
manuals.
- Documentation: complete the distribution and installation
manuals.
- Documentation: complete the documentation for new-style
classes.
- Documentation: complete the documentation for new-style
classes.
- Look over the Demos/ directory and update where required (Andrew
Kuchling has done a lot of this)
- Look over the Demos/ directory and update where required (Andrew
Kuchling has done a lot of this)
- New tests.
- New tests.
- Fix doc bugs on SF.
- Fix doc bugs on SF.
- Remove use of deprecated features in the core.
- Remove use of deprecated features in the core.
- Document deprecated features appropriately.
- Document deprecated features appropriately.
- Mark deprecated C APIs with Py_DEPRECATED.
- Mark deprecated C APIs with ``Py_DEPRECATED``.
- Deprecate modules which are unmaintained, or perhaps make a new
category for modules 'Unmaintained'
- Deprecate modules which are unmaintained, or perhaps make a new
category for modules 'Unmaintained'
- In general, lots of cleanup so it is easier to move forward.
- In general, lots of cleanup so it is easier to move forward.
Open issues
===========
There are some issues that may need more work and/or thought
before the final release (and preferably before the first beta
release): No issues remaining.
There are some issues that may need more work and/or thought
before the final release (and preferably before the first beta
release): No issues remaining.
Features that did not make it into Python 2.3
=============================================
- The import lock could use some redesign. (SF 683658.)
- The import lock could use some redesign. (SF 683658.)
- Set API issues; is the sets module perfect?
- Set API issues; is the sets module perfect?
I expect it's good enough to stop polishing it until we've had
more widespread user experience.
I expect it's good enough to stop polishing it until we've had
more widespread user experience.
- A nicer API to open text files, replacing the ugly (in some
people's eyes) "U" mode flag. There's a proposal out there to
have a new built-in type textfile(filename, mode, encoding).
(Shouldn't it have a bufsize argument too?)
- A nicer API to open text files, replacing the ugly (in some
people's eyes) "U" mode flag. There's a proposal out there to
have a new built-in type textfile(filename, mode, encoding).
(Shouldn't it have a bufsize argument too?)
Ditto.
Ditto.
- New widgets for Tkinter???
- New widgets for Tkinter???
Has anyone gotten the time for this? *Are* there any new
widgets in Tk 8.4? Note that we've got better Tix support
already (though not on Windows yet).
Has anyone gotten the time for this? *Are* there any new
widgets in Tk 8.4? Note that we've got better Tix support
already (though not on Windows yet).
- Fredrik Lundh's basetime proposal:
http://effbot.org/ideas/time-type.htm
- Fredrik Lundh's basetime proposal:
I believe this is dead now.
http://effbot.org/ideas/time-type.htm
- PEP 304 (Controlling Generation of Bytecode Files by Montanaro)
seems to have lost steam.
I believe this is dead now.
- For a class defined inside another class, the __name__ should be
"outer.inner", and pickling should work. (SF 633930. I'm no
longer certain this is easy or even right.)
- PEP 304 (Controlling Generation of Bytecode Files by Montanaro)
seems to have lost steam.
- reST is going to be used a lot in Zope3. Maybe it could become
a standard library module? (Since reST's author thinks it's too
instable, I'm inclined not to do this.)
- For a class defined inside another class, the ``__name__`` should be
"outer.inner", and pickling should work. (SF 633930. I'm no
longer certain this is easy or even right.)
- Decide on a clearer deprecation policy (especially for modules)
and act on it. For a start, see this message from Neal Norwitz:
http://mail.python.org/pipermail/python-dev/2002-April/023165.html
There seems insufficient interest in moving this further in an
organized fashion, and it's not particularly important.
- reST is going to be used a lot in Zope3. Maybe it could become
a standard library module? (Since reST's author thinks it's too
unstable, I'm inclined not to do this.)
- Provide alternatives for common uses of the types module;
Skip Montanaro has posted a proto-PEP for this idea:
http://mail.python.org/pipermail/python-dev/2002-May/024346.html
There hasn't been any progress on this, AFAICT.
- Decide on a clearer deprecation policy (especially for modules)
and act on it. For a start, see this message from Neal Norwitz:
http://mail.python.org/pipermail/python-dev/2002-April/023165.html
There seems insufficient interest in moving this further in an
organized fashion, and it's not particularly important.
- Use pending deprecation for the types and string modules. This
requires providing alternatives for the parts that aren't
covered yet (e.g. string.whitespace and types.TracebackType).
It seems we can't get consensus on this.
- Provide alternatives for common uses of the types module;
- Deprecate the buffer object.
http://mail.python.org/pipermail/python-dev/2002-July/026388.html
http://mail.python.org/pipermail/python-dev/2002-July/026408.html
It seems that this is never going to be resolved.
Skip Montanaro has posted a proto-PEP for this idea:
http://mail.python.org/pipermail/python-dev/2002-May/024346.html
- PEP 269 Pgen Module for Python Riehl
There hasn't been any progress on this, AFAICT.
(Some necessary changes are in; the pgen module itself needs to
mature more.)
- Use pending deprecation for the types and string modules. This
requires providing alternatives for the parts that aren't
covered yet (e.g. ``string.whitespace`` and ``types.TracebackType``).
It seems we can't get consensus on this.
- Add support for the long-awaited Python catalog. Kapil
Thangavelu has a Zope-based implementation that he demoed at
OSCON 2002. Now all we need is a place to host it and a person
to champion it. (Some changes to distutils to support this are
in, at least.)
- Deprecate the buffer object.
- PEP 266 Optimizing Global Variable/Attribute Access Montanaro
PEP 267 Optimized Access to Module Namespaces Hylton
PEP 280 Optimizing access to globals van Rossum
- http://mail.python.org/pipermail/python-dev/2002-July/026388.html
- http://mail.python.org/pipermail/python-dev/2002-July/026408.html
These are basically three friendly competing proposals. Jeremy
has made a little progress with a new compiler, but it's going
slow and the compiler is only the first step. Maybe we'll be
able to refactor the compiler in this release. I'm tempted to
say we won't hold our breath. In the mean time, Oren Tirosh has
a much simpler idea that may give a serious boost to the
performance of accessing globals and built-ins, by optimizing
and inlining the dict access:
http://tothink.com/python/fastnames/
It seems that this is never going to be resolved.
- Lazily tracking tuples?
http://mail.python.org/pipermail/python-dev/2002-May/023926.html
http://www.python.org/sf/558745
Not much enthusiasm I believe.
- PEP 269 Pgen Module for Python, Riehl
- PEP 286 Enhanced Argument Tuples von Loewis
(Some necessary changes are in; the ``pgen`` module itself needs to
mature more.)
I haven't had the time to review this thoroughly. It seems a
deep optimization hack (also makes better correctness guarantees
though).
- Add support for the long-awaited Python catalog. Kapil
Thangavelu has a Zope-based implementation that he demoed at
OSCON 2002. Now all we need is a place to host it and a person
to champion it. (Some changes to distutils to support this are
in, at least.)
- Make 'as' a keyword. It has been a pseudo-keyword long enough.
Too much effort to bother.
- PEP 266 Optimizing Global Variable/Attribute Access, Montanaro
PEP 267 Optimized Access to Module Namespaces, Hylton
PEP 280 Optimizing access to globals, van Rossum
These are basically three friendly competing proposals. Jeremy
has made a little progress with a new compiler, but it's going
slow and the compiler is only the first step. Maybe we'll be
able to refactor the compiler in this release. I'm tempted to
say we won't hold our breath. In the mean time, Oren Tirosh has
a much simpler idea that may give a serious boost to the
performance of accessing globals and built-ins, by optimizing
and inlining the dict access: http://tothink.com/python/fastnames/
- Lazily tracking tuples?
- http://mail.python.org/pipermail/python-dev/2002-May/023926.html
- http://www.python.org/sf/558745
Not much enthusiasm I believe.
- PEP 286 Enhanced Argument Tuples, von Loewis
I haven't had the time to review this thoroughly. It seems a
deep optimization hack (also makes better correctness guarantees
though).
- Make 'as' a keyword. It has been a pseudo-keyword long enough.
Too much effort to bother.
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:

View File

@ -5,311 +5,338 @@ Last-Modified: $Date$
Author: A.M. Kuchling, Richard Jones
Status: Final
Type: Standards Track
Content-Type: text/plain
Content-Type: text/x-rst
Created: 12-Apr-2003
Python-Version: 2.5
Post-History: 29-Apr-2003
Replaces: 241
Introduction
============
This PEP describes a mechanism for adding metadata to Python
packages. It includes specifics of the field names, and their
semantics and usage.
This PEP describes a mechanism for adding metadata to Python
packages. It includes specifics of the field names, and their
semantics and usage.
This document specifies version 1.1 of the metadata format.
Version 1.0 is specified in PEP 241.
This document specifies version 1.1 of the metadata format.
Version 1.0 is specified in PEP 241.
Including Metadata in Packages
==============================
The Distutils 'sdist' command will extract the metadata fields
from the arguments and write them to a file in the generated
zipfile or tarball. This file will be named PKG-INFO and will be
placed in the top directory of the source distribution (where the
README, INSTALL, and other files usually go).
The Distutils ``sdist`` command will extract the metadata fields
from the arguments and write them to a file in the generated
zipfile or tarball. This file will be named PKG-INFO and will be
placed in the top directory of the source distribution (where the
README, INSTALL, and other files usually go).
Developers may not provide their own PKG-INFO file. The "sdist"
command will, if it detects an existing PKG-INFO file, terminate
with an appropriate error message. This should prevent confusion
caused by the PKG-INFO and setup.py files being out of sync.
Developers may not provide their own PKG-INFO file. The ``sdist``
command will, if it detects an existing PKG-INFO file, terminate
with an appropriate error message. This should prevent confusion
caused by the PKG-INFO and setup.py files being out of sync.
The PKG-INFO file format is a single set of RFC-822 headers
parseable by the rfc822.py module. The field names listed in the
following section are used as the header names.
The PKG-INFO file format is a single set of RFC-822 headers
parseable by the rfc822.py module. The field names listed in the
following section are used as the header names.
Fields
======
This section specifies the names and semantics of each of the
supported metadata fields.
Fields marked with "(Multiple use)" may be specified multiple
times in a single PKG-INFO file. Other fields may only occur
once in a PKG-INFO file. Fields marked with "(optional)" are
not required to appear in a valid PKG-INFO file; all other
fields must be present.
This section specifies the names and semantics of each of the
supported metadata fields.
Metadata-Version
Fields marked with "(Multiple use)" may be specified multiple
times in a single PKG-INFO file. Other fields may only occur
once in a PKG-INFO file. Fields marked with "(optional)" are
not required to appear in a valid PKG-INFO file; all other
fields must be present.
Version of the file format; currently "1.0" and "1.1" are the
only legal values here.
Metadata-Version
----------------
Example:
Version of the file format; currently "1.0" and "1.1" are the
only legal values here.
Metadata-Version: 1.1
Example::
Name
Metadata-Version: 1.1
The name of the package.
Name
----
Example:
The name of the package.
Name: BeagleVote
Version
Example::
A string containing the package's version number. This
field should be parseable by one of the Version classes
(StrictVersion or LooseVersion) in the distutils.version
module.
Name: BeagleVote
Example:
Version
-------
Version: 1.0a2
Platform (multiple use)
A string containing the package's version number. This
field should be parseable by one of the Version classes
(StrictVersion or LooseVersion) in the distutils.version
module.
A comma-separated list of platform specifications, summarizing
the operating systems supported by the package which are not
listed in the "Operating System" Trove classifiers. See
"Classifier" below.
Example::
Example:
Version: 1.0a2
Platform: ObscureUnix, RareDOS
Platform (multiple use)
-----------------------
Supported-Platform (multiple use)
A comma-separated list of platform specifications, summarizing
the operating systems supported by the package which are not
listed in the "Operating System" Trove classifiers. See
"Classifier" below.
Binary distributions containing a PKG-INFO file will use the
Supported-Platform field in their metadata to specify the OS and
CPU for which the binary package was compiled. The semantics of
the Supported-Platform field are not specified in this PEP.
Example::
Example:
Platform: ObscureUnix, RareDOS
Supported-Platform: RedHat 7.2
Supported-Platform: i386-win32-2791
Supported-Platform (multiple use)
---------------------------------
Summary
Binary distributions containing a PKG-INFO file will use the
Supported-Platform field in their metadata to specify the OS and
CPU for which the binary package was compiled. The semantics of
the Supported-Platform field are not specified in this PEP.
A one-line summary of what the package does.
Example::
Example:
Supported-Platform: RedHat 7.2
Supported-Platform: i386-win32-2791
Summary: A module for collecting votes from beagles.
Description (optional)
Summary
-------
A longer description of the package that can run to several
paragraphs. Software that deals with metadata should not assume
any maximum size for this field, though people shouldn't include
their instruction manual as the description.
A one-line summary of what the package does.
The contents of this field can be written using reStructuredText
markup [1]. For programs that work with the metadata,
supporting markup is optional; programs can also display the
contents of the field as-is. This means that authors should be
conservative in the markup they use.
Example::
Example:
Description: This module collects votes from beagles
in order to determine their electoral wishes.
Do *not* try to use this module with basset hounds;
it makes them grumpy.
Keywords (optional)
Summary: A module for collecting votes from beagles.
A list of additional keywords to be used to assist searching
for the package in a larger catalog.
Description (optional)
----------------------
Example:
A longer description of the package that can run to several
paragraphs. Software that deals with metadata should not assume
any maximum size for this field, though people shouldn't include
their instruction manual as the description.
Keywords: dog puppy voting election
Home-page (optional)
The contents of this field can be written using reStructuredText
markup [1]_. For programs that work with the metadata,
supporting markup is optional; programs can also display the
contents of the field as-is. This means that authors should be
conservative in the markup they use.
A string containing the URL for the package's home page.
Example::
Example:
Description: This module collects votes from beagles
in order to determine their electoral wishes.
Do *not* try to use this module with basset hounds;
it makes them grumpy.
Home-page: http://www.example.com/~cschultz/bvote/
Download-URL
A string containing the URL from which this version of the package
can be downloaded. (This means that the URL can't be something like
".../package-latest.tgz", but instead must be "../package-0.45.tgz".)
Author (optional)
Keywords (optional)
-------------------
A string containing the author's name at a minimum; additional
contact information may be provided.
A list of additional keywords to be used to assist searching
for the package in a larger catalog.
Example:
Example::
Author: C. Schultz, Universal Features Syndicate,
Los Angeles, CA <cschultz@peanuts.example.com>
Author-email
Keywords: dog puppy voting election
A string containing the author's e-mail address. It can contain
a name and e-mail address in the legal forms for a RFC-822
'From:' header. It's not optional because cataloging systems
can use the e-mail portion of this field as a unique key
representing the author. A catalog might provide authors the
ability to store their GPG key, personal home page, and other
additional metadata *about the author*, and optionally the
ability to associate several e-mail addresses with the same
person. Author-related metadata fields are not covered by this
PEP.
Home-page (optional)
--------------------
Example:
A string containing the URL for the package's home page.
Author-email: "C. Schultz" <cschultz@example.com>
License
Text indicating the license covering the package where the license
is not a selection from the "License" Trove classifiers. See
"Classifier" below.
Example::
Example:
Home-page: http://www.example.com/~cschultz/bvote/
License: This software may only be obtained by sending the
author a postcard, and then the user promises not
to redistribute it.
Download-URL
------------
Classifier (multiple use)
A string containing the URL from which this version of the package
can be downloaded. (This means that the URL can't be something like
".../package-latest.tgz", but instead must be "../package-0.45.tgz".)
Each entry is a string giving a single classification value
for the package. Classifiers are described in PEP 301 [2].
Author (optional)
-----------------
Examples:
A string containing the author's name at a minimum; additional
contact information may be provided.
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console (Text Based)
Example::
Requires (multiple use)
Each entry contains a string describing some other module or
package required by this package.
Author: C. Schultz, Universal Features Syndicate,
Los Angeles, CA <cschultz@peanuts.example.com>
The format of a requirement string is identical to that of a
module or package name usable with the 'import' statement,
optionally followed by a version declaration within parentheses.
Author-email
------------
A version declaration is a series of conditional operators and
version numbers, separated by commas. Conditional operators
must be one of "<", ">", "<=", ">=", "==", and "!=". Version
numbers must be in the format accepted by the
distutils.version.StrictVersion class: two or three
dot-separated numeric components, with an optional "pre-release"
tag on the end consisting of the letter 'a' or 'b' followed by a
number. Example version numbers are "1.0", "2.3a2", "1.3.99",
A string containing the author's e-mail address. It can contain
a name and e-mail address in the legal forms for a RFC-822
'From:' header. It's not optional because cataloging systems
can use the e-mail portion of this field as a unique key
representing the author. A catalog might provide authors the
ability to store their GPG key, personal home page, and other
additional metadata *about the author*, and optionally the
ability to associate several e-mail addresses with the same
person. Author-related metadata fields are not covered by this
PEP.
Any number of conditional operators can be specified, e.g.
the string ">1.0, !=1.3.4, <2.0" is a legal version declaration.
Example::
All of the following are possible requirement strings: "rfc822",
"zlib (>=1.1.4)", "zope".
Author-email: "C. Schultz" <cschultz@example.com>
There's no canonical list of what strings should be used; the
Python community is left to choose its own standards.
License
-------
Example:
Text indicating the license covering the package where the license
is not a selection from the "License" Trove classifiers. See
"Classifier" below.
Requires: re
Requires: sys
Requires: zlib
Requires: xml.parsers.expat (>1.0)
Requires: psycopg
Provides (multiple use)
Example::
Each entry contains a string describing a package or module that
will be provided by this package once it is installed. These
strings should match the ones used in Requirements fields. A
version declaration may be supplied (without a comparison
operator); the package's version number will be implied if none
is specified.
License: This software may only be obtained by sending the
author a postcard, and then the user promises not
to redistribute it.
Example:
Classifier (multiple use)
-------------------------
Provides: xml
Provides: xml.utils
Provides: xml.utils.iso8601
Provides: xml.dom
Provides: xmltools (1.3)
Each entry is a string giving a single classification value
for the package. Classifiers are described in PEP 301 [2]_.
Obsoletes (multiple use)
Examples::
Each entry contains a string describing a package or module
that this package renders obsolete, meaning that the two packages
should not be installed at the same time. Version declarations
can be supplied.
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console (Text Based)
The most common use of this field will be in case a package name
changes, e.g. Gorgon 2.3 gets subsumed into Torqued Python 1.0.
When you install Torqued Python, the Gorgon package should be
removed.
Example:
Obsoletes: Gorgon
Requires (multiple use)
-----------------------
Each entry contains a string describing some other module or
package required by this package.
The format of a requirement string is identical to that of a
module or package name usable with the 'import' statement,
optionally followed by a version declaration within parentheses.
A version declaration is a series of conditional operators and
version numbers, separated by commas. Conditional operators
must be one of "<", ">", "<=", ">=", "==", and "!=". Version
numbers must be in the format accepted by the
distutils.version.StrictVersion class: two or three
dot-separated numeric components, with an optional "pre-release"
tag on the end consisting of the letter 'a' or 'b' followed by a
number. Example version numbers are "1.0", "2.3a2", "1.3.99",
Any number of conditional operators can be specified, e.g.
the string ">1.0, !=1.3.4, <2.0" is a legal version declaration.
All of the following are possible requirement strings: "rfc822",
"zlib (>=1.1.4)", "zope".
There's no canonical list of what strings should be used; the
Python community is left to choose its own standards.
Example::
Requires: re
Requires: sys
Requires: zlib
Requires: xml.parsers.expat (>1.0)
Requires: psycopg
Provides (multiple use)
-----------------------
Each entry contains a string describing a package or module that
will be provided by this package once it is installed. These
strings should match the ones used in Requirements fields. A
version declaration may be supplied (without a comparison
operator); the package's version number will be implied if none
is specified.
Example::
Provides: xml
Provides: xml.utils
Provides: xml.utils.iso8601
Provides: xml.dom
Provides: xmltools (1.3)
Obsoletes (multiple use)
------------------------
Each entry contains a string describing a package or module
that this package renders obsolete, meaning that the two packages
should not be installed at the same time. Version declarations
can be supplied.
The most common use of this field will be in case a package name
changes, e.g. Gorgon 2.3 gets subsumed into Torqued Python 1.0.
When you install Torqued Python, the Gorgon package should be
removed.
Example::
Obsoletes: Gorgon
Summary of Differences From PEP 241
===================================
* Metadata-Version is now 1.1.
* Metadata-Version is now 1.1.
* Added the Classifiers field from PEP 301.
* Added the Classifiers field from PEP 301.
* The License and Platform files should now only be used if the
platform or license can't be handled by an appropriate Classifier
value.
* The License and Platform files should now only be used if the
platform or license can't be handled by an appropriate Classifier
value.
* Added fields: Download-URL, Requires, Provides, Obsoletes.
* Added fields: Download-URL, Requires, Provides, Obsoletes.
Open issues
===========
None.
None.
Acknowledgements
================
None.
None.
References
==========
[1] reStructuredText
http://docutils.sourceforge.net/
.. [1] reStructuredText
http://docutils.sourceforge.net/
[2] PEP 301
http://www.python.org/dev/peps/pep-0301/
.. [2] PEP 301
http://www.python.org/dev/peps/pep-0301/
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:

View File

@ -5,309 +5,327 @@ Last-Modified: $Date$
Author: Talin <viridia@gmail.com>
Status: Final
Type: Standards Track
Content-Type: text/plain
Content-Type: text/x-rst
Created: 07-Mar-2007
Python-Version: 3.0
Post-History: 11-March-2007, 14-March-2007
Abstract
This PEP proposes changing the syntax for declaring metaclasses,
and alters the semantics for how classes with metaclasses are
constructed.
Abstract
========
This PEP proposes changing the syntax for declaring metaclasses,
and alters the semantics for how classes with metaclasses are
constructed.
Rationale
=========
There are two rationales for this PEP, both of which are somewhat
subtle.
There are two rationales for this PEP, both of which are somewhat
subtle.
The primary reason for changing the way metaclasses work, is that
there are a number of interesting use cases that require the
metaclass to get involved earlier in the class construction process
than is currently possible. Currently, the metaclass mechanism is
essentially a post-processing step. With the advent of class
decorators, much of these post-processing chores can be taken over
by the decorator mechanism.
The primary reason for changing the way metaclasses work, is that
there are a number of interesting use cases that require the
metaclass to get involved earlier in the class construction process
than is currently possible. Currently, the metaclass mechanism is
essentially a post-processing step. With the advent of class
decorators, much of these post-processing chores can be taken over
by the decorator mechanism.
In particular, there is an important body of use cases where it
would be useful to preserve the order in which a class members are
declared. Ordinary Python objects store their members in a
dictionary, in which ordering is unimportant, and members are
accessed strictly by name. However, Python is often used to
interface with external systems in which the members are organized
according to an implicit ordering. Examples include declaration of C
structs; COM objects; Automatic translation of Python classes into
IDL or database schemas, such as used in an ORM; and so on.
In particular, there is an important body of use cases where it
would be useful to preserve the order in which a class members are
declared. Ordinary Python objects store their members in a
dictionary, in which ordering is unimportant, and members are
accessed strictly by name. However, Python is often used to
interface with external systems in which the members are organized
according to an implicit ordering. Examples include declaration of C
structs; COM objects; Automatic translation of Python classes into
IDL or database schemas, such as used in an ORM; and so on.
In such cases, it would be useful for a Python programmer to specify
such ordering directly using the declaration order of class members.
Currently, such orderings must be specified explicitly, using some
other mechanism (see the ctypes module for an example.)
In such cases, it would be useful for a Python programmer to specify
such ordering directly using the declaration order of class members.
Currently, such orderings must be specified explicitly, using some
other mechanism (see the ctypes module for an example.)
Unfortunately, the current method for declaring a metaclass does
not allow for this, since the ordering information has already been
lost by the time the metaclass comes into play. By allowing the
metaclass to get involved in the class construction process earlier,
the new system allows the ordering or other early artifacts of
construction to be preserved and examined.
Unfortunately, the current method for declaring a metaclass does
not allow for this, since the ordering information has already been
lost by the time the metaclass comes into play. By allowing the
metaclass to get involved in the class construction process earlier,
the new system allows the ordering or other early artifacts of
construction to be preserved and examined.
There proposed metaclass mechanism also supports a number of other
interesting use cases beyond preserving the ordering of declarations.
One use case is to insert symbols into the namespace of the class
body which are only valid during class construction. An example of
this might be "field constructors", small functions that are used in
the creation of class members. Another interesting possibility is
supporting forward references, i.e. references to Python
symbols that are declared further down in the class body.
There proposed metaclass mechanism also supports a number of other
interesting use cases beyond preserving the ordering of declarations.
One use case is to insert symbols into the namespace of the class
body which are only valid during class construction. An example of
this might be "field constructors", small functions that are used in
the creation of class members. Another interesting possibility is
supporting forward references, i.e. references to Python
symbols that are declared further down in the class body.
The other, weaker, rationale is purely cosmetic: The current method
for specifying a metaclass is by assignment to the special variable
__metaclass__, which is considered by some to be aesthetically less
than ideal. Others disagree strongly with that opinion. This PEP
will not address this issue, other than to note it, since aesthetic
debates cannot be resolved via logical proofs.
The other, weaker, rationale is purely cosmetic: The current method
for specifying a metaclass is by assignment to the special variable
``__metaclass__``, which is considered by some to be aesthetically less
than ideal. Others disagree strongly with that opinion. This PEP
will not address this issue, other than to note it, since aesthetic
debates cannot be resolved via logical proofs.
Specification
=============
In the new model, the syntax for specifying a metaclass is via a
keyword argument in the list of base classes:
In the new model, the syntax for specifying a metaclass is via a
keyword argument in the list of base classes::
class Foo(base1, base2, metaclass=mymeta):
...
class Foo(base1, base2, metaclass=mymeta):
...
Additional keywords will also be allowed here, and will be passed to
the metaclass, as in the following example:
Additional keywords will also be allowed here, and will be passed to
the metaclass, as in the following example::
class Foo(base1, base2, metaclass=mymeta, private=True):
...
class Foo(base1, base2, metaclass=mymeta, private=True):
...
Note that this PEP makes no attempt to define what these other
keywords might be - that is up to metaclass implementors to
determine.
Note that this PEP makes no attempt to define what these other
keywords might be - that is up to metaclass implementors to
determine.
More generally, the parameter list passed to a class definition will
now support all of the features of a function call, meaning that you
can now use *args and **kwargs-style arguments in the class base
list:
More generally, the parameter list passed to a class definition will
now support all of the features of a function call, meaning that you
can now use ``*args`` and ``**kwargs``-style arguments in the class base
list::
class Foo(*bases, **kwds):
...
class Foo(*bases, **kwds):
...
Invoking the Metaclass
======================
In the current metaclass system, the metaclass object can be any
callable type. This does not change, however in order to fully
exploit all of the new features the metaclass will need to have an
extra attribute which is used during class pre-construction.
In the current metaclass system, the metaclass object can be any
callable type. This does not change, however in order to fully
exploit all of the new features the metaclass will need to have an
extra attribute which is used during class pre-construction.
This attribute is named __prepare__, which is invoked as a function
before the evaluation of the class body. The __prepare__ function
takes two positional arguments, and an arbitrary number of keyword
arguments. The two positional arguments are:
This attribute is named ``__prepare__``, which is invoked as a function
before the evaluation of the class body. The ``__prepare__`` function
takes two positional arguments, and an arbitrary number of keyword
arguments. The two positional arguments are:
'name' - the name of the class being created.
'bases' - the list of base classes.
========= ====================================
``name`` the name of the class being created.
``bases`` the list of base classes.
========= ====================================
The interpreter always tests for the existence of __prepare__ before
calling it; If it is not present, then a regular dictionary is used,
as illustrated in the following Python snippet.
The interpreter always tests for the existence of ``__prepare__`` before
calling it; If it is not present, then a regular dictionary is used,
as illustrated in the following Python snippet.
def prepare_class(name, *bases, metaclass=None, **kwargs):
if metaclass is None:
metaclass = compute_default_metaclass(bases)
prepare = getattr(metaclass, '__prepare__', None)
if prepare is not None:
return prepare(name, bases, **kwargs)
else:
return dict()
::
The example above illustrates how the arguments to 'class' are
interpreted. The class name is the first argument, followed by
an arbitrary length list of base classes. After the base classes,
there may be one or more keyword arguments, one of which can be
'metaclass'. Note that the 'metaclass' argument is not included
in kwargs, since it is filtered out by the normal parameter
assignment algorithm. (Note also that 'metaclass' is a keyword-
only argument as per PEP 3102 [6].)
def prepare_class(name, *bases, metaclass=None, **kwargs):
if metaclass is None:
metaclass = compute_default_metaclass(bases)
prepare = getattr(metaclass, '__prepare__', None)
if prepare is not None:
return prepare(name, bases, **kwargs)
else:
return dict()
Even though __prepare__ is not required, the default metaclass
('type') implements it, for the convenience of subclasses calling
it via super().
The example above illustrates how the arguments to 'class' are
interpreted. The class name is the first argument, followed by
an arbitrary length list of base classes. After the base classes,
there may be one or more keyword arguments, one of which can be
'metaclass'. Note that the 'metaclass' argument is not included
in kwargs, since it is filtered out by the normal parameter
assignment algorithm. (Note also that 'metaclass' is a keyword-
only argument as per PEP 3102 [6]_.)
__prepare__ returns a dictionary-like object which is used to store
the class member definitions during evaluation of the class body.
In other words, the class body is evaluated as a function block
(just like it is now), except that the local variables dictionary
is replaced by the dictionary returned from __prepare__. This
dictionary object can be a regular dictionary or a custom mapping
type.
Even though ``__prepare__`` is not required, the default metaclass
('type') implements it, for the convenience of subclasses calling
it via super().
This dictionary-like object is not required to support the full
dictionary interface. A dictionary which supports a limited set of
dictionary operations will restrict what kinds of actions can occur
during evaluation of the class body. A minimal implementation might
only support adding and retrieving values from the dictionary - most
class bodies will do no more than that during evaluation. For some
classes, it may be desirable to support deletion as well. Many
metaclasses will need to make a copy of this dictionary afterwards,
so iteration or other means for reading out the dictionary contents
may also be useful.
``__prepare__`` returns a dictionary-like object which is used to store
the class member definitions during evaluation of the class body.
In other words, the class body is evaluated as a function block
(just like it is now), except that the local variables dictionary
is replaced by the dictionary returned from ``__prepare__``. This
dictionary object can be a regular dictionary or a custom mapping
type.
The __prepare__ method will most often be implemented as a class
method rather than an instance method because it is called before
the metaclass instance (i.e. the class itself) is created.
This dictionary-like object is not required to support the full
dictionary interface. A dictionary which supports a limited set of
dictionary operations will restrict what kinds of actions can occur
during evaluation of the class body. A minimal implementation might
only support adding and retrieving values from the dictionary - most
class bodies will do no more than that during evaluation. For some
classes, it may be desirable to support deletion as well. Many
metaclasses will need to make a copy of this dictionary afterwards,
so iteration or other means for reading out the dictionary contents
may also be useful.
Once the class body has finished evaluating, the metaclass will be
called (as a callable) with the class dictionary, which is no
different from the current metaclass mechanism.
The ``__prepare__`` method will most often be implemented as a class
method rather than an instance method because it is called before
the metaclass instance (i.e. the class itself) is created.
Typically, a metaclass will create a custom dictionary - either a
subclass of dict, or a wrapper around it - that will contain
additional properties that are set either before or during the
evaluation of the class body. Then in the second phase, the
metaclass can use these additional properties to further customize
the class.
Once the class body has finished evaluating, the metaclass will be
called (as a callable) with the class dictionary, which is no
different from the current metaclass mechanism.
An example would be a metaclass that uses information about the
ordering of member declarations to create a C struct. The metaclass
would provide a custom dictionary that simply keeps a record of the
order of insertions. This does not need to be a full 'ordered dict'
implementation, but rather just a Python list of (key,value) pairs
that is appended to for each insertion.
Typically, a metaclass will create a custom dictionary - either a
subclass of dict, or a wrapper around it - that will contain
additional properties that are set either before or during the
evaluation of the class body. Then in the second phase, the
metaclass can use these additional properties to further customize
the class.
Note that in such a case, the metaclass would be required to deal
with the possibility of duplicate keys, but in most cases that is
trivial. The metaclass can use the first declaration, the last,
combine them in some fashion, or simply throw an exception. It's up
to the metaclass to decide how it wants to handle that case.
An example would be a metaclass that uses information about the
ordering of member declarations to create a C struct. The metaclass
would provide a custom dictionary that simply keeps a record of the
order of insertions. This does not need to be a full 'ordered dict'
implementation, but rather just a Python list of (key,value) pairs
that is appended to for each insertion.
Example:
Note that in such a case, the metaclass would be required to deal
with the possibility of duplicate keys, but in most cases that is
trivial. The metaclass can use the first declaration, the last,
combine them in some fashion, or simply throw an exception. It's up
to the metaclass to decide how it wants to handle that case.
Here's a simple example of a metaclass which creates a list of
the names of all class members, in the order that they were
declared:
# The custom dictionary
class member_table(dict):
def __init__(self):
Example
=======
Here's a simple example of a metaclass which creates a list of
the names of all class members, in the order that they were
declared::
# The custom dictionary
class member_table(dict):
def __init__(self):
self.member_names = []
def __setitem__(self, key, value):
def __setitem__(self, key, value):
# if the key is not already defined, add to the
# list of keys.
if key not in self:
self.member_names.append(key)
self.member_names.append(key)
# Call superclass
dict.__setitem__(self, key, value)
# The metaclass
class OrderedClass(type):
# The metaclass
class OrderedClass(type):
# The prepare function
@classmethod
def __prepare__(metacls, name, bases): # No keywords in this case
return member_table()
# The prepare function
@classmethod
def __prepare__(metacls, name, bases): # No keywords in this case
return member_table()
# The metaclass invocation
def __new__(cls, name, bases, classdict):
# Note that we replace the classdict with a regular
# dict before passing it to the superclass, so that we
# don't continue to record member names after the class
# has been created.
result = type.__new__(cls, name, bases, dict(classdict))
result.member_names = classdict.member_names
return result
# The metaclass invocation
def __new__(cls, name, bases, classdict):
# Note that we replace the classdict with a regular
# dict before passing it to the superclass, so that we
# don't continue to record member names after the class
# has been created.
result = type.__new__(cls, name, bases, dict(classdict))
result.member_names = classdict.member_names
return result
class MyClass(metaclass=OrderedClass):
# method1 goes in array element 0
def method1(self):
class MyClass(metaclass=OrderedClass):
# method1 goes in array element 0
def method1(self):
pass
# method2 goes in array element 1
def method2(self):
# method2 goes in array element 1
def method2(self):
pass
Sample Implementation:
Guido van Rossum has created a patch which implements the new
functionality:
http://python.org/sf/1681101
Sample Implementation
=====================
Guido van Rossum has created a patch which implements the new
functionality: http://python.org/sf/1681101
Alternate Proposals
===================
Josiah Carlson proposed using the name 'type' instead of
'metaclass', on the theory that what is really being specified is
the type of the type. While this is technically correct, it is also
confusing from the point of view of a programmer creating a new
class. From the application programmer's point of view, the 'type'
that they are interested in is the class that they are writing; the
type of that type is the metaclass.
Josiah Carlson proposed using the name 'type' instead of
'metaclass', on the theory that what is really being specified is
the type of the type. While this is technically correct, it is also
confusing from the point of view of a programmer creating a new
class. From the application programmer's point of view, the 'type'
that they are interested in is the class that they are writing; the
type of that type is the metaclass.
There were some objections in the discussion to the 'two-phase'
creation process, where the metaclass is invoked twice, once to
create the class dictionary and once to 'finish' the class. Some
people felt that these two phases should be completely separate, in
that there ought to be separate syntax for specifying the custom
dict as for specifying the metaclass. However, in most cases, the
two will be intimately tied together, and the metaclass will most
likely have an intimate knowledge of the internal details of the
class dict. Requiring the programmer to insure that the correct dict
type and the correct metaclass type are used together creates an
additional and unneeded burden on the programmer.
There were some objections in the discussion to the 'two-phase'
creation process, where the metaclass is invoked twice, once to
create the class dictionary and once to 'finish' the class. Some
people felt that these two phases should be completely separate, in
that there ought to be separate syntax for specifying the custom
dict as for specifying the metaclass. However, in most cases, the
two will be intimately tied together, and the metaclass will most
likely have an intimate knowledge of the internal details of the
class dict. Requiring the programmer to insure that the correct dict
type and the correct metaclass type are used together creates an
additional and unneeded burden on the programmer.
Another good suggestion was to simply use an ordered dict for all
classes, and skip the whole 'custom dict' mechanism. This was based
on the observation that most use cases for a custom dict were for
the purposes of preserving order information. However, this idea has
several drawbacks, first because it means that an ordered dict
implementation would have to be added to the set of built-in types
in Python, and second because it would impose a slight speed (and
complexity) penalty on all class declarations. Later, several people
came up with ideas for use cases for custom dictionaries other
than preserving field orderings, so this idea was dropped.
Another good suggestion was to simply use an ordered dict for all
classes, and skip the whole 'custom dict' mechanism. This was based
on the observation that most use cases for a custom dict were for
the purposes of preserving order information. However, this idea has
several drawbacks, first because it means that an ordered dict
implementation would have to be added to the set of built-in types
in Python, and second because it would impose a slight speed (and
complexity) penalty on all class declarations. Later, several people
came up with ideas for use cases for custom dictionaries other
than preserving field orderings, so this idea was dropped.
Backwards Compatibility
=======================
It would be possible to leave the existing __metaclass__ syntax in
place. Alternatively, it would not be too difficult to modify the
syntax rules of the Py3K translation tool to convert from the old to
the new syntax.
It would be possible to leave the existing ``__metaclass__`` syntax in
place. Alternatively, it would not be too difficult to modify the
syntax rules of the Py3K translation tool to convert from the old to
the new syntax.
References
==========
[1] [Python-3000] Metaclasses in Py3K (original proposal)
http://mail.python.org/pipermail/python-3000/2006-December/005030.html
.. [1] [Python-3000] Metaclasses in Py3K (original proposal)
http://mail.python.org/pipermail/python-3000/2006-December/005030.html
[2] [Python-3000] Metaclasses in Py3K (Guido's suggested syntax)
http://mail.python.org/pipermail/python-3000/2006-December/005033.html
.. [2] [Python-3000] Metaclasses in Py3K (Guido's suggested syntax)
http://mail.python.org/pipermail/python-3000/2006-December/005033.html
[3] [Python-3000] Metaclasses in Py3K (Objections to two-phase init)
http://mail.python.org/pipermail/python-3000/2006-December/005108.html
.. [3] [Python-3000] Metaclasses in Py3K (Objections to two-phase init)
http://mail.python.org/pipermail/python-3000/2006-December/005108.html
[4] [Python-3000] Metaclasses in Py3K (Always use an ordered dict)
http://mail.python.org/pipermail/python-3000/2006-December/005118.html
.. [4] [Python-3000] Metaclasses in Py3K (Always use an ordered dict)
http://mail.python.org/pipermail/python-3000/2006-December/005118.html
[5] PEP 359: The 'make' statement -
http://www.python.org/dev/peps/pep-0359/
.. [5] PEP 359: The 'make' statement -
http://www.python.org/dev/peps/pep-0359/
[6] PEP 3102: Keyword-only arguments -
http://www.python.org/dev/peps/pep-3102/
.. [6] PEP 3102: Keyword-only arguments -
http://www.python.org/dev/peps/pep-3102/
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
coding: utf-8
End:
..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
coding: utf-8
End: