classification
Title: HTTPResponse instance has no attribute 'fileno'
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: orsenthil Nosy List: BreamoreBoy, ajaksu2, brett.cannon, georg.brandl, jjlee, kdwyer, kevindication, orsenthil
Priority: normal Keywords: easy, patch

Created on 2005-10-16 14:41 by kevindication, last changed 2010-09-21 02:11 by orsenthil. This issue is now closed.

Files
File name Uploaded Description Edit
httplib_fileno_2.diff ajaksu2, 2009-02-11 17:16 Adds a 'fileno' property to HTTPResponse
urllib_fileno_2.diff ajaksu2, 2009-02-11 17:17 Adds a 'fileno' property to addinfourl
test_pyclbr_property.diff ajaksu2, 2009-02-11 20:18 Workaround test_pyclbr not known "property" and not finding attrs set in __init__
Messages (14)
msg60827 - (view) Author: Kevin Dwyer (kevindication) Date: 2005-10-16 14:41
In python2.3, the following code works.  In python2.4
it fails with an AttributeError:

>>> import urllib2
>>> request = urllib2.Request("http://pheared.net")
>>> opener = urllib2.build_opener()
>>> r = opener.open(request)
>>> r.fileno()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/lib/python2.4/socket.py", line 246, in fileno
    return self._sock.fileno()
AttributeError: HTTPResponse instance has no attribute
'fileno'

Without a fileno it's hard to do things like select.
msg60828 - (view) Author: Kevin Dwyer (kevindication) Date: 2005-10-16 15:08
Logged In: YES 
user_id=285914

I think the problem is at line 1010 in urllib2.py.

--- urllib2.py-orig     2005-10-16 11:04:30.000000000 -0400
+++ urllib2.py  2005-10-16 11:05:02.000000000 -0400
@@ -1007,7 +1007,7 @@
         # out of socket._fileobject() and into a base class.

         r.recv = r.read
-        fp = socket._fileobject(r)
+        fp = socket._fileobject(r.fp)

         resp = addinfourl(fp, r.msg, req.get_full_url())
         resp.code = r.status

msg60829 - (view) Author: Kevin Dwyer (kevindication) Date: 2005-10-16 15:23
Logged In: YES 
user_id=285914

Actually that's not entirely correct.  The fix is probably
more like the other hack in there:

--- urllib2.py-orig     2005-10-16 11:19:34.000000000 -0400
+++ urllib2.py  2005-10-16 11:22:30.000000000 -0400
@@ -1007,6 +1007,7 @@
         # out of socket._fileobject() and into a base class.

         r.recv = r.read
+        r.fileno = r.fp.fileno
         fp = socket._fileobject(r)

         resp = addinfourl(fp, r.msg, req.get_full_url())
msg81437 - (view) Author: Daniel Diniz (ajaksu2) (Python triager) Date: 2009-02-09 04:57
Besides being outdated, the OP shows it's trivial to access the fileno:
"r.fileno = r.fp.fileno". I suggest closing.
msg81579 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-02-10 18:44
Well, easy access is not the point. If the object is supposed to have
the file-like interface, and can provide a fileno(), it should.
msg81585 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-02-10 19:34
Georg is right and this has been fixed apparently in 3.0, leaving 2.7
and older broken.

There are two possible solutions to this. One is to change
socket._fileobject.fileno() to simply try self._sock.fp.fileno() if
self._sock.fileno() does not exist. The other option is to add a
__getattr__ to httplib.HTTPResponse to redirect to self.fp. Anyone have
an opinion?
msg81588 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-02-10 19:44
Another option is to change urllib.addinfourl to look for fileno() on an
HTTPResponse object.
msg81644 - (view) Author: Daniel Diniz (ajaksu2) (Python triager) Date: 2009-02-11 14:18
OK, I'll work on a test + patch.
msg81651 - (view) Author: Daniel Diniz (ajaksu2) (Python triager) Date: 2009-02-11 16:56
IMHO, using a fileno property looks better than __getattr__. Setting an
attribute in init works too, unless fp changes during the object life
(then 3.x is broken IIUC).

