PEP 259: Omit printing newline after newline
This commit is contained in:
parent
afd299ae13
commit
559c1c1ad4
|
@ -60,6 +60,7 @@ Index by Category
|
||||||
S 256 pep-0256.txt Docstring Processing System Framework Goodger
|
S 256 pep-0256.txt Docstring Processing System Framework Goodger
|
||||||
S 257 pep-0257.txt Docstring Conventions Goodger
|
S 257 pep-0257.txt Docstring Conventions Goodger
|
||||||
S 258 pep-0258.txt DPS Generic Implementation Details Goodger
|
S 258 pep-0258.txt DPS Generic Implementation Details Goodger
|
||||||
|
S 259 pep-0259.txt Omit printing newline after newline van Rossum
|
||||||
|
|
||||||
Py-in-the-sky PEPs (not ready; may become active yet)
|
Py-in-the-sky PEPs (not ready; may become active yet)
|
||||||
|
|
||||||
|
@ -184,6 +185,7 @@ Numerical Index
|
||||||
S 256 pep-0256.txt Docstring Processing System Framework Goodger
|
S 256 pep-0256.txt Docstring Processing System Framework Goodger
|
||||||
S 257 pep-0257.txt Docstring Conventions Goodger
|
S 257 pep-0257.txt Docstring Conventions Goodger
|
||||||
S 258 pep-0258.txt DPS Generic Implementation Details Goodger
|
S 258 pep-0258.txt DPS Generic Implementation Details Goodger
|
||||||
|
S 259 pep-0259.txt Omit printing newline after newline van Rossum
|
||||||
|
|
||||||
|
|
||||||
Key
|
Key
|
||||||
|
|
87
pep-0253.txt
87
pep-0253.txt
|
@ -34,19 +34,24 @@ Abstract
|
||||||
sufficiently familiar with the traditional way of creating new
|
sufficiently familiar with the traditional way of creating new
|
||||||
Python types in C.
|
Python types in C.
|
||||||
|
|
||||||
This PEP will introduce the following optional features to types:
|
This PEP will introduce the following features:
|
||||||
|
|
||||||
- create an instance of a type by calling it
|
- a type, like a class, can be a factory for its instances
|
||||||
|
|
||||||
- create a subtype in C by specifying a base type pointer
|
- types can be subtyped in C by specifying a base type pointer
|
||||||
|
|
||||||
- create a subtype in Python using a class statement
|
- types can be subtyped in Python using the class statement
|
||||||
|
|
||||||
- multiple inheritance
|
- multiple inheritance from types (insofar as practical)
|
||||||
|
|
||||||
This PEP builds on PEP 252, which adds standard introspection to
|
- the standard coercions (int, tuple, str etc.) will be the
|
||||||
|
corresponding type objects
|
||||||
|
|
||||||
|
- a standard type hierarchy
|
||||||
|
|
||||||
|
This PEP builds on pep-0252, which adds standard introspection to
|
||||||
types; in particular, types are assumed to have e.g. a __hash__
|
types; in particular, types are assumed to have e.g. a __hash__
|
||||||
method when the type object defines the tp_hash slot. PEP 252 also
|
method when the type object defines the tp_hash slot. pep-0252 also
|
||||||
adds a dictionary to type objects which contains all methods. At
|
adds a dictionary to type objects which contains all methods. At
|
||||||
the Python level, this dictionary is read-only; at the C level, it
|
the Python level, this dictionary is read-only; at the C level, it
|
||||||
is accessible directly (but modifying it is not recommended except
|
is accessible directly (but modifying it is not recommended except
|
||||||
|
@ -76,12 +81,13 @@ Metatypes
|
||||||
"Don Beaudry hook", which says that if a metatype is callable, its
|
"Don Beaudry hook", which says that if a metatype is callable, its
|
||||||
instances (which are regular types) can be subclassed (really
|
instances (which are regular types) can be subclassed (really
|
||||||
subtyped) using a Python class statement. We will use this rule
|
subtyped) using a Python class statement. We will use this rule
|
||||||
to support subtyping of built-in types, and in the process we will
|
to support subtyping of built-in types, and in fact it greatly
|
||||||
introduce some additional metatypes, and a "metametatype". (The
|
simplifies the logic of class creation to always simply call the
|
||||||
metametatype is nothing unusual; Python's type system allows any
|
metatype. When no base class is specified, a default metatype is
|
||||||
number of metalevels.)
|
called -- the default metatype is the "ClassType" object, so the
|
||||||
|
class statement will behave as before in the normal case.
|
||||||
|
|
||||||
Note that Python uses the concept of metatypes or metaclasses in a
|
Python uses the concept of metatypes or metaclasses in a
|
||||||
different way than Smalltalk. In Smalltalk-80, there is a
|
different way than Smalltalk. In Smalltalk-80, there is a
|
||||||
hierarchy of metaclasses that mirrors the hierarchy of regular
|
hierarchy of metaclasses that mirrors the hierarchy of regular
|
||||||
classes, metaclasses map 1-1 to classes (except for some funny
|
classes, metaclasses map 1-1 to classes (except for some funny
|
||||||
|
@ -104,7 +110,8 @@ Metatypes
|
||||||
Instantiation by calling the type object
|
Instantiation by calling the type object
|
||||||
|
|
||||||
Traditionally, for each type there is at least one C function that
|
Traditionally, for each type there is at least one C function that
|
||||||
creates instances of the type. This function has to take care of
|
creates instances of the type (e.g. PyInt_FromLong(),
|
||||||
|
PyTuple_New() and so on). This function has to take care of
|
||||||
both allocating memory for the object and initializing that
|
both allocating memory for the object and initializing that
|
||||||
memory. As of Python 2.0, it also has to interface with the
|
memory. As of Python 2.0, it also has to interface with the
|
||||||
garbage collection subsystem, if the type chooses to participate
|
garbage collection subsystem, if the type chooses to participate
|
||||||
|
@ -127,24 +134,17 @@ Instantiation by calling the type object
|
||||||
can't be called. Now we're adding a tp_call slot to the metatype,
|
can't be called. Now we're adding a tp_call slot to the metatype,
|
||||||
which makes all types "callable" in a trivial sense. But
|
which makes all types "callable" in a trivial sense. But
|
||||||
obviously the metatype's tp_call implementation doesn't know how
|
obviously the metatype's tp_call implementation doesn't know how
|
||||||
to initialize individual types. So the type defines a new slot,
|
to initialize the instances of individual types. So the type
|
||||||
tp_construct, which is invoked by the metatype's tp_call slot. If
|
defines a new slot, tp_new, which is invoked by the metatype's
|
||||||
the tp_construct slot is NULL, the metatype's tp_call issues a
|
tp_call slot. If the tp_new slot is NULL, the metatype's tp_call
|
||||||
nice error message: the type isn't callable.
|
issues a nice error message: the type isn't callable.
|
||||||
|
|
||||||
We already know that tp_construct is responsible for initializing
|
This mechanism gives the maximum freedom to the type: a type's
|
||||||
the object (this will be important for subtyping too). Who should
|
tp_new doesn't necessarily have to return a new object, or even an
|
||||||
be responsible for allocation of the new object? Either the
|
object that is an instance of the type (although the latter should
|
||||||
metatype's tp_call can allocate the object, or the type's
|
be rare).
|
||||||
tp_construct can allocate it. The solution is copied from typical
|
|
||||||
C++ implementations: if the metatype's tp_call allocates storage
|
HIRO
|
||||||
for the object it passes the storage as a pointer to the type's
|
|
||||||
tp_construct; if the metatype's tp_call does not allocate storage,
|
|
||||||
it passes a NULL pointer to the type's tp_call in which case the
|
|
||||||
type allocates the storage itself. This moves the policy decision
|
|
||||||
to the metatype, and different metatypes may have different
|
|
||||||
policies. The mechanisms are fixed though: either the metatype's
|
|
||||||
tp_call allocates storage, or the type's tp_construct allocates.
|
|
||||||
|
|
||||||
The deallocation mechanism chosen should match the allocation
|
The deallocation mechanism chosen should match the allocation
|
||||||
mechanism: an allocation policy should prescribe both the
|
mechanism: an allocation policy should prescribe both the
|
||||||
|
@ -279,7 +279,7 @@ Subtyping in C
|
||||||
PyType_InitDict() must be called. This replaces zero slots in the
|
PyType_InitDict() must be called. This replaces zero slots in the
|
||||||
subtype with the value of the corresponding base type slots. It
|
subtype with the value of the corresponding base type slots. It
|
||||||
also fills in tp_dict, the type's dictionary; this is more a
|
also fills in tp_dict, the type's dictionary; this is more a
|
||||||
matter of PEP 252.
|
matter of pep-0252.
|
||||||
|
|
||||||
The subtype's tp_dealloc slot deserves special attention. It must
|
The subtype's tp_dealloc slot deserves special attention. It must
|
||||||
uninitialize and deallocate the object in an orderly manner: first
|
uninitialize and deallocate the object in an orderly manner: first
|
||||||
|
@ -329,7 +329,7 @@ Subtyping in Python
|
||||||
Assume B is a type object. Since type objects are objects, and
|
Assume B is a type object. Since type objects are objects, and
|
||||||
every object has a type, B has a type. B's type is accessible via
|
every object has a type, B has a type. B's type is accessible via
|
||||||
type(B) or B.__class__ (the latter notation is new for types; it
|
type(B) or B.__class__ (the latter notation is new for types; it
|
||||||
is introduced in PEP 252). Let's say B's type is M (for
|
is introduced in pep-0252). Let's say B's type is M (for
|
||||||
Metatype). The class statement will create a new type, C. Since
|
Metatype). The class statement will create a new type, C. Since
|
||||||
C will be a type object just like B, we view the creation of C as
|
C will be a type object just like B, we view the creation of C as
|
||||||
an instantiation of the metatype, M. The information that needs
|
an instantiation of the metatype, M. The information that needs
|
||||||
|
@ -373,6 +373,29 @@ Subtyping in Python
|
||||||
dictionary (the third argument to the call to M).
|
dictionary (the third argument to the call to M).
|
||||||
|
|
||||||
|
|
||||||
|
Implementation
|
||||||
|
|
||||||
|
A prototype implementation of this PEP is available from CVS as a
|
||||||
|
branch named "descr-branch". To experiment with this
|
||||||
|
implementation, proceed to check out Python from CVS according to
|
||||||
|
the instructions at http://sourceforge.net/cvs/?group_id=5470 but
|
||||||
|
add the arguments "-r descr-branch" to the cvs checkout command.
|
||||||
|
(You can also start with an existing checkout and do "cvs update
|
||||||
|
-r descr-branch".) For some examples of the features described
|
||||||
|
here, see the file Lib/test/test_descr.py and the extension module
|
||||||
|
Modules/spam.c.
|
||||||
|
|
||||||
|
Note: the code in this branch is for pep-0252, pep-0253, and
|
||||||
|
pep-254.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
|
||||||
|
[1] "Putting Metaclasses to Work", by Ira R. Forman and Scott
|
||||||
|
H. Danforth, Addison-Wesley 1999.
|
||||||
|
(http://www.aw.com/product/0,2627,0201433052,00.html)
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
PEP: 259
|
||||||
|
Title: Omit printing newline after newline
|
||||||
|
Version: $Revision$
|
||||||
|
Author: guido@python.org (Guido van Rossum)
|
||||||
|
Status: Draft
|
||||||
|
Type: Standards Track
|
||||||
|
Python-Version: 2.2
|
||||||
|
Created: 11-Jun-2001
|
||||||
|
Post-History: 11-Jun-2001
|
||||||
|
|
||||||
|
Abstract
|
||||||
|
|
||||||
|
Currently, the print statement always appends a newline, unless a
|
||||||
|
trailing comma is used. This means that if we want to print data
|
||||||
|
that already ends in a newline, we get two newlines, unless
|
||||||
|
special precautions are taken.
|
||||||
|
|
||||||
|
I propose to skip printing the newline when it follows a newline
|
||||||
|
that came from data.
|
||||||
|
|
||||||
|
In order to avoid having to add yet another magic variable to file
|
||||||
|
objects, I propose to give the existing 'softspace' variable an
|
||||||
|
extra meaning: a negative value will mean "the last data written
|
||||||
|
ended in a newline so no space *or* newline is required."
|
||||||
|
|
||||||
|
|
||||||
|
Problem
|
||||||
|
|
||||||
|
When printing data that resembles the lines read from a file using
|
||||||
|
a simple loop, double-spacing occurs unless special care is taken:
|
||||||
|
|
||||||
|
>>> for line in open("/etc/passwd").readlines():
|
||||||
|
... print line
|
||||||
|
...
|
||||||
|
root:x:0:0:root:/root:/bin/bash
|
||||||
|
|
||||||
|
bin:x:1:1:bin:/bin:
|
||||||
|
|
||||||
|
daemon:x:2:2:daemon:/sbin:
|
||||||
|
|
||||||
|
(etc.)
|
||||||
|
|
||||||
|
>>>
|
||||||
|
|
||||||
|
While there are easy work-arounds, this is often noticed only
|
||||||
|
during testing and requires an extra edit-test roundtrip; the
|
||||||
|
fixed code is uglier and harder to maintain.
|
||||||
|
|
||||||
|
|
||||||
|
Proposed Solution
|
||||||
|
|
||||||
|
In the PRINT_ITEM opcode in ceval.c, when a string object is
|
||||||
|
printed, a check is already made that looks at the last character
|
||||||
|
of that string. Currently, if that last character is a whitespace
|
||||||
|
character other than space, the softspace flag is reset to zero;
|
||||||
|
this suppresses the space between two items if the first item is a
|
||||||
|
string ending in newline, tab, etc. (but not when it ends in a
|
||||||
|
space). Otherwise the softspace flag is set to one.
|
||||||
|
|
||||||
|
The proposal changes this test slightly so that softspace is set
|
||||||
|
to:
|
||||||
|
|
||||||
|
-1 -- if the last object written is a string ending in a
|
||||||
|
newline
|
||||||
|
|
||||||
|
0 -- if the last object written is a string ending in a
|
||||||
|
whitespace character that's neither space nor newline
|
||||||
|
|
||||||
|
1 -- in all other cases (including the case when the last
|
||||||
|
object written is an empty string or not a string)
|
||||||
|
|
||||||
|
Then, the PRINT_NEWLINE opcode, printing of the newline is
|
||||||
|
suppressed if the value of softspace is negative; in any case the
|
||||||
|
softspace flag is reset to zero.
|
||||||
|
|
||||||
|
|
||||||
|
Scope
|
||||||
|
|
||||||
|
This only affects printing of 8-bit strings. It doesn't affect
|
||||||
|
Unicode, although that could be considered a bug in the Unicode
|
||||||
|
implementation. It doesn't affect other objects whose string
|
||||||
|
representation happens to end in a newline character.
|
||||||
|
|
||||||
|
|
||||||
|
Risks
|
||||||
|
|
||||||
|
This change breaks some existing code. For example:
|
||||||
|
|
||||||
|
print "Subject: PEP 259\n"
|
||||||
|
print message_body
|
||||||
|
|
||||||
|
In current Python, this produces a blank line separating the
|
||||||
|
subject from the message body; with the proposed change, the body
|
||||||
|
begins immediately below the subject. This is not very robust
|
||||||
|
code anyway; it is better written as
|
||||||
|
|
||||||
|
print "Subject: PEP 259"
|
||||||
|
print
|
||||||
|
print message_body
|
||||||
|
|
||||||
|
In the test suite, only test_StringIO (which explicitly tests for
|
||||||
|
this feature) breaks.
|
||||||
|
|
||||||
|
|
||||||
|
Implementation
|
||||||
|
|
||||||
|
A patch relative to current CVS is here:
|
||||||
|
|
||||||
|
http://sourceforge.net/tracker/index.php?func=detail&aid=432183&group_id=5470&atid=305470
|
||||||
|
|
||||||
|
|
||||||
|
Copyright
|
||||||
|
|
||||||
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
Local Variables:
|
||||||
|
mode: indented-text
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
Loading…
Reference in New Issue