classification
Title: HTTPSConnection __init__ super implementation causes recursion error
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.2, Python 3.3
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: Jelle Zijlstra, eric.araujo, martin.panter, michael.mulich, orsenthil
Priority: normal Keywords:

Created on 2012-01-11 17:53 by michael.mulich, last changed 2016-06-05 02:32 by berker.peksag. This issue is now closed.

Messages (6)
msg151072 - (view) Author: Michael Mulich (michael.mulich) * Date: 2012-01-11 17:53
While working on porting wsgi_intercept to Python 3 I came across a recursion issue with http.client.HTTPSConnection. The following is an lesser extraction of the traceback:


Traceback (most recent call last):
  File ".../wsgi_intercept/test/test_httplib.py", line 28, in test_success
    http = self.make_one(self.domain)
  File ".../wsgi_intercept/test/test_httplib.py", line 40, in make_one
    return http.client.HTTPSConnection(*args)
  File ".../lib/python3.2/http/client.py", line 1075, in __init__
    source_address)
  ...
  File ".../lib/python3.2/http/client.py", line 1075, in __init__
    source_address)
  File ".../lib/python3.2/http/client.py", line 1074, in __init__
    super(HTTPSConnection, self).__init__(host, port, strict, timeout,
RuntimeError: maximum recursion depth exceeded while calling a Python object

Some background information is necessary to explain what is happening here. One, this is a traceback from a test method (make_one) which makes and https connection. Two, wsgi_intercept has overridden http.client.HTTPSConnection with a class that subclasses HTTPSConnection and overrides a few methonds. For more general information, see the PyPI page (http://pypi.python.org/pypi/wsgi_intercept). 

After the wsgi_intercept behavior is invoked the __mro__ of http.client.HTTPSConnection becomes: (<class 'wsgi_intercept.WSGI_HTTPSConnection'>, <class 'http.client.HTTPSConnection'>, <class 'http.client.HTTPConnection'>, <class 'object'>). Because of this we end up recursively running the __init__.

Possible solutions:

1) Fix the issue in http/client.py:1074 by replacing "super(HTTPSConnection, self)" with "super()", which if I'm not mistaken is the recommended usage of super in Python 3.
2) Fix the issue in the wsgi_intercept package.

I was successful with both approaches, but applying the second fix would make the maintenance of wsgi_intercept slightly harder because of the code duplication and round-about-way of calling its parent classes.
msg152520 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2012-02-03 14:41
Hi,

> wsgi_intercept has overridden http.client.HTTPSConnection with a class that subclasses
> HTTPSConnection and overrides a few methonds.
Do you mean that the module is monkey-patched?

> Fix the issue in http/client.py:1074 by replacing "super(HTTPSConnection, self)" with
> "super()", which if I'm not mistaken is the recommended usage of super in Python 3.
Because it’s possible does not mean it’s liked :)  Some of us still dislike that hack.
msg152653 - (view) Author: Michael Mulich (michael.mulich) * Date: 2012-02-05 01:13
Sure does. But that's the point of the package.

Why is this super usage without arguments considered a hack?

>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue13771>
> _______________________________________
msg152668 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2012-02-05 09:57
super without arguments literally relies on a compiler hack.
msg267259 - (view) Author: Jelle Zijlstra (Jelle Zijlstra) * (Python triager) Date: 2016-06-04 15:56
Could you provide a minimal code sample that demonstrates the problem? I'm having a hard time seeing why the http.client code is buggy.
msg267359 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2016-06-05 01:15
My guess is Michael was doing something like

>>> class Monkey(http.client.HTTPSConnection):
...     pass
... 
>>> http.client.HTTPSConnection = Monkey
>>> http.client.HTTPSConnection("bugs.python.org")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/http/client.py", line 1210, in __init__
    source_address)
  [. . .]
  File "/usr/lib/python3.5/http/client.py", line 1210, in __init__
    source_address)
  File "/usr/lib/python3.5/http/client.py", line 1209, in __init__
    super(HTTPSConnection, self).__init__(host, port, timeout,
RecursionError: maximum recursion depth exceeded while calling a Python object

Looking at <https://github.com/cdent/wsgi-intercept/commit/d70dfa9>, I think this problem has been overcome by also overriding __init__(). IMO Python shouldn’t go very far out of its way to support monkey patching, and in this case the workaround was disliked by Eric. Given these two facts and no apparent interest since, I think we should close this.
History
Date User Action Args
2016-06-05 02:32:09berker.peksagsetstatus: open -> closed
resolution: rejected
stage: resolved
2016-06-05 01:15:43martin.pantersetnosy: + martin.panter
messages: + msg267359
2016-06-04 15:56:31Jelle Zijlstrasetnosy: + Jelle Zijlstra
messages: + msg267259
2012-02-05 09:57:54eric.araujosetmessages: + msg152668
2012-02-05 01:13:22michael.mulichsetmessages: + msg152653
2012-02-03 14:41:18eric.araujosetnosy: + eric.araujo
messages: + msg152520
2012-01-11 18:03:00pitrousetnosy: + orsenthil

components: + Library (Lib), - None
versions: - Python 3.4
2012-01-11 17:53:10michael.mulichcreate