omniload 0.0.0.dev0__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.
Files changed (218) hide show
  1. omniload/conftest.py +72 -0
  2. omniload/main.py +810 -0
  3. omniload/src/.gitignore +10 -0
  4. omniload/src/adjust/__init__.py +108 -0
  5. omniload/src/adjust/adjust_helpers.py +122 -0
  6. omniload/src/airtable/__init__.py +84 -0
  7. omniload/src/allium/__init__.py +128 -0
  8. omniload/src/anthropic/__init__.py +277 -0
  9. omniload/src/anthropic/helpers.py +525 -0
  10. omniload/src/applovin/__init__.py +316 -0
  11. omniload/src/applovin_max/__init__.py +117 -0
  12. omniload/src/appsflyer/__init__.py +325 -0
  13. omniload/src/appsflyer/client.py +110 -0
  14. omniload/src/appstore/__init__.py +142 -0
  15. omniload/src/appstore/client.py +126 -0
  16. omniload/src/appstore/errors.py +15 -0
  17. omniload/src/appstore/models.py +117 -0
  18. omniload/src/appstore/resources.py +179 -0
  19. omniload/src/arrow/__init__.py +81 -0
  20. omniload/src/asana_source/__init__.py +281 -0
  21. omniload/src/asana_source/helpers.py +30 -0
  22. omniload/src/asana_source/settings.py +158 -0
  23. omniload/src/attio/__init__.py +102 -0
  24. omniload/src/attio/helpers.py +65 -0
  25. omniload/src/blob.py +95 -0
  26. omniload/src/bruin/__init__.py +76 -0
  27. omniload/src/chess/__init__.py +180 -0
  28. omniload/src/chess/helpers.py +35 -0
  29. omniload/src/chess/settings.py +18 -0
  30. omniload/src/clickup/__init__.py +85 -0
  31. omniload/src/clickup/helpers.py +47 -0
  32. omniload/src/collector/spinner.py +43 -0
  33. omniload/src/couchbase_source/__init__.py +118 -0
  34. omniload/src/couchbase_source/helpers.py +135 -0
  35. omniload/src/cursor/__init__.py +83 -0
  36. omniload/src/cursor/helpers.py +188 -0
  37. omniload/src/customer_io/__init__.py +486 -0
  38. omniload/src/customer_io/helpers.py +530 -0
  39. omniload/src/destinations.py +982 -0
  40. omniload/src/docebo/__init__.py +589 -0
  41. omniload/src/docebo/client.py +435 -0
  42. omniload/src/docebo/helpers.py +97 -0
  43. omniload/src/dune/__init__.py +104 -0
  44. omniload/src/dune/helpers.py +108 -0
  45. omniload/src/dynamodb/__init__.py +86 -0
  46. omniload/src/elasticsearch/__init__.py +80 -0
  47. omniload/src/elasticsearch/helpers.py +141 -0
  48. omniload/src/errors.py +26 -0
  49. omniload/src/facebook_ads/__init__.py +403 -0
  50. omniload/src/facebook_ads/exceptions.py +19 -0
  51. omniload/src/facebook_ads/helpers.py +296 -0
  52. omniload/src/facebook_ads/settings.py +224 -0
  53. omniload/src/facebook_ads/utils.py +53 -0
  54. omniload/src/factory.py +305 -0
  55. omniload/src/filesystem/__init__.py +133 -0
  56. omniload/src/filesystem/helpers.py +114 -0
  57. omniload/src/filesystem/readers.py +187 -0
  58. omniload/src/filters.py +62 -0
  59. omniload/src/fireflies/__init__.py +151 -0
  60. omniload/src/fireflies/helpers.py +753 -0
  61. omniload/src/fluxx/__init__.py +10013 -0
  62. omniload/src/fluxx/helpers.py +233 -0
  63. omniload/src/frankfurter/__init__.py +157 -0
  64. omniload/src/frankfurter/helpers.py +48 -0
  65. omniload/src/freshdesk/__init__.py +103 -0
  66. omniload/src/freshdesk/freshdesk_client.py +151 -0
  67. omniload/src/freshdesk/settings.py +23 -0
  68. omniload/src/fundraiseup/__init__.py +95 -0
  69. omniload/src/fundraiseup/client.py +81 -0
  70. omniload/src/github/__init__.py +202 -0
  71. omniload/src/github/helpers.py +207 -0
  72. omniload/src/github/queries.py +129 -0
  73. omniload/src/github/settings.py +24 -0
  74. omniload/src/google_ads/__init__.py +198 -0
  75. omniload/src/google_ads/field.py +17 -0
  76. omniload/src/google_ads/metrics.py +254 -0
  77. omniload/src/google_ads/predicates.py +37 -0
  78. omniload/src/google_ads/reports.py +411 -0
  79. omniload/src/google_ads/test_google_ads.py +184 -0
  80. omniload/src/google_analytics/__init__.py +144 -0
  81. omniload/src/google_analytics/helpers.py +312 -0
  82. omniload/src/google_sheets/README.md +95 -0
  83. omniload/src/google_sheets/__init__.py +166 -0
  84. omniload/src/google_sheets/helpers/__init__.py +15 -0
  85. omniload/src/google_sheets/helpers/api_calls.py +160 -0
  86. omniload/src/google_sheets/helpers/data_processing.py +316 -0
  87. omniload/src/gorgias/__init__.py +595 -0
  88. omniload/src/gorgias/helpers.py +166 -0
  89. omniload/src/hostaway/__init__.py +302 -0
  90. omniload/src/hostaway/client.py +288 -0
  91. omniload/src/http/__init__.py +38 -0
  92. omniload/src/http/readers.py +146 -0
  93. omniload/src/http_client.py +24 -0
  94. omniload/src/hubspot/__init__.py +800 -0
  95. omniload/src/hubspot/helpers.py +417 -0
  96. omniload/src/hubspot/settings.py +329 -0
  97. omniload/src/indeed/__init__.py +153 -0
  98. omniload/src/indeed/helpers.py +228 -0
  99. omniload/src/influxdb/__init__.py +46 -0
  100. omniload/src/influxdb/client.py +34 -0
  101. omniload/src/intercom/__init__.py +142 -0
  102. omniload/src/intercom/helpers.py +674 -0
  103. omniload/src/intercom/settings.py +279 -0
  104. omniload/src/isoc_pulse/__init__.py +159 -0
  105. omniload/src/jira_source/__init__.py +377 -0
  106. omniload/src/jira_source/helpers.py +510 -0
  107. omniload/src/jira_source/settings.py +184 -0
  108. omniload/src/kafka/__init__.py +120 -0
  109. omniload/src/kafka/helpers.py +241 -0
  110. omniload/src/kinesis/__init__.py +153 -0
  111. omniload/src/kinesis/helpers.py +96 -0
  112. omniload/src/klaviyo/__init__.py +237 -0
  113. omniload/src/klaviyo/client.py +212 -0
  114. omniload/src/klaviyo/helpers.py +19 -0
  115. omniload/src/linear/__init__.py +634 -0
  116. omniload/src/linear/helpers.py +111 -0
  117. omniload/src/linkedin_ads/__init__.py +266 -0
  118. omniload/src/linkedin_ads/dimension_time_enum.py +17 -0
  119. omniload/src/linkedin_ads/helpers.py +246 -0
  120. omniload/src/loader.py +69 -0
  121. omniload/src/mailchimp/__init__.py +126 -0
  122. omniload/src/mailchimp/helpers.py +226 -0
  123. omniload/src/mailchimp/settings.py +164 -0
  124. omniload/src/masking.py +344 -0
  125. omniload/src/mixpanel/__init__.py +62 -0
  126. omniload/src/mixpanel/client.py +104 -0
  127. omniload/src/monday/__init__.py +246 -0
  128. omniload/src/monday/helpers.py +392 -0
  129. omniload/src/monday/settings.py +325 -0
  130. omniload/src/mongodb/__init__.py +281 -0
  131. omniload/src/mongodb/helpers.py +975 -0
  132. omniload/src/notion/__init__.py +69 -0
  133. omniload/src/notion/helpers/__init__.py +14 -0
  134. omniload/src/notion/helpers/client.py +178 -0
  135. omniload/src/notion/helpers/database.py +92 -0
  136. omniload/src/notion/settings.py +17 -0
  137. omniload/src/partition.py +32 -0
  138. omniload/src/personio/__init__.py +345 -0
  139. omniload/src/personio/helpers.py +100 -0
  140. omniload/src/phantombuster/__init__.py +65 -0
  141. omniload/src/phantombuster/client.py +87 -0
  142. omniload/src/pinterest/__init__.py +82 -0
  143. omniload/src/pipedrive/__init__.py +212 -0
  144. omniload/src/pipedrive/helpers/__init__.py +37 -0
  145. omniload/src/pipedrive/helpers/custom_fields_munger.py +116 -0
  146. omniload/src/pipedrive/helpers/pages.py +129 -0
  147. omniload/src/pipedrive/settings.py +41 -0
  148. omniload/src/pipedrive/typing.py +17 -0
  149. omniload/src/plusvibeai/__init__.py +335 -0
  150. omniload/src/plusvibeai/helpers.py +544 -0
  151. omniload/src/plusvibeai/settings.py +252 -0
  152. omniload/src/primer/__init__.py +45 -0
  153. omniload/src/primer/helpers.py +79 -0
  154. omniload/src/quickbooks/__init__.py +117 -0
  155. omniload/src/reddit_ads/__init__.py +183 -0
  156. omniload/src/reddit_ads/helpers.py +232 -0
  157. omniload/src/resource.py +40 -0
  158. omniload/src/revenuecat/__init__.py +83 -0
  159. omniload/src/revenuecat/helpers.py +237 -0
  160. omniload/src/salesforce/__init__.py +170 -0
  161. omniload/src/salesforce/helpers.py +78 -0
  162. omniload/src/shopify/__init__.py +1953 -0
  163. omniload/src/shopify/exceptions.py +17 -0
  164. omniload/src/shopify/helpers.py +202 -0
  165. omniload/src/shopify/settings.py +19 -0
  166. omniload/src/slack/__init__.py +290 -0
  167. omniload/src/slack/helpers.py +218 -0
  168. omniload/src/slack/settings.py +36 -0
  169. omniload/src/smartsheets/__init__.py +82 -0
  170. omniload/src/snapchat_ads/__init__.py +455 -0
  171. omniload/src/snapchat_ads/client.py +72 -0
  172. omniload/src/snapchat_ads/helpers.py +630 -0
  173. omniload/src/snapchat_ads/settings.py +130 -0
  174. omniload/src/socrata_source/__init__.py +83 -0
  175. omniload/src/socrata_source/helpers.py +85 -0
  176. omniload/src/socrata_source/settings.py +8 -0
  177. omniload/src/solidgate/__init__.py +219 -0
  178. omniload/src/solidgate/helpers.py +154 -0
  179. omniload/src/sources.py +5408 -0
  180. omniload/src/sql_database/__init__.py +0 -0
  181. omniload/src/sql_database/callbacks.py +66 -0
  182. omniload/src/stripe_analytics/__init__.py +183 -0
  183. omniload/src/stripe_analytics/helpers.py +386 -0
  184. omniload/src/stripe_analytics/settings.py +80 -0
  185. omniload/src/table_definition.py +15 -0
  186. omniload/src/testdata/fakebqcredentials.json +14 -0
  187. omniload/src/tiktok_ads/__init__.py +150 -0
  188. omniload/src/tiktok_ads/tiktok_helpers.py +130 -0
  189. omniload/src/time.py +11 -0
  190. omniload/src/trustpilot/__init__.py +48 -0
  191. omniload/src/trustpilot/client.py +48 -0
  192. omniload/src/version.py +6 -0
  193. omniload/src/wise/__init__.py +68 -0
  194. omniload/src/wise/client.py +63 -0
  195. omniload/src/zendesk/__init__.py +480 -0
  196. omniload/src/zendesk/helpers/__init__.py +39 -0
  197. omniload/src/zendesk/helpers/api_helpers.py +119 -0
  198. omniload/src/zendesk/helpers/credentials.py +68 -0
  199. omniload/src/zendesk/helpers/talk_api.py +132 -0
  200. omniload/src/zendesk/settings.py +71 -0
  201. omniload/src/zoom/__init__.py +99 -0
  202. omniload/src/zoom/helpers.py +102 -0
  203. omniload/testdata/.gitignore +2 -0
  204. omniload/testdata/create_replace.csv +21 -0
  205. omniload/testdata/delete_insert_expected.csv +6 -0
  206. omniload/testdata/delete_insert_part1.csv +5 -0
  207. omniload/testdata/delete_insert_part2.csv +6 -0
  208. omniload/testdata/merge_expected.csv +5 -0
  209. omniload/testdata/merge_part1.csv +4 -0
  210. omniload/testdata/merge_part2.csv +5 -0
  211. omniload/tests/unit/test_smartsheets.py +133 -0
  212. omniload-0.0.0.dev0.dist-info/METADATA +439 -0
  213. omniload-0.0.0.dev0.dist-info/RECORD +218 -0
  214. omniload-0.0.0.dev0.dist-info/WHEEL +4 -0
  215. omniload-0.0.0.dev0.dist-info/entry_points.txt +2 -0
  216. omniload-0.0.0.dev0.dist-info/licenses/LICENSE.Apache-2.0 +201 -0
  217. omniload-0.0.0.dev0.dist-info/licenses/LICENSE.md +21 -0
  218. omniload-0.0.0.dev0.dist-info/licenses/NOTICE +35 -0
