tap-belvo 0.3.1__py3-none-any.whl → 0.3.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tap-belvo might be problematic. Click here for more details.

tap_belvo/client.py CHANGED
@@ -2,31 +2,35 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import typing as t
5
+ import sys
6
6
  from abc import ABCMeta, abstractmethod
7
7
  from copy import deepcopy
8
+ from importlib import resources
9
+ from typing import TYPE_CHECKING, Any
8
10
  from urllib.parse import ParseResult, parse_qsl
9
11
 
10
12
  from requests.auth import HTTPBasicAuth
11
13
  from requests_cache import install_cache
12
- from singer_sdk import RESTStream
13
- from singer_sdk.helpers._typing import is_date_or_datetime_type
14
+ from singer_sdk import OpenAPISchema, RESTStream
14
15
  from singer_sdk.pagination import BaseHATEOASPaginator
15
- from singer_sdk.singerlib import resolve_schema_references
16
16
 
17
- from tap_belvo.openapi import load_openapi
17
+ if sys.version_info >= (3, 12):
18
+ from typing import override
19
+ else:
20
+ from typing_extensions import override
18
21
 
19
- if t.TYPE_CHECKING:
22
+ if TYPE_CHECKING:
20
23
  from requests import Response
21
24
  from singer_sdk.helpers.types import Context
22
25
 
23
26
 
24
27
  PAGE_SIZE = 1000
28
+ OPENAPI = OpenAPISchema(resources.files("tap_belvo") / "openapi.json")
25
29
 
26
30
  install_cache("tap_belvo_cache", backend="sqlite", expire_after=3600)
27
31
 
28
32
 
29
- def _handle_schema_nullable(schema: dict[str, t.Any]) -> dict[str, t.Any]:
33
+ def _handle_schema_nullable(schema: dict[str, Any]) -> dict[str, Any]:
30
34
  """Resolve x-nullable properties to standard JSON Schema nullable type.
31
35
 
32
36
  Args:
@@ -60,15 +64,9 @@ def _handle_schema_nullable(schema: dict[str, t.Any]) -> dict[str, t.Any]:
60
64
  class BelvoPaginator(BaseHATEOASPaginator):
61
65
  """Belvo API paginator class."""
62
66
 
67
+ @override
63
68
  def get_next_url(self, response: Response) -> str | None:
64
- """Get the next URL from the response.
65
-
66
- Args:
67
- response: The response object.
68
-
69
- Returns:
70
- The next URL.
71
- """
69
+ """Get the next URL from the response."""
72
70
  return response.json().get("next") # type: ignore[no-any-return]
73
71
 
74
72
 
@@ -77,58 +75,28 @@ class BelvoStream(RESTStream[ParseResult], metaclass=ABCMeta):
77
75
 
78
76
  records_jsonpath = "$.results[*]" # Or override `parse_response`.
79
77
 
78
+ @override
80
79
  @property
81
80
  def url_base(self) -> str:
82
- """Return the URL base property.
83
-
84
- Returns:
85
- str: The URL base.
86
- """
87
81
  return self.config["base_url"] # type: ignore[no-any-return]
88
82
 
83
+ @override
89
84
  @property
90
85
  def authenticator(self) -> HTTPBasicAuth:
91
- """Get an authenticator object.
92
-
93
- Returns:
94
- The authenticator instance for this REST stream.
95
- """
96
86
  return HTTPBasicAuth(self.config["secret_id"], self.config["password"])
97
87
 
98
- @property
99
- def http_headers(self) -> dict[str, str]:
100
- """Return the http headers needed.
101
-
102
- Returns:
103
- A dictionary of HTTP headers.
104
- """
105
- headers = {}
106
- headers["User-Agent"] = f"{self.tap_name}/{self._tap.plugin_version}"
107
- return headers
108
-
88
+ @override
109
89
  def get_new_paginator(self) -> BelvoPaginator:
110
- """Get a new paginator instance.
111
-
112
- Returns:
113
- A new paginator instance.
114
- """
115
90
  return BelvoPaginator()
116
91
 
92
+ @override
117
93
  def get_url_params(
118
94
  self,
119
95
  context: Context | None,
120
96
  next_page_token: ParseResult | None,
121
- ) -> dict[str, t.Any]:
122
- """Get URL query parameters.
123
-
124
- Args:
125
- context: Stream sync context.
126
- next_page_token: Next offset.
127
-
128
- Returns:
129
- Mapping of URL query parameters.
130
- """
131
- params: dict[str, t.Any] = {
97
+ ) -> dict[str, Any]:
98
+ """Get URL query parameters."""
99
+ params: dict[str, Any] = {
132
100
  "page": 1,
133
101
  "page_size": PAGE_SIZE,
134
102
  }
@@ -136,50 +104,20 @@ class BelvoStream(RESTStream[ParseResult], metaclass=ABCMeta):
136
104
  if next_page_token:
137
105
  params.update(parse_qsl(next_page_token.query))
138
106
 
139
- if self.replication_key:
140
- start_date = self.get_starting_timestamp(context)
141
- if start_date:
142
- params[f"{self.replication_key}__gte"] = start_date.date()
107
+ if (
108
+ self.replication_key # Only if the stream is running incrementally
109
+ and (start_date := self.get_starting_timestamp(context))
110
+ ):
111
+ params[f"{self.replication_key}__gte"] = start_date.date().isoformat()
143
112
 
144
113
  return params
145
114
 
115
+ @override
146
116
  @property
147
- def is_timestamp_replication_key(self) -> bool:
148
- """Check is replication key is a timestamp.
149
-
150
- Developers can override to `True` in order to force this value, although this
151
- should not be required in most use cases since the type can generally be
152
- accurately detected from the JSON Schema.
153
-
154
- Returns:
155
- True if the stream uses a timestamp-based replication key.
156
- """
157
- if not self.replication_key:
158
- return False
159
- type_dict = self.schema.get("properties", {}).get(self.replication_key)
160
- return is_date_or_datetime_type(type_dict)
161
-
162
- def _resolve_openapi_ref(self) -> dict[str, t.Any]:
163
- schema = {"$ref": f"#/components/schemas/{self.openapi_ref}"}
164
- openapi = load_openapi()
165
- schema["components"] = openapi["components"]
166
- return resolve_schema_references(schema)
167
-
168
- @property
169
- def schema(self) -> dict[str, t.Any]:
170
- """Return the schema for this stream.
171
-
172
- Returns:
173
- The schema for this stream.
174
- """
175
- return _handle_schema_nullable(self._resolve_openapi_ref())
117
+ def schema(self) -> dict[str, Any]:
118
+ return _handle_schema_nullable(OPENAPI.fetch_schema(self.openapi_ref))
176
119
 
177
120
  @property
178
121
  @abstractmethod
179
122
  def openapi_ref(self) -> str:
180
- """Return the OpenAPI component name for this stream.
181
-
182
- Returns:
183
- The OpenAPI reference for this stream.
184
- """
185
- ...
123
+ """OpenAPI component name for this stream."""