Skip to content

Commit

Permalink
Merge pull request #388 from mesozoic/testing
Browse files Browse the repository at this point in the history
Context manager for mocking API interactions in tests
  • Loading branch information
mesozoic authored Oct 13, 2024
2 parents 97f2f1b + 2e1a6fc commit 4fd2172
Show file tree
Hide file tree
Showing 11 changed files with 1,009 additions and 80 deletions.
3 changes: 3 additions & 0 deletions docs/source/_substitutions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

.. |arg_record_id| replace:: An Airtable record ID.

.. |arg_table_id_or_name| replace:: An Airtable table ID or name.
Table name should be unencoded, as shown on browser.

.. |kwarg_view| replace:: The name or ID of a view.
If set, only the records in that view will be returned.
The records will be sorted according to the order of the view.
Expand Down
1 change: 1 addition & 0 deletions docs/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Changelog
* Added support for `Upload attachment <https://airtable.com/developers/web/api/upload-attachment>`_
via :meth:`Table.upload_attachment <pyairtable.Table.upload_attachment>`
or :meth:`AttachmentsList.upload <pyairtable.orm.lists.AttachmentsList.upload>`.
* Added :class:`pyairtable.testing.MockAirtable` for easier testing.

2.3.3 (2024-03-22)
------------------------
Expand Down
11 changes: 11 additions & 0 deletions docs/source/tables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,14 @@ and :meth:`~pyairtable.Table.add_comment` methods will return instances of
>>> table.comments("recMNxslc6jG0XedV")[0].text
'Never mind!'
>>> comment.delete()

Testing Your Code
-----------------

pyAirtable provides a :class:`~pyairtable.testing.MockAirtable` class that can be used to
test your code without making real requests to Airtable.

.. autoclass:: pyairtable.testing.MockAirtable
:noindex:

For more information, see :mod:`pyairtable.testing`.
8 changes: 6 additions & 2 deletions pyairtable/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Any, Dict, Iterator, List, Optional, Sequence, Tuple, TypeVar, Union

import requests
from requests import PreparedRequest
from requests.sessions import Session
from typing_extensions import TypeAlias

Expand Down Expand Up @@ -273,14 +274,17 @@ def request(
json=json,
)

response = self.session.send(prepared, timeout=self.timeout)
return self._process_response(response)
return self._perform_request(prepared)

get = partialmethod(request, "GET")
post = partialmethod(request, "POST")
patch = partialmethod(request, "PATCH")
delete = partialmethod(request, "DELETE")

def _perform_request(self, prepared: PreparedRequest) -> Any:
response = self.session.send(prepared, timeout=self.timeout)
return self._process_response(response)

def _process_response(self, response: requests.Response) -> Any:
try:
response.raise_for_status()
Expand Down
3 changes: 1 addition & 2 deletions pyairtable/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ def table(
Build a new :class:`Table` instance using this instance of :class:`Base`.
Args:
id_or_name: An Airtable table ID or name. Table name should be unencoded,
as shown on browser.
id_or_name: |arg_table_id_or_name|
validate: |kwarg_validate_metadata|
force: |kwarg_force_metadata|
Expand Down
3 changes: 3 additions & 0 deletions pyairtable/api/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,9 @@ class UpdateRecordDict(TypedDict):
fields: WritableFields


AnyRecordDict: TypeAlias = Union[RecordDict, CreateRecordDict, UpdateRecordDict]


class RecordDeletedDict(TypedDict):
"""
A ``dict`` representing the payload returned by the Airtable API to confirm a deletion.
Expand Down
Loading

0 comments on commit 4fd2172

Please sign in to comment.