AttributeError: 'NoneType' object has no attribute 'read'

Bug #1642396 reported by mak
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
requests-mock
Invalid
Undecided
Jamie Lennox

Bug Description

Originally filed here: https://github.com/kennethreitz/requests/issues/3698

I'm using a test suite which uses `requests_mock`, and it appears that something is not handled properly for the new 2.12.1 version of `requests`.

Build: https://ci.appveyor.com/project/coala/coala-bears/build/1.0.3537/job/1wm7b4u9yhgkxkgn

Relevant part:
```
================================== FAILURES ===================================
_________________ InvalidLinkBearTest.test_redirect_threshold _________________
self = <tests.general.InvalidLinkBearTest.InvalidLinkBearTest testMethod=test_redirect_threshold>
    def test_redirect_threshold(self):

        long_url_redirect = """
            https://bitbucket.org/api/301
            https://bitbucket.org/api/302
            """.splitlines()

        short_url_redirect = """
            http://httpbin.org/status/301
            """.splitlines()

        self.assertResult(valid_file=long_url_redirect,
                          invalid_file=short_url_redirect,
> settings={'follow_redirects': 'yeah'})
tests\general\InvalidLinkBearTest.py:157:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests\general\InvalidLinkBearTest.py:75: in assertResult
    out = list(uut.run("valid", valid_file, **settings))
bears\general\InvalidLinkBear.py:80: in run
    file, timeout, link_ignore_regex):
bears\general\InvalidLinkBear.py:53: in find_links_in_file
    code = InvalidLinkBear.get_status_code(link, timeout)
bears\general\InvalidLinkBear.py:37: in get_status_code
    timeout=timeout).status_code
C:\Python34\lib\site-packages\requests\api.py:96: in head
    return request('head', url, **kwargs)
C:\Python34\lib\site-packages\requests\api.py:56: in request
    return session.request(method=method, url=url, **kwargs)
C:\Python34\lib\site-packages\requests\sessions.py:488: in request
    resp = self.send(prep, **send_kwargs)
C:\Python34\lib\site-packages\requests_mock\mocker.py:69: in _fake_send
    return self._real_send(session, request, **kwargs)
C:\Python34\lib\site-packages\requests\sessions.py:641: in send
    r.content
C:\Python34\lib\site-packages\requests\models.py:772: in content
    self._content = bytes().join(self.iter_content(CONTENT_CHUNK_SIZE)) or bytes()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def generate():
        # Special case for urllib3.
        if hasattr(self.raw, 'stream'):
            try:
                for chunk in self.raw.stream(chunk_size, decode_content=True):
                    yield chunk
            except ProtocolError as e:
                raise ChunkedEncodingError(e)
            except DecodeError as e:
                raise ContentDecodingError(e)
            except ReadTimeoutError as e:
                raise ConnectionError(e)
        else:
            # Standard file-like object.
            while True:
> chunk = self.raw.read(chunk_size)
E AttributeError: 'NoneType' object has no attribute 'read'
C:\Python34\lib\site-packages\requests\models.py:705: AttributeError
```
happens on Windows and Linux.

Revision history for this message
Jamie Lennox (jamielennox) wrote :

Closing as not a bug in requests-mock, but in the way coala is providing its responses.

Duplicating my response from https://github.com/kennethreitz/requests/issues/3698

From a requests-mock perspective bug #1642697 was filed that was hit because of the exact same removal of AttributeError handling in https://github.com/kennethreitz/requests/commit/327512f5ef9eea79a0cb324ba47e7eabf6967b3a . This only affects the requests-mock tests and not the mocking itself but is likely the same result.

From a requests-mock usage perspective (which should probably go elsewhere, but i'm not sure where) there's a few things you can fix in your tests to not have this problem.

1). It's unlikely you really want a custom matcher, A matcher is the code that checks if you want to return a response. When you do a requests_mock.get() or .register_uri() it creates a matcher for you and you can regexp or a whole variety of things there. You can then attach a function that fills in a response for you, and requests_mock will handle making it a response that requests understands [1].

It's fine/expected to make register each url you are using with it's own response rather than try to cram everything into the same custom matcher.

2). requests_mock.create_response() is a function that is used to create a HTTPResponse that requests understands and it's public for just this reason. If you use this instead of constructing your own requests.Response it will patch all this stuff for you.

3). update to requests_mock 1.x. There's no API break, it had just been stable long enough to not be considered a 0.x release any more. There's also probably not anything you really need from the 1.x branch but it will be less likely to break with new requests releases.

[1] http://requests-mock.readthedocs.io/en/latest/response.html#dynamic-response

Changed in requests-mock:
status: New → Invalid
assignee: nobody → Jamie Lennox (jamielennox)
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.