Skip to content

Commit

Permalink
Add strict mypy check, update docs on type checking
Browse files Browse the repository at this point in the history
  • Loading branch information
sanjacob committed Jan 4, 2024
1 parent dcacf6e commit ed3d2ef
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
run: flake8 tiny_api_client

- name: Run type checker
run: mypy tiny_api_client
run: mypy --strict tiny_api_client

- name: Run test suite
run: pytest -vvvv
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ To learn how to test your own API clients, see the :doc:`testing`.
:caption: Contents:

quick
typing
testing
api_reference

Expand Down
18 changes: 17 additions & 1 deletion docs/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Usage
::

from my_api import MyClient

def test_my_client(api_call):
# set your fake api response
api_call.return_value = [{"id": 0, "name": "Mary Jane"}, ...]
Expand All @@ -46,6 +46,22 @@ Usage
assert users[0].name == "Mary Jane"


Using a Context Manager
-----------------------

In some circumstances it might not be possible to use a function-scoped fixture.
One example of this is when using the property-based testing library ``hypothesis``.
It is still possible to use a context manager to temporarily patch the api call.

::

from unittest.mock import patch

def test_my_client():
with patch('pytest_tiny_api_client._api_call') as api_call:
...


Not Using Pytest
----------------

Expand Down
43 changes: 43 additions & 0 deletions docs/typing.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Type Checking
=============

You should be able to use *mypy* and other type checkers to verify the
correctness of your code. The library itself is checked with the ``--strict``
flag.

For the most part, you should not have issues with type checking except when
passing keyword arguments to your endpoints. Unfortunately you will see the
following error.

::

error: Unexpected keyword argument "arg" for "call" of "Client"
[call-arg]

This is due to inherent limitations with the typing spec as of Python 3.12,
and the fact that keyword arguments cannot be concatenated for type checking
purposes. For more information, see `pep`_ 612.

.. _pep: https://peps.python.org/pep-0612/#concatenating-keyword-parameters

Mitigations
-----------

One way around this is to include arbitrary keyword-only arguments in your
endpoint definition. This will let mypy know that the wrapper function can
also accept arbitrary keyword-only arguments. The obvious downside is that
it does not look very clean and if you have multiple endpoints it can get
tiring to write them like this.

::

from typing import Any

@get('/my_endpoint/{item_id}')
def my_call(self, response, /, **_: Any) -> str:
return response

The other way is to manually silence this error for a certain scope.
For more information, see the `mypy`_ docs.

.. _mypy: https://mypy.readthedocs.io/en/stable/error_codes.html
2 changes: 1 addition & 1 deletion tiny_api_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ def request(route: str, *, version: int = 1, use_api: bool = True,
:param int version: Replaces version placeholder in API URL
:param bool json: Toggle JSON parsing of response
:param bool xml: Toggle XML parsing of response
:param dict g_kwargs: Any keyword arguments passed to requests
:param dict request_kwargs: Any keyword arguments passed to requests
"""
endpoint = Endpoint(route, version, use_api, json, xml, request_kwargs)

Expand Down

0 comments on commit ed3d2ef

Please sign in to comment.