google / grumpy

Grumpy is a Python to Go source code transcompiler and runtime.
Apache License 2.0
10.54k stars 648 forks source link

Trailing space in output of print with comma #223

Open S-YOU opened 7 years ago

S-YOU commented 7 years ago

Minor issue, but reporting what I noticed. For given code.

for i in range(2):
  for j in range(2):
    print j,
  print
% python hello.py
0 1
0 1
% python hello.py | hexdump
0000000 30 20 31 0a 30 20 31 0a                        
0000008
% cat hello.py | make run | hexdump
0000000 30 20 31 20 0a 30 20 31 20 0a                  
000000a
trotterdylan commented 7 years ago

Ah, good find. Thanks for reporting.

alanjds commented 7 years ago

I am on it. Needed a push to learn Golang anyway...

alanjds commented 7 years ago

From https://docs.python.org/2/reference/simple_stmts.html#the-print-statement:

A space is written before each object is (converted and) written, unless the output system believes it is positioned at the beginning of a line. This is the case (1) when no characters have yet been written to standard output, (2) when the last character written to standard output is a whitespace character except ' ', or (3) when the last write operation on standard output was not a print statement. (In some cases it may be functional to write an empty string to standard output for this reason.)

This seems to be not that easy...

Do not print a space before:

alanjds commented 7 years ago

(and I had not yet found the CPython source of print statement) Found here: https://github.com/python/cpython/blob/2.7/Python/bltinmodule.c#L1580

alanjds commented 7 years ago

Pypy does the right thing, I guess:

$ python hello.py | hexdump
0000000 2030 0a31 2030 0a31
0000008
$ pypy hello.py | hexdump
0000000 2030 0a31 2030 0a31
0000008
$ cat hello.py | make run | hexdump
0000000 2030 2031 300a 3120 0a20
000000a
$ uname -a
Linux b2wdill 4.4.0-59-generic #80-Ubuntu SMP Fri Jan 6 17:47:47 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

And the pypy code is so easier to understand!

Update:

Just to note: There is 2 pypy print implementations:

The "print STATEMENT" implementation is attached to a specific bytecode on Pypy.

alanjds commented 7 years ago

Looks like the way to go is via the softspace attribute of file objects.

I had updated grumpy File but it seems to be not available yet. Is there anything yet I need to do to access this in Python code?

diff --git a/runtime/file.go b/runtime/file.go
index a5b1c46..b775213 100644
--- a/runtime/file.go
+++ b/runtime/file.go
@@ -37,2 +37,3 @@ type File struct {
        open        bool
+       softspace   int
        reader      *bufio.Reader
@@ -131,2 +132,3 @@ func fileInit(f *Frame, o *Object, args Args, _ KWArgs) (*Object, *BaseException
        file.file = osFile
+       file.softspace = 0
        file.reader = bufio.NewReader(osFile)
$ python -c 'import sys; sys.stdout.softspace'
$ echo 'import sys; sys.stdout.softspace' | make run
AttributeError: 'file' object has no attribute 'softspace'
exit status 1
make: *** [run] Error 1
trotterdylan commented 7 years ago

Discussed on gitter, but the softspace attr is not currently supported. Looks like Alan is going to add it.

alanjds commented 7 years ago

After discussion on gitter, implemented the attr_mode:"rw" allowing native public attributes to be changed via Python. Is on PR #243.

The fix here will start to be implemented on the branch of #243