Question

I need to monkeypatch requests' Response class (version 1.0.4, current as of this question), to add additional methods.

I have this code:

import requests

class Response(requests.models.Response):
    def hmm(self):
        return 'ok'

requests.models.Response = Response

r = requests.get('http://bbc.co.uk')

print r

It fails when the original Response calls super() - https://github.com/kennethreitz/requests/blob/master/requests/models.py#L391

I think this is because it gets confused, as I have replaced the class, I feel like I'm doing something silly, any ideas? Thanks in advance.

Was it helpful?

Solution

You'd be better off just adding your function directly to the class:

def hmm(self):
    return 'ok'
requests.models.Response.hmm = hmm

This works just fine:

>>> import requests
>>> def hmm(self):
...     return 'ok'
... 
>>> requests.models.Response.hmm = hmm
>>> r = requests.get('http://bbc.co.uk')
>>> print r
<Response [200]>
>>> r.hmm()
'ok'
>>> requests.__version__
'1.0.4'

OTHER TIPS

I don’t think you can monkey-patch that type like that. When importing requests, all these modules are initialized. And as the whole library uses from xy import Request over and over, it will have an exact reference to the actual type. And only after that, you replace the Response type within the models module, so only subsequent imports are affected.

Unless you go through all the modules and manually replace their Response reference with your new type, they will still use the original one, making your patch useless.

Instead, you should keep the original type but expand it directly, as Martijn suggested.

Just a quick fix using setattr, but it's a bit ugly (but semantically equivalent to @Martijn answer):

def hmm(self):
    return 'OK - %s' % self.status_code

setattr(requests.models.Response, 'hmm', hmm)

r = requests.get('http://bbc.co.uk')
print r.hmm()
# prints 
# OK - 200
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top