[Python-checkins] CVS: python/nondist/peps pep-0259.txt,NONE,1.1 pep-0000.txt,1.95,1.96 pep-0253.txt,1.2,1.3

Guido van Rossum gvanrossum@users.sourceforge.net
Mon, 11 Jun 2001 13:07:40 -0700


Update of /cvsroot/python/python/nondist/peps
In directory usw-pr-cvs1:/tmp/cvs-serv1958

Modified Files:
	pep-0000.txt pep-0253.txt 
Added Files:
	pep-0259.txt 
Log Message:
PEP 259: Omit printing newline after newline

--- NEW FILE: pep-0259.txt ---
PEP: 259
Title: Omit printing newline after newline
Version: $Revision: 1.1 $
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:

Index: pep-0000.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v
retrieving revision 1.95
retrieving revision 1.96
diff -C2 -r1.95 -r1.96
*** pep-0000.txt	2001/06/06 05:56:34	1.95
--- pep-0000.txt	2001/06/11 20:07:37	1.96
***************
*** 61,64 ****
--- 61,65 ----
   S   257  pep-0257.txt  Docstring Conventions                  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)
***************
*** 185,188 ****
--- 186,190 ----
   S   257  pep-0257.txt  Docstring Conventions                  Goodger
   S   258  pep-0258.txt  DPS Generic Implementation Details     Goodger
+  S   259  pep-0259.txt  Omit printing newline after newline    van Rossum
  
  

Index: pep-0253.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0253.txt,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** pep-0253.txt	2001/05/15 01:36:46	1.2
--- pep-0253.txt	2001/06/11 20:07:37	1.3
***************
*** 35,51 ****
      Python types in C.
  
!     This PEP will introduce the following optional features to types:
  
!     - create an instance of a type by calling it
  
!     - create a subtype in C by specifying a base type pointer
  
!     - create a subtype in Python using a class statement
  
!     - multiple inheritance
  
!     This PEP builds on PEP 252, which adds standard introspection to
      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
      adds a dictionary to type objects which contains all methods.  At
      the Python level, this dictionary is read-only; at the C level, it
--- 35,56 ----
      Python types in C.
  
!     This PEP will introduce the following features:
  
!     - a type, like a class, can be a factory for its instances
  
!     - types can be subtyped in C by specifying a base type pointer
  
!     - types can be subtyped in Python using the class statement
  
!     - multiple inheritance from types (insofar as practical)
  
!     - 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__
!     method when the type object defines the tp_hash slot.  pep-0252 also
      adds a dictionary to type objects which contains all methods.  At
      the Python level, this dictionary is read-only; at the C level, it
***************
*** 77,86 ****
      instances (which are regular types) can be subclassed (really
      subtyped) using a Python class statement.  We will use this rule
!     to support subtyping of built-in types, and in the process we will
!     introduce some additional metatypes, and a "metametatype". (The
!     metametatype is nothing unusual; Python's type system allows any
!     number of metalevels.)
  
!     Note that Python uses the concept of metatypes or metaclasses in a
      different way than Smalltalk.  In Smalltalk-80, there is a
      hierarchy of metaclasses that mirrors the hierarchy of regular
--- 82,92 ----
      instances (which are regular types) can be subclassed (really
      subtyped) using a Python class statement.  We will use this rule
!     to support subtyping of built-in types, and in fact it greatly
!     simplifies the logic of class creation to always simply call the
!     metatype.  When no base class is specified, a default metatype is
!     called -- the default metatype is the "ClassType" object, so the
!     class statement will behave as before in the normal case.
  
!     Python uses the concept of metatypes or metaclasses in a
      different way than Smalltalk.  In Smalltalk-80, there is a
      hierarchy of metaclasses that mirrors the hierarchy of regular
***************
*** 105,109 ****
  
      Traditionally, for each type there is at least one C function that
!     creates instances of the type.  This function has to take care of
      both allocating memory for the object and initializing that
      memory.  As of Python 2.0, it also has to interface with the
--- 111,116 ----
  
      Traditionally, for each type there is at least one C function that
!     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
      memory.  As of Python 2.0, it also has to interface with the
***************
*** 128,149 ****
      which makes all types "callable" in a trivial sense.  But
      obviously the metatype's tp_call implementation doesn't know how
!     to initialize individual types.  So the type defines a new slot,
!     tp_construct, which is invoked by the metatype's tp_call slot.  If
!     the tp_construct slot is NULL, the metatype's tp_call issues a
!     nice error message: the type isn't callable.
! 
!     We already know that tp_construct is responsible for initializing
!     the object (this will be important for subtyping too).  Who should
!     be responsible for allocation of the new object? Either the
!     metatype's tp_call can allocate the object, or the type's
!     tp_construct can allocate it.  The solution is copied from typical
!     C++ implementations: if the metatype's tp_call allocates storage
!     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
--- 135,149 ----
      which makes all types "callable" in a trivial sense.  But
      obviously the metatype's tp_call implementation doesn't know how
!     to initialize the instances of individual types.  So the type
!     defines a new slot, tp_new, which is invoked by the metatype's
!     tp_call slot.  If the tp_new slot is NULL, the metatype's tp_call
!     issues a nice error message: the type isn't callable.
! 
!     This mechanism gives the maximum freedom to the type: a type's
!     tp_new doesn't necessarily have to return a new object, or even an
!     object that is an instance of the type (although the latter should
!     be rare).
! 
!     HIRO
  
      The deallocation mechanism chosen should match the allocation
***************
*** 280,284 ****
      subtype with the value of the corresponding base type slots.  It
      also fills in tp_dict, the type's dictionary; this is more a
!     matter of PEP 252.
  
      The subtype's tp_dealloc slot deserves special attention.  It must
--- 280,284 ----
      subtype with the value of the corresponding base type slots.  It
      also fills in tp_dict, the type's dictionary; this is more a
!     matter of pep-0252.
  
      The subtype's tp_dealloc slot deserves special attention.  It must
***************
*** 330,334 ****
      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
!     is introduced in PEP 252).  Let's say B's type is M (for
      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
--- 330,334 ----
      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
!     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
      C will be a type object just like B, we view the creation of C as
***************
*** 372,375 ****
--- 372,398 ----
      tp_dict slot is updated with the contents of the namespace
      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)