classification
Title: BadStatusLine is hell to debug
Type: Stage:
Components: Library (Lib) Versions: Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: aswan, djc, jakemcguire, martin.panter, merwok
Priority: normal Keywords:

Created on 2009-12-03 15:52 by djc, last changed 2017-03-12 21:48 by martin.panter. This issue is now closed.

Messages (8)
msg95934 - (view) Author: Dirkjan Ochtman (djc) * (Python committer) Date: 2009-12-03 15:52
For whatever reason, BadStatusLine tracebacks often don't show the line
passed into them. Given the errr, heavy architecture of httplib, this
makes it pretty bad to debug. It's not clear to me why this is:

Traceback (most recent call last):
  File "/home/djc/src/couchdb-python/couchdb/tests/client.py", line 138,
in test_attachment_crud_with_files
    doc = self.db['foo']
  File "/home/djc/src/couchdb-python/couchdb/client.py", line 293, in
__getitem__
    _, _, data = self.resource.get(id)
  File "/home/djc/src/couchdb-python/couchdb/http.py", line 333, in get
    return self._request('GET', path, headers=headers, **params)
  File "/home/djc/src/couchdb-python/couchdb/http.py", line 350, in _request
    credentials=self.credentials)
  File "/home/djc/src/couchdb-python/couchdb/http.py", line 179, in request
    resp = _try_request()
  File "/home/djc/src/couchdb-python/couchdb/http.py", line 167, in
_try_request
    return conn.getresponse()
  File "/usr/lib/python2.6/httplib.py", line 950, in getresponse
  File "/usr/lib/python2.6/httplib.py", line 390, in begin
  File "/usr/lib/python2.6/httplib.py", line 354, in _read_status
BadStatusLine

However, some interactive testing shows that this should work:

djc@enrai couchdb-python $ python
Python 2.6.2 (r262:71600, Oct  5 2009, 12:18:48)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class CrapShoot(Exception):
...     def __init__(self, a):
...             self.args = a,
...
>>> raise CrapShoot('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.CrapShoot: a
>>> class ParentExc(Exception):
...     pass
...
>>> class CrapShoot(ParentExc):
...     def __init__(self, a):
...             self.args = a,
...
>>> raise CrapShoot('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.CrapShoot: a
>>>

Definition of BadStatusLine:

class BadStatusLine(HTTPException):
    def __init__(self, line):
        self.args = line,
        self.line = line

class HTTPException(Exception):
    # Subclasses that define an __init__ must call Exception.__init__
    # or define self.args.  Otherwise, str() will fail.
    pass

The note here seems like a cautionary but insufficient tale...
msg95935 - (view) Author: Dirkjan Ochtman (djc) * (Python committer) Date: 2009-12-03 15:59
Also, it might be useful here if it showed repr(line) instead of just
line, but that'd just be icing on the cake.
msg95969 - (view) Author: Jake McGuire (jakemcguire) Date: 2009-12-04 18:34
I think what's happening is that your connection is being closed due to 
inactivity, so the status line that comes back is empty.  Printing 
repr(line) would probably make the emptiness clear, but maybe the httplib 
code should put in a more specific message in this case...
msg100003 - (view) Author: Dirkjan Ochtman (djc) * (Python committer) Date: 2010-02-24 04:50
Fixed up the repr in r48417.
msg100004 - (view) Author: Éric Araujo (merwok) * (Python committer) Date: 2010-02-24 04:53
Actually r78417.
msg171324 - (view) Author: Andrew Swan (aswan) Date: 2012-09-25 23:48
I just got tripped up by this change, I wanted to catch the specific case of an http server closing a connection and assumed that the following would work:

try:
  resp = conn.getresponse()
except httplib.BadStatusLine, e:
  if len(e.line) == 0:
    # server closed...
  else:
    raise

That doesn't work since e.line holds the representation of the empty string instead of just holding the empty string.  I think the fragment above would be a much better way to write this test, the current alterntative of:
  if e.line == "''":
is hopelessly obscure.

Seems like the original fix should have been to add __repr__ to BadStatusLine rather than changing its contents.  Can this be revisited?
msg231405 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2014-11-20 02:22
As far as I can tell, the “line” attribute isn’t documented anyway. But Issue 8450 is opened about improving the exception when the connection is closed.
msg289511 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2017-03-12 21:48
This change was only made in 2.7a4, not 2.6
History
Date User Action Args
2017-03-12 21:48:19martin.pantersetmessages: + msg289511
versions: + Python 2.7, - Python 2.6
2014-11-20 02:22:23martin.pantersetnosy: + martin.panter
messages: + msg231405
2012-09-25 23:48:11aswansetnosy: + aswan
messages: + msg171324
2010-02-24 04:53:39merwoksetnosy: + merwok
messages: + msg100004
2010-02-24 04:50:42djcsetstatus: open -> closed
resolution: fixed
messages: + msg100003
2009-12-04 18:34:22jakemcguiresetnosy: + jakemcguire
messages: + msg95969
2009-12-03 15:59:20djcsetmessages: + msg95935
2009-12-03 15:52:43djccreate