isinstance(.., file) for Python 3

2012-11-08 Thread Ulrich Eckhardt

Hi!

I have two problems that are related and that I'd like to solve together.

Firstly, I have code that allows either a file or a string representing 
its content as parameter. If the parameter is a file, the content is 
read from the file. In Python 2, I used isinstance(p, file) to 
determine whether the parameter p is a file. In Python 3, the 
returnvalue of open() is of type _io.TextIOWrapper, while the built-in 
class file doesn't exist, so I can't use that code.


Secondly, checking for the type is kind-of ugly, because it means that I 
can't use an object that fits but that doesn't have the right type. In 
other words, it breaks duck-typing. This is already broken in the Python 
2 code, but since I have to touch the code anyway, I might as well fix 
it on the way.


If possible, I'm looking for a solution that works for Pythons 2 and 3, 
since I'm not fully through the conversion yet and have clients that 
might use the older snake for some time before shedding their skin.


Suggestions?

Uli


--
http://mail.python.org/mailman/listinfo/python-list


Re: isinstance(.., file) for Python 3

2012-11-08 Thread MRAB

On 2012-11-08 12:05, Ulrich Eckhardt wrote:

Hi!

I have two problems that are related and that I'd like to solve together.

Firstly, I have code that allows either a file or a string representing
its content as parameter. If the parameter is a file, the content is
read from the file. In Python 2, I used isinstance(p, file) to
determine whether the parameter p is a file. In Python 3, the
returnvalue of open() is of type _io.TextIOWrapper, while the built-in
class file doesn't exist, so I can't use that code.

Secondly, checking for the type is kind-of ugly, because it means that I
can't use an object that fits but that doesn't have the right type. In
other words, it breaks duck-typing. This is already broken in the Python
2 code, but since I have to touch the code anyway, I might as well fix
it on the way.

If possible, I'm looking for a solution that works for Pythons 2 and 3,
since I'm not fully through the conversion yet and have clients that
might use the older snake for some time before shedding their skin.

Suggestions?


Instead of checking whether it's a file, check whether it's a string!
--
http://mail.python.org/mailman/listinfo/python-list


Re: isinstance(.., file) for Python 3

2012-11-08 Thread Chris Angelico
On Thu, Nov 8, 2012 at 11:05 PM, Ulrich Eckhardt
ulrich.eckha...@dominolaser.com wrote:
 Firstly, I have code that allows either a file or a string representing its
 content as parameter. If the parameter is a file, the content is read from
 the file. In Python 2, I used isinstance(p, file) to determine whether the
 parameter p is a file...

Can you use the inverted check isinstance(p, str)? It's more likely
that you'll want to pass a file-like object than a string-like object.
This would work on Python 2 as well, though it's semantically
different; to safely check for both Unicode and bytes strings on both
Py2 and Py3, this may work:

# Once-off:
try:
basestring
except NameError:
basestring = (str, bytes)

# Is p a string?
if isinstance(p, basestring):
pass

It abuses the fact that isinstance will happily accept the
'basestring' common supertype of both strings in Python 2, but will
equally happily accept a tuple of types.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: isinstance(.., file) for Python 3

2012-11-08 Thread Peter Otten
Ulrich Eckhardt wrote:

 Hi!
 
 I have two problems that are related and that I'd like to solve together.
 
 Firstly, I have code that allows either a file or a string representing
 its content as parameter. If the parameter is a file, the content is
 read from the file. In Python 2, I used isinstance(p, file) to
 determine whether the parameter p is a file. In Python 3, the
 returnvalue of open() is of type _io.TextIOWrapper, while the built-in
 class file doesn't exist, so I can't use that code.
 
 Secondly, checking for the type is kind-of ugly, because it means that I
 can't use an object that fits but that doesn't have the right type. In
 other words, it breaks duck-typing. This is already broken in the Python
 2 code, but since I have to touch the code anyway, I might as well fix
 it on the way.
 
 If possible, I'm looking for a solution that works for Pythons 2 and 3,
 since I'm not fully through the conversion yet and have clients that
 might use the older snake for some time before shedding their skin.
 
 Suggestions?

In order of obviousness:
hasattr(p, read)
not isinstance(p, str)
iter(p) is p

Or you change the interface

def f(*, contents=None, file=None):
if contents is None:
with open(file) as f:
contents = f.read()
... # work with contents



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: isinstance(.., file) for Python 3

2012-11-08 Thread Steven D'Aprano
On Thu, 08 Nov 2012 13:05:22 +0100, Ulrich Eckhardt wrote:

 Firstly, I have code that allows either a file or a string representing
 its content as parameter. If the parameter is a file, the content is
 read from the file. In Python 2, I used isinstance(p, file) to
 determine whether the parameter p is a file. In Python 3, the
 returnvalue of open() is of type _io.TextIOWrapper, 

Incorrect.

py type(open('x', 'wb'))
class '_io.BufferedWriter'

The type returned by open will depend on what you open and how you open 
it.

 while the built-in
 class file doesn't exist, so I can't use that code.

import io
file = io._IOBase

will probably work. But consider it a little smelly, since you're relying 
on an implementation detail.


 Secondly, checking for the type is kind-of ugly, because it means that I
 can't use an object that fits but that doesn't have the right type. In
 other words, it breaks duck-typing. This is already broken in the Python
 2 code, but since I have to touch the code anyway, I might as well fix
 it on the way.

if hasattr(obj, 'read'):
# object is file-like enough to treat as a file
pass

That means that you can also use io.StringIO objects as pseudo-files too.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: isinstance(.., file) for Python 3

2012-11-08 Thread Duncan Booth
Ulrich Eckhardt ulrich.eckha...@dominolaser.com wrote:

 If possible, I'm looking for a solution that works for Pythons 2 and 3, 
 since I'm not fully through the conversion yet and have clients that 
 might use the older snake for some time before shedding their skin.
 
 Suggestions?

Why bother checking types at all?

def foo(file_or_string):
try:
data = file_or_string.read()
except AttributeError:
data = file_or_string
... use data ...

-- 
Duncan Booth http://kupuguy.blogspot.com
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: isinstance(.., file) for Python 3

2012-11-08 Thread Stefan Behnel
Duncan Booth, 08.11.2012 14:58:
 Ulrich Eckhardt wrote:
 If possible, I'm looking for a solution that works for Pythons 2 and 3, 
 since I'm not fully through the conversion yet and have clients that 
 might use the older snake for some time before shedding their skin.

 Suggestions?
 
 Why bother checking types at all?
 
 def foo(file_or_string):
 try:
 data = file_or_string.read()
 except AttributeError:
 data = file_or_string
 ... use data ...

Or, a tiny bit more safely:

try:
read = file_or_string.read
except AttributeError:
data = file_or_string
else:
data = read()

I'd rather go with one of the previous solutions, though.

Stefan


-- 
http://mail.python.org/mailman/listinfo/python-list