Author barry
Recipients barry
Date 2016-05-19.23:50:49
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1463701849.23.0.646090431797.issue27066@psf.upfronthosting.co.za>
In-reply-to
Content
Let's say you use a custom opener, and that opener happens to return exactly -1.  You end up with a SystemError because NULL got returned without an exception being set:

def negative(fname, flags):
    return -1


with open('/tmp/foo.txt', 'w', encoding='utf-8', opener=negative) as fp:
    print('oops', file=fp)


% python3 /tmp/foo.py 
Traceback (most recent call last):
  File "/tmp/foo.py", line 5, in <module>
    with open('/tmp/foo.txt', 'w', encoding='utf-8', opener=negative) as fp:
SystemError: <class '_io.FileIO'> returned NULL without setting an error


Anything else and you get a relatively decent exception.  E.g. return -2 and you get an OSError.  Raise an exception and you get that exception.

The problem is pretty clear to see; when an opener is set, after coercing the fd to an integer, the check is made for that integer being -1, and then it jumps right to the exit.

Let's say you return some non-integer, like 'foo'.  Then the _PyLong_AsInt() will fail and a proper exception will be set.  So I think the "if (self->fd == -1)" clause just needs to check for an exception set first and set one if there isn't one before it does the "goto error".  I guess you'd want to see the same exception as if it returned say, -2:

Traceback (most recent call last):
  File "/tmp/foo.py", line 5, in <module>
    with open('/tmp/foo.txt', 'w', encoding='utf-8', opener=negative) as fp:
OSError: [Errno 0] Error: '/tmp/foo.txt'
History
Date User Action Args
2016-05-19 23:50:49barrysetrecipients: + barry
2016-05-19 23:50:49barrysetmessageid: <1463701849.23.0.646090431797.issue27066@psf.upfronthosting.co.za>
2016-05-19 23:50:49barrylinkissue27066 messages
2016-05-19 23:50:49barrycreate