Skip to content

Commit

Permalink
šŸ› [source-airtable] next_page_token should adhere to HttpStream interā€¦
Browse files Browse the repository at this point in the history
ā€¦face (#38765)
  • Loading branch information
brianjlai authored May 29, 2024
1 parent 2bf0bf8 commit 7aa390f
Show file tree
Hide file tree
Showing 7 changed files with 412 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ data:
connectorSubtype: api
connectorType: source
definitionId: 14c6e7ea-97ed-4f5e-a7b5-25e9a80b8212
dockerImageTag: 4.2.0
dockerImageTag: 4.2.1
dockerRepository: airbyte/source-airtable
documentationUrl: https://docs.airbyte.com/integrations/sources/airtable
githubIssueLabel: source-airtable
Expand Down
496 changes: 394 additions & 102 deletions airbyte-integrations/connectors/source-airtable/poetry.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
version = "4.2.0"
version = "4.2.1"
name = "source-airtable"
description = "Source implementation for Airtable."
authors = [ "Airbyte <[email protected]>",]
Expand All @@ -17,7 +17,7 @@ include = "source_airtable"

[tool.poetry.dependencies]
python = "^3.9,<3.12"
airbyte-cdk = "^0"
airbyte-cdk = "^1"

[tool.poetry.scripts]
source-airtable = "source_airtable.run:run"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
#


import logging
from typing import Any, Iterable, Iterator, List, Mapping, MutableMapping, Tuple, Union

from airbyte_cdk.logger import AirbyteLogger
from airbyte_cdk.models import AirbyteCatalog, AirbyteMessage, AirbyteStateMessage, ConfiguredAirbyteCatalog
from airbyte_cdk.sources import AbstractSource
from airbyte_cdk.sources.streams import Stream
Expand All @@ -24,7 +23,7 @@ class SourceAirtable(AbstractSource):
streams_catalog: Iterable[Mapping[str, Any]] = []
_auth: AirtableAuth = None

def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> Tuple[bool, Any]:
def check_connection(self, logger: logging.Logger, config: Mapping[str, Any]) -> Tuple[bool, Any]:
auth = AirtableAuth(config)
try:
# try reading first table from each base, to check the connectivity,
Expand Down Expand Up @@ -66,7 +65,7 @@ def read(
catalog = self._remove_missed_streams_from_catalog(logger, config, catalog)
return super().read(logger, config, catalog, state)

def discover(self, logger: AirbyteLogger, config) -> AirbyteCatalog:
def discover(self, logger: logging.Logger, config) -> AirbyteCatalog:
"""
Override to provide the dynamic schema generation capabilities,
using resource available for authenticated user.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ def backoff_time(self, response: requests.Response) -> Optional[float]:
self.logger.error(f"Stream {self.name}: rate limit exceeded")
return 30.0

def next_page_token(self, response: requests.Response, **kwargs) -> str:
def next_page_token(self, response: requests.Response, **kwargs) -> Optional[Mapping[str, Any]]:
"""
The bases list could be more than 100 records, therefore the pagination is required to fetch all of them.
"""
next_page = response.json().get("offset")
if next_page:
return next_page
return {"offset": next_page}
return None

def request_params(self, next_page_token: str = None, **kwargs) -> Mapping[str, Any]:
def request_params(self, next_page_token: Optional[Mapping[str, Any]] = None, **kwargs) -> Mapping[str, Any]:
params = {}
if next_page_token:
params["offset"] = next_page_token
params.update(next_page_token)
return params

def parse_response(self, response: requests.Response, **kwargs) -> Mapping[str, Any]:
Expand Down Expand Up @@ -150,7 +150,7 @@ def get_json_schema(self) -> Mapping[str, Any]:
def next_page_token(self, response: requests.Response, **kwargs) -> Optional[Mapping[str, Any]]:
next_page = response.json().get("offset")
if next_page:
return next_page
return {"offset": next_page}
return None

def request_params(self, next_page_token: Mapping[str, Any] = None, **kwargs) -> MutableMapping[str, Any]:
Expand All @@ -159,7 +159,7 @@ def request_params(self, next_page_token: Mapping[str, Any] = None, **kwargs) ->
"""
params = {}
if next_page_token:
params["offset"] = next_page_token
params.update(next_page_token)
return params

def process_records(self, records) -> Iterable[Mapping[str, Any]]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ def test_next_page(self, requests_mock):
url = "https://api.airtable.com/v0/meta/bases/"
requests_mock.get(url, status_code=200, json={"offset": "xyz"})
response = requests.get(url)
assert self.bases_instance.next_page_token(response) == "xyz"
assert self.bases_instance.next_page_token(response) == {"offset": "xyz"}

@pytest.mark.parametrize(
("next_page", "expected"),
[
(None, {}),
("xyz", {"offset": "xyz"}),
({"offset": "xyz"}, {"offset": "xyz"}),
],
)
def test_request_params(self, next_page, expected):
Expand Down Expand Up @@ -143,13 +143,13 @@ def test_streams_next_page(self, prepared_stream, requests_mock):
url = "https://api.airtable.com/v0/meta/bases/"
requests_mock.get(url, status_code=200, json={"offset": "xyz"})
response = requests.get(url)
assert self.stream_instance(prepared_stream).next_page_token(response) == "xyz"
assert self.stream_instance(prepared_stream).next_page_token(response) == {"offset": "xyz"}

@pytest.mark.parametrize(
("next_page", "expected"),
[
(None, {}),
("xyz", {"offset": "xyz"}),
({"offset": "xyz"}, {"offset": "xyz"}),
],
)
def test_streams_request_params(self, next_page, expected, prepared_stream):
Expand Down
3 changes: 2 additions & 1 deletion docs/integrations/sources/airtable.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ See information about rate limits [here](https://airtable.com/developers/web/api
## Changelog

| Version | Date | Pull Request | Subject |
| :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------------- |
|:--------|:-----------| :------------------------------------------------------- |:---------------------------------------------------------------------------------------|
| 4.2.1 | 2024-05-29 | [38765](https://github.com/airbytehq/airbyte/pull/38765) | Fix next_page_token() to correctly adhere to HttpStream interface |
| 4.2.0 | 2024-03-19 | [36267](https://github.com/airbytehq/airbyte/pull/36267) | Pin airbyte-cdk version to `^0` |
| 4.1.6 | 2024-02-12 | [35149](https://github.com/airbytehq/airbyte/pull/35149) | Manage dependencies with Poetry. |
| 4.1.5 | 2023-10-19 | [31599](https://github.com/airbytehq/airbyte/pull/31599) | Base image migration: remove Dockerfile and use the python-connector-base image |
Expand Down

0 comments on commit 7aa390f

Please sign in to comment.