@@ -0,0 +1,69 @@
1
+ # Copyright 2022-2025 ScaleVector
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """A source that extracts data from Notion API"""
16
+
17
+ from typing import Dict, Iterator, List, Optional
18
+
19
+ import dlt
20
+ from dlt.sources import DltResource
21
+
22
+ from .helpers.client import NotionClient
23
+ from .helpers.database import NotionDatabase
24
+
25
+
26
+ @dlt.source(max_table_nesting=1)
27
+ def notion_databases(
28
+ database_ids: Optional[List[Dict[str, str]]] = None,
29
+ api_key: str = dlt.secrets.value,
30
+ ) -> Iterator[DltResource]:
31
+ """
32
+ Retrieves data from Notion databases.
33
+
34
+ Args:
35
+ database_ids (List[Dict[str, str]], optional): A list of dictionaries
36
+ each containing a database id and a name.
37
+ Defaults to None. If None, the function will generate all databases
38
+ in the workspace that are accessible to the integration.
39
+ api_key (str): The Notion API secret key.
40
+
41
+ Yields:
42
+ DltResource: Data resources from Notion databases.
43
+ """
44
+ notion_client = NotionClient(api_key)
45
+
46
+ if database_ids is None:
47
+ search_results = notion_client.search(
48
+ filter_criteria={"value": "database", "property": "object"}
49
+ )
50
+ database_ids = [
51
+ {"id": result["id"], "use_name": result["title"][0]["plain_text"]}
52
+ for result in search_results
53
+ ]
54
+
55
+ for database in database_ids:
56
+ if "use_name" not in database:
57
+ # Fetch the database details from Notion
58
+ details = notion_client.get_database(database["id"])
59
+
60
+ # Extract the name/title from the details
61
+ database["use_name"] = details["title"][0]["plain_text"]
62
+
63
+ notion_database = NotionDatabase(database["id"], notion_client)
64
+ yield dlt.resource( # type: ignore
65
+ notion_database.query(),
66
+ primary_key="id",
67
+ name=database["use_name"],
68
+ write_disposition="replace",
69
+ )
@@ -0,0 +1,14 @@
1
+ # Copyright 2022-2025 ScaleVector
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
@@ -0,0 +1,178 @@
1
+ # Copyright 2022-2025 ScaleVector
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Any, Dict, Iterator, Optional
16
+
17
+ from dlt.sources.helpers import requests
18
+
19
+ from ..settings import API_URL
20
+
21
+
22
+ class NotionClient:
23
+ """A client to interact with the Notion API.
24
+
25
+ Attributes:
26
+ api_key (str): The Notion API secret key.
27
+ """
28
+
29
+ def __init__(self, api_key: Optional[str] = None):
30
+ self.api_key = api_key
31
+
32
+ def _create_headers(self) -> Dict[str, str]:
33
+ headers = {
34
+ "accept": "application/json",
35
+ "Notion-Version": "2022-06-28",
36
+ "Authorization": f"Bearer {self.api_key}",
37
+ }
38
+ return headers
39
+
40
+ def _filter_out_none_values(self, dict_in: Dict[str, Any]) -> Dict[str, Any]:
41
+ return {k: v for k, v in dict_in.items() if v is not None}
42
+
43
+ def get_endpoint(
44
+ self, resource: str, resource_id: str, subresource: Optional[str] = None
45
+ ) -> str:
46
+ """Returns the endpoint for a given resource.
47
+
48
+ Args:
49
+ resource (str): The resource to get the endpoint for.
50
+ resource_id (str): The id of the resource.
51
+ subresource (str, optional): The subresource to get the endpoint for.
52
+
53
+ Returns:
54
+ str: The endpoint for the resource.
55
+ """
56
+ url = f"{API_URL}/{resource}/{resource_id}"
57
+ if subresource:
58
+ url += f"/{subresource}"
59
+ return url
60
+
61
+ def fetch_resource(
62
+ self, resource: str, resource_id: str, subresource: Optional[str] = None
63
+ ) -> Any:
64
+ """Fetches a resource from the Notion API.
65
+
66
+ Args:
67
+ resource (str): The resource to fetch.
68
+ resource_id (str): The id of the resource.
69
+ subresource (str, optional): The subresource to fetch. Defaults to None.
70
+
71
+ Returns:
72
+ Any: The resource from the Notion API.
73
+ """
74
+ url = self.get_endpoint(resource, resource_id, subresource)
75
+ headers = self._create_headers()
76
+ response = requests.get(url, headers=headers)
77
+ response.raise_for_status()
78
+ return response.json()
79
+
80
+ def send_payload(
81
+ self,
82
+ resource: str,
83
+ resource_id: str,
84
+ subresource: Optional[str] = None,
85
+ query_params: Optional[Dict[str, Any]] = None,
86
+ payload: Optional[Dict[str, Any]] = None,
87
+ ) -> Any:
88
+ """Sends a payload to the Notion API using the POST method.
89
+
90
+ Args:
91
+ resource (str): The resource to send the payload to.
92
+ resource_id (str): The id of the resource.
93
+ subresource (str, optional): The subresource to send the payload to.
94
+ Defaults to None.
95
+ query_params (Dict[str, Any], optional): The query parameters to send
96
+ with the payload. Defaults to None.
97
+ payload (Dict[str, Any], optional): The payload to send. Defaults to None.
98
+
99
+ Returns:
100
+ Any: The response from the Notion API.
101
+
102
+ Raises:
103
+ requests.HTTPError: If the response from the Notion API is not 200.
104
+ """
105
+
106
+ url = self.get_endpoint(resource, resource_id, subresource)
107
+ headers = self._create_headers()
108
+
109
+ if payload is None:
110
+ payload = {}
111
+
112
+ filtered_payload = self._filter_out_none_values(payload)
113
+
114
+ response = requests.post(
115
+ url, headers=headers, params=query_params, json=filtered_payload
116
+ )
117
+ response.raise_for_status()
118
+ return response.json()
119
+
120
+ def search(
121
+ self,
122
+ query: Optional[str] = None,
123
+ filter_criteria: Optional[Dict[str, Any]] = None,
124
+ sort: Optional[Dict[str, Any]] = None,
125
+ start_cursor: Optional[str] = None,
126
+ page_size: Optional[int] = None,
127
+ ) -> Iterator[Dict[str, Any]]:
128
+ """Searches all parent or child pages and databases that have been
129
+ shared with an integration.
130
+
131
+ Notion API Reference. Search:
132
+ https://developers.notion.com/reference/post-search
133
+
134
+ Args:
135
+ query (str, optional): The string to search for. Defaults to None.
136
+ filter_criteria (Dict[str, Any], optional): The filter to apply to
137
+ the results.
138
+ sort (Dict[str, Any], optional): The sort to apply to the results.
139
+ start_cursor (str, optional): The cursor to start the query at.
140
+ Defaults to None.
141
+ page_size (int, optional): The number of results to return.
142
+ Defaults to None.
143
+
144
+ Yields:
145
+ Dict[str, Any]: A result from the search.
146
+ """
147
+ has_more = True
148
+
149
+ while has_more:
150
+ payload = {
151
+ "query": query,
152
+ "sort": sort,
153
+ "filter": filter_criteria,
154
+ "start_cursor": start_cursor,
155
+ "page_size": page_size,
156
+ }
157
+
158
+ filtered_payload = self._filter_out_none_values(payload)
159
+
160
+ response = self.send_payload("search", "", payload=filtered_payload)
161
+
162
+ for result in response.get("results", []):
163
+ yield result
164
+
165
+ next_cursor = response.get("next_cursor")
166
+ has_more = next_cursor is not None
167
+ start_cursor = next_cursor
168
+
169
+ def get_database(self, database_id: str) -> Any:
170
+ """Fetches the details of a specific database by its ID.
171
+
172
+ Args:
173
+ database_id (str): The ID of the database to fetch.
174
+
175
+ Returns:
176
+ Any: The details of the database.
177
+ """
178
+ return self.fetch_resource("databases", database_id)
@@ -0,0 +1,92 @@
1
+ # Copyright 2022-2025 ScaleVector
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Any, Dict, Iterable, Optional
16
+
17
+ from dlt.common.typing import TDataItem
18
+
19
+ from .client import NotionClient
20
+
21
+
22
+ class NotionDatabase:
23
+ """
24
+ A class to represent a Notion database.
25
+
26
+ Attributes:
27
+ database_id (str): The ID of the Notion database.
28
+ notion_client (NotionClient): A client to interact with the Notion API.
29
+ """
30
+
31
+ def __init__(self, database_id: str, notion_client: NotionClient):
32
+ self.database_id = database_id
33
+ self.notion_client = notion_client
34
+
35
+ def get_structure(self) -> Any:
36
+ """Retrieves the structure of the database.
37
+
38
+ Notion API Reference. Retrieve a database:
39
+ https://developers.notion.com/reference/retrieve-a-database
40
+
41
+ Returns:
42
+ Any: The structure of the database.
43
+ """
44
+ return self.notion_client.fetch_resource("databases", self.database_id)
45
+
46
+ def query(
47
+ self,
48
+ filter_properties: Optional[Dict[str, Any]] = None,
49
+ filter_criteria: Optional[Dict[str, Any]] = None,
50
+ sorts: Optional[Dict[str, Any]] = None,
51
+ start_cursor: Optional[str] = None,
52
+ page_size: Optional[int] = None,
53
+ ) -> Iterable[TDataItem]:
54
+ """Queries the database for records.
55
+
56
+ Notion API Reference. Query a database:
57
+ https://developers.notion.com/reference/post-database-query
58
+
59
+ Args:
60
+ filter_properties (Dict[str, Any], optional): A dictionary of
61
+ properties to filter the records by. Defaults to None.
62
+ filter_criteria (Dict[str, Any], optional): A dictionary of filters
63
+ to apply to the records. Defaults to None.
64
+ sorts (Dict[str, Any], optional): A dictionary of sorts to apply
65
+ to the records. Defaults to None.
66
+ start_cursor (str, optional): The cursor to start the query at.
67
+ Defaults to None.
68
+ page_size (int, optional): The number of records to return.
69
+ Defaults to None.
70
+
71
+ Yields:
72
+ List[Dict[str, Any]]: A record from the database.
73
+ """
74
+ while True:
75
+ payload = {
76
+ "filter": filter_criteria,
77
+ "sorts": sorts,
78
+ "start_cursor": start_cursor,
79
+ "page_size": page_size,
80
+ }
81
+ response = self.notion_client.send_payload(
82
+ "databases",
83
+ self.database_id,
84
+ subresource="query",
85
+ query_params=filter_properties,
86
+ payload=payload,
87
+ )
88
+
89
+ yield response.get("results", [])
90
+ if not response.get("has_more"):
91
+ break
92
+ start_cursor = response.get("next_cursor")
@@ -0,0 +1,17 @@
1
+ # Copyright 2022-2025 ScaleVector
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Notion source settings and constants"""
16
+
17
+ API_URL = "https://api.notion.com/v1"
@@ -0,0 +1,32 @@
1
+ from typing import Dict
2
+
3
+ from dlt.common.schema.typing import TColumnSchema
4
+ from dlt.sources import DltResource, DltSource
5
+
6
+ import omniload.src.resource as resource
7
+
8
+
9
+ def apply_athena_hints(
10
+ source: DltSource | DltResource,
11
+ partition_column: str,
12
+ additional_hints: Dict[str, TColumnSchema] = {},
13
+ ) -> None:
14
+ from dlt.destinations.adapters import athena_adapter, athena_partition
15
+
16
+ def _apply_partition_hint(resource: DltResource) -> None:
17
+ columns = resource.columns if resource.columns else {}
18
+
19
+ partition_hint = (
20
+ columns.get(partition_column) # type: ignore
21
+ or additional_hints.get(partition_column)
22
+ )
23
+
24
+ athena_adapter(
25
+ resource,
26
+ athena_partition.day(partition_column)
27
+ if partition_hint
28
+ and partition_hint.get("data_type") in ("timestamp", "date")
29
+ else partition_column,
30
+ )
31
+
32
+ resource.for_each(source, _apply_partition_hint)