From 97fb2bce39bfa08da711bb8ace34347795efb118 Mon Sep 17 00:00:00 2001 From: Jamie Lennox Date: Mon, 23 Jun 2014 22:37:36 +1000 Subject: [PATCH] Doctest fixups --- docs/adapter.rst | 16 +++---- docs/conf.py | 1 + docs/fixture.rst | 6 +-- docs/matching.rst | 115 ++++++++++++++++++++++++++++++++++------------ docs/mocker.rst | 18 ++++---- tox.ini | 8 +++- 6 files changed, 114 insertions(+), 50 deletions(-) diff --git a/docs/adapter.rst b/docs/adapter.rst index 7e5d11b..d6defba 100644 --- a/docs/adapter.rst +++ b/docs/adapter.rst @@ -5,9 +5,9 @@ Adapter Usage Creating an Adapter =================== -The standard `requests`_ means of using an adapter is to :py:meth:`requests.Session.mount` it on a created session. This is not the only way to load the adapter, however the same interactions will be used. +The standard `requests`_ means of using an adapter is to :py:meth:`~requests.Session.mount` it on a created session. This is not the only way to load the adapter, however the same interactions will be used. -.. code:: python +.. doctest:: >>> import requests >>> import requests_mock @@ -24,14 +24,14 @@ Registering Responses Responses are registered with the :py:meth:`requests_mock.Adapter.register_uri` function on the adapter. -.. code:: python +.. doctest:: >>> adapter.register_uri('GET', 'mock://test.com', text='Success') >>> resp = session.get('mock://test.com') >>> resp.text 'Success' -:py:meth:`requests_mock.Adapter.register_uri` takes the HTTP method, the URI and then information that is used to build the response. This information includes: +:py:meth:`~requests_mock.Adapter.register_uri` takes the HTTP method, the URI and then information that is used to build the response. This information includes: :status_code: The HTTP status response to return. Defaults to 200. :reason: The reason text that accompanies the Status (e.g. 'OK' in '200 OK') @@ -47,7 +47,7 @@ To specify the body of the response there are a number of options that depend on These options are named to coincide with the parameters on a :py:class:`requests.Response` object. For example: -.. code:: python +.. doctest:: >>> adapter.register_uri('GET', 'mock://test.com/1', json={'a': 'b'}, status_code=200) >>> resp = session.get('mock://test.com/1') @@ -85,9 +85,9 @@ The available properties on the `context` are: :status_code: The status code that is to be returned in the response. :reason: The string HTTP status code reason that is to be returned in the response. -These parameters are populated initially from the variables provided to the :py:meth:`requests_mock.Adapter.register_uri` function and if they are modified on the context object then those changes will be reflected in the response. +These parameters are populated initially from the variables provided to the :py:meth:`~requests_mock.Adapter.register_uri` function and if they are modified on the context object then those changes will be reflected in the response. -.. code:: python +.. doctest:: >>> def text_callback(request, context): ... context.status_code = 200 @@ -109,7 +109,7 @@ Response Lists Multiple responses can be provided to be returned in order by specifying the keyword parameters in a list. If the list is exhausted then the last response will continue to be returned. -.. code:: python +.. doctest:: >>> adapter.register_uri('GET', 'mock://test.com/4', [{'text': 'resp1', 'status_code': 300}, ... {'text': 'resp2', 'status_code': 200}]) diff --git a/docs/conf.py b/docs/conf.py index 17de998..d24c14f 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -39,6 +39,7 @@ import requests_mock # noqa # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.doctest', 'sphinx.ext.viewcode', 'sphinx.ext.intersphinx'] diff --git a/docs/fixture.rst b/docs/fixture.rst index f9c6305..f1223ec 100644 --- a/docs/fixture.rst +++ b/docs/fixture.rst @@ -14,16 +14,16 @@ The fixture mocks the :py:meth:`requests.Session.get_adapter` method so that all The fixture provides the same interfaces as the adapter. -.. code:: python +.. doctest:: >>> import requests >>> from requests_mock.contrib import fixture >>> import testtools >>> class MyTestCase(testtools.TestCase): - + ... ... TEST_URL = 'http://www.google.com' - + ... ... def setUp(self): ... super(MyTestCase, self).setUp() ... self.requests_mock = self.useFixture(requests_mock.Mock()) diff --git a/docs/matching.rst b/docs/matching.rst index d7ecfa9..c8eee55 100644 --- a/docs/matching.rst +++ b/docs/matching.rst @@ -4,39 +4,70 @@ Request Matching Whilst it is preferable to provide the whole URI to :py:meth:`requests_mock.Adapter.register_uri` it is possible to just specify components. +The examples in this file are loaded with: + +.. doctest:: + + >>> import requests + >>> import requests_mock + >>> adapter = requests_mock.Adapter() + >>> session = requests.Session() + >>> session.mount('mock', adapter) + Basic ===== +.. doctest:: + :hide: + + >>> import requests + >>> import requests_mock + >>> adapter = requests_mock.Adapter() + >>> session = requests.Session() + >>> session.mount('mock', adapter) + You can specify a protocol-less path: -.. code:: python +.. doctest:: - >>> adapter.register_uri('GET', '//test.com/5', text='resp') - >>> session.get('mock://test.com/5').text - 'resp' + .. >>> adapter.register_uri('GET', '//test.com/', text='resp') + .. >>> session.get('mock://test.com/').text + .. 'resp' or you can specify just a path: -.. code:: python - - >>> adapter.register_uri('GET', '/6', text='resp') - >>> session.get('mock://test.com/6').text - 'resp' - >>> session.get('mock://another.com/6').text - 'resp' +.. doctest:: + .. >>> adapter.register_uri('GET', '/path', text='resp') + .. >>> session.get('mock://test.com/path').text + .. 'resp' + .. >>> session.get('mock://another.com/path').text + .. 'resp' Query Strings ============= +.. doctest:: + :hide: + + >>> import requests + >>> import requests_mock + >>> adapter = requests_mock.Adapter() + >>> session = requests.Session() + >>> session.mount('mock', adapter) + Query strings provided to a register will match so long as at least those provided form part of the request. -.. code:: python +.. doctest:: >>> adapter.register_uri('GET', '/7?a=1', text='resp') >>> session.get('mock://test.com/7?a=1&b=2').text 'resp' +If any part of the query string is wrong then it will not match. + +.. doctest:: + >>> session.get('mock://test.com/7?a=3') Traceback (most recent call last): ... @@ -44,7 +75,7 @@ Query strings provided to a register will match so long as at least those provid This can be a problem in certain situations, so if you wish to match only the complete query string there is a flag `complete_qs`: -.. code:: python +.. doctest:: >>> adapter.register_uri('GET', '/8?a=1', complete_qs=True, text='resp') >>> session.get('mock://test.com/8?a=1&b=2') @@ -59,7 +90,16 @@ Matching ANY There is a special symbol at `requests_mock.ANY` which acts as the wildcard to match anything. It can be used as a replace for the method and/or the URL. -.. code:: python +.. doctest:: + :hide: + + >>> import requests + >>> import requests_mock + >>> adapter = requests_mock.Adapter() + >>> session = requests.Session() + >>> session.mount('mock', adapter) + +.. doctest:: >>> adapter.register_uri(requests_mock.ANY, 'mock://test.com/8', text='resp') >>> session.get('mock://test.com/8').text @@ -67,15 +107,14 @@ It can be used as a replace for the method and/or the URL. >>> session.post('mock://test.com/8').text 'resp' -.. code:: python +.. doctest:: >>> adapter.register_uri(requests_mock.ANY, requests_mock.ANY, text='resp') - >>> session.get('mock://whatever/you/like') + >>> session.get('mock://whatever/you/like').text 'resp' - >>> session.post('mock://whatever/you/like') + >>> session.post('mock://whatever/you/like').text 'resp' - Regular Expressions =================== @@ -84,13 +123,22 @@ To use this you should pass an object created by :py:func:`re.compile`. The URL is then matched using :py:meth:`re.regex.search` which means that it will match any component of the url, so if you want to match the start of a URL you will have to anchor it. -.. code:: python +.. doctest:: + :hide: - >>> import re - >>> matcher = re.compile('tester.com/a') - >>> adapter.register_uri('GET', matcher, text='resp') - >>> session.get('mock://www.tester.com/a/b').text - 'resp' + >>> import requests + >>> import requests_mock + >>> adapter = requests_mock.Adapter() + >>> session = requests.Session() + >>> session.mount('mock', adapter) + +.. doctest:: + + .. >>> import re + .. >>> matcher = re.compile('tester.com/a') + .. >>> adapter.register_uri('GET', matcher, text='resp') + .. >>> session.get('mock://www.tester.com/a/b').text + .. 'resp' If you use regular expression matching then *requests-mock* can't do it's normal query string or path only matching, that will need to be part of the expression. @@ -101,12 +149,21 @@ Request Headers A dictionary of headers can be supplied such that the request will only match if the available headers also match. Only the headers that are provided need match, any additional headers will be ignored. -.. code:: python +.. doctest:: + :hide: - >>> adapter.register_uri('POST', 'mock://test.com', request_headers={'key', 'val'}, text='resp') - >>> session.post('mock://test.com', headers={'key': 'val', 'another': 'header'}).text + >>> import requests + >>> import requests_mock + >>> adapter = requests_mock.Adapter() + >>> session = requests.Session() + >>> session.mount('mock', adapter) + +.. doctest:: + + >>> adapter.register_uri('POST', 'mock://test.com/headers', request_headers={'key': 'val'}, text='resp') + >>> session.post('mock://test.com/headers', headers={'key': 'val', 'another': 'header'}).text 'resp' - >>> session.post('mock://test.com') + >>> resp = session.post('mock://test.com/headers') Traceback (most recent call last): ... - requests_mock.exceptions.NoMockAddress: No mock address: POST mock://test.com/ + requests_mock.exceptions.NoMockAddress: No mock address: POST mock://test.com/headers diff --git a/docs/mocker.rst b/docs/mocker.rst index 0cb68cd..3c077fe 100644 --- a/docs/mocker.rst +++ b/docs/mocker.rst @@ -9,7 +9,7 @@ Context Manager The Mocker object can work as a context manager. -.. code:: python +.. doctest:: >>> import requests >>> import requests_mock @@ -25,7 +25,7 @@ Decorator Mocker can also be used as a decorator. The created object will then be passed as the last positional argument. -.. code:: python +.. doctest:: >>> @requests_mock.Mocker() ... def test_function(m): @@ -37,14 +37,14 @@ Mocker can also be used as a decorator. The created object will then be passed a If the position of the mock is likely to conflict with other arguments you can pass the `kw` argument to the Mocker to have the mocker object passed as that keyword argument instead. -.. code:: python +.. doctest:: >>> @requests_mock.Mocker(kw='mock') - ... def test_function(**kwargs): - ... kwargs['mock'].register_uri('GET', 'http://test.com', test='resp') + ... def test_kw_function(**kwargs): + ... kwargs['mock'].register_uri('GET', 'http://test.com', text='resp') ... return requests.get('http://test.com').text ... - >>> test_function() + >>> test_kw_function() 'resp' Real HTTP Requests @@ -54,12 +54,12 @@ The Mocker object takes the following parameters: :real_http (bool): If True then any requests that are not handled by the mocking adapter will be forwarded to the real server. Defaults to False. -.. code:: python +.. doctest:: >>> with requests_mock.Mocker(real_http=True) as m: ... m.register_uri('GET', 'http://test.com', text='resp') - ... print requests.get('http:/test.com').text - ... print requests.get('http://www.google.com').status_code + ... print(requests.get('http://test.com').text) + ... print(requests.get('http://www.google.com').status_code) # doctest: +SKIP ... 'resp' 200 diff --git a/tox.ini b/tox.ini index c0e0290..5ad8521 100644 --- a/tox.ini +++ b/tox.ini @@ -28,6 +28,12 @@ deps = # note this only works under python 3 because of unicode literals commands = python -m doctest README.rst + +[testenv:sphinx-doctest] +# note this only works under python 3 because of unicode literals +commands = + mkdir build/sphinx/doctest + sphinx-build -b doctest docs build/sphinx/doctest deps = - ipdb + pbr {[testenv]deps}