It works OK as a property of either urllib.addinfourl or of
httplib.HTTPResponse (socket would work, but is this broken there or a
higher layer). 

Tests and fixes for both solutions attached. As soon as one is chosen,
some docs on fileno would be nice, even for 3.x.


This (current) test in test_urllibnet.py passes, but I don't see how to
improve it, assuming it should fail/detect this bug (maybe self.urlopen
isn't testing urllib.urlopen correctly?):

    def test_fileno(self):
        if (sys.platform in ('win32',) or
                not hasattr(os, 'fdopen')):
            # On Windows, socket handles are not file descriptors; this
            # test can't pass on Windows.
            return
        # Make sure fd returned by fileno is valid.
        open_url = self.urlopen("http://www.python.org/")
        fd = open_url.fileno()
        FILE = os.fdopen(fd)
msg81653 - (view) Author: Daniel Diniz (ajaksu2) (Python triager) Date: 2009-02-11 17:16
Hmm, always run all the tests :)

fileno is set in test_urllib2. New patches.
msg81663 - (view) Author: Daniel Diniz (ajaksu2) (Python triager) Date: 2009-02-11 20:18
The urllib patch breaks test_pyclbr because test_pyclbr can't handle
properties. I think the test is wrong here, hence the hack attached...
otherwise, let's go with httplib.
msg110437 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2010-07-16 13:28
These patches are small and marked as easy, can they be accepted?
msg117013 - (view) Author: Senthil Kumaran (orsenthil) * (Python committer) Date: 2010-09-21 01:42
Fix committed in revision 84932.  A property based fileno was not required, because it is hardly set, it is always often a read-only attribute. Also, py3k behavior is same as the current fix.
msg117018 - (view) Author: Senthil Kumaran (orsenthil) * (Python committer) Date: 2010-09-21 02:11
Documented it in r84933, r84934 and r84935
History
Date User Action Args
2010-09-21 02:11:13orsenthilsetstatus: open -> closed
resolution: fixed
messages: + msg117018

stage: patch review -> resolved
2010-09-21 01:42:54orsenthilsetmessages: + msg117013
2010-08-24 03:18:17orsenthilsetassignee: orsenthil
2010-08-22 01:09:20BreamoreBoysetversions: + Python 2.7, - Python 2.6
2010-07-17 09:17:46kdwyersetnosy: + kevindication
2010-07-16 13:28:49BreamoreBoysetnosy: + BreamoreBoy
messages: + msg110437
2009-04-22 17:26:47ajaksu2setkeywords: + easy
2009-02-13 01:20:11ajaksu2setnosy: + jjlee
2009-02-12 18:27:34ajaksu2setnosy: + orsenthil
versions: - Python 2.5, Python 2.4, Python 2.7
2009-02-11 20:18:11ajaksu2setfiles: + test_pyclbr_property.diff
messages: + msg81663
2009-02-11 17:18:17ajaksu2setfiles: - urllib_fileno.diff
2009-02-11 17:17:53ajaksu2setfiles: + urllib_fileno_2.diff
2009-02-11 17:17:20ajaksu2setfiles: - httplib_fileno.diff
2009-02-11 17:16:56ajaksu2setfiles: + httplib_fileno_2.diff
messages: + msg81653
2009-02-11 16:58:13ajaksu2setfiles: + urllib_fileno.diff
type: behavior
components: + Library (Lib), - None
2009-02-11 16:56:54ajaksu2setfiles: + httplib_fileno.diff
keywords: + patch
messages: + msg81651
stage: test needed -> patch review
2009-02-11 14:18:48ajaksu2setmessages: + msg81644
2009-02-10 19:44:15brett.cannonsetmessages: + msg81588
2009-02-10 19:34:49brett.cannonsetnosy: + brett.cannon
stage: test needed
messages: + msg81585
versions: + Python 2.6, Python 2.5, Python 2.4, Python 2.7
2009-02-10 18:44:29georg.brandlsetnosy: + georg.brandl
messages: + msg81579
2009-02-09 04:57:18ajaksu2setnosy: + ajaksu2
messages: + msg81437
2005-10-16 14:41:19kevindicationcreate