PEP: 259
Title: Omit printing newline after newline
Version: $Revision$
Last-Modified: $Date$
Author: guido@python.org (Guido van Rossum)
Status: Rejected
Type: Standards Track
Content-Type: text/x-rst
Created: 11-Jun-2001
Python-Version: 2.2
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


Rejected
========

The user community unanimously rejected this, so I won't pursue
this idea any further.  Frequently heard arguments against
included:

- It is likely to break thousands of CGI scripts.

- Enough magic already (also: no more tinkering with 'print'
  please).


Copyright
=========

This document has been placed in the public domain.


..
  Local Variables:
  mode: indented-text
  indent-tabs-mode: nil
  End:
