ingestr 0.13.42__tar.gz → 0.13.44__tar.gz

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 ingestr might be problematic. Click here for more details.

Files changed (279) hide show
  1. {ingestr-0.13.42 → ingestr-0.13.44}/PKG-INFO +1 -1
  2. {ingestr-0.13.42 → ingestr-0.13.44}/docs/.vitepress/config.mjs +1 -0
  3. ingestr-0.13.44/docs/supported-sources/attio.md +42 -0
  4. ingestr-0.13.44/ingestr/src/attio/__init__.py +100 -0
  5. ingestr-0.13.44/ingestr/src/attio/helpers.py +54 -0
  6. ingestr-0.13.44/ingestr/src/buildinfo.py +1 -0
  7. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/destinations.py +19 -3
  8. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/factory.py +2 -0
  9. ingestr-0.13.44/ingestr/src/http_client.py +17 -0
  10. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/sources.py +27 -0
  11. ingestr-0.13.42/ingestr/src/buildinfo.py +0 -1
  12. {ingestr-0.13.42 → ingestr-0.13.44}/.dockerignore +0 -0
  13. {ingestr-0.13.42 → ingestr-0.13.44}/.githooks/pre-commit-hook.sh +0 -0
  14. {ingestr-0.13.42 → ingestr-0.13.44}/.github/workflows/deploy-docs.yml +0 -0
  15. {ingestr-0.13.42 → ingestr-0.13.44}/.github/workflows/release.yml +0 -0
  16. {ingestr-0.13.42 → ingestr-0.13.44}/.github/workflows/secrets-scan.yml +0 -0
  17. {ingestr-0.13.42 → ingestr-0.13.44}/.github/workflows/tests.yml +0 -0
  18. {ingestr-0.13.42 → ingestr-0.13.44}/.gitignore +0 -0
  19. {ingestr-0.13.42 → ingestr-0.13.44}/.gitleaksignore +0 -0
  20. {ingestr-0.13.42 → ingestr-0.13.44}/.python-version +0 -0
  21. {ingestr-0.13.42 → ingestr-0.13.44}/.vale.ini +0 -0
  22. {ingestr-0.13.42 → ingestr-0.13.44}/Dockerfile +0 -0
  23. {ingestr-0.13.42 → ingestr-0.13.44}/LICENSE.md +0 -0
  24. {ingestr-0.13.42 → ingestr-0.13.44}/Makefile +0 -0
  25. {ingestr-0.13.42 → ingestr-0.13.44}/README.md +0 -0
  26. {ingestr-0.13.42 → ingestr-0.13.44}/docs/.vitepress/theme/custom.css +0 -0
  27. {ingestr-0.13.42 → ingestr-0.13.44}/docs/.vitepress/theme/index.js +0 -0
  28. {ingestr-0.13.42 → ingestr-0.13.44}/docs/commands/example-uris.md +0 -0
  29. {ingestr-0.13.42 → ingestr-0.13.44}/docs/commands/ingest.md +0 -0
  30. {ingestr-0.13.42 → ingestr-0.13.44}/docs/getting-started/core-concepts.md +0 -0
  31. {ingestr-0.13.42 → ingestr-0.13.44}/docs/getting-started/incremental-loading.md +0 -0
  32. {ingestr-0.13.42 → ingestr-0.13.44}/docs/getting-started/quickstart.md +0 -0
  33. {ingestr-0.13.42 → ingestr-0.13.44}/docs/getting-started/telemetry.md +0 -0
  34. {ingestr-0.13.42 → ingestr-0.13.44}/docs/index.md +0 -0
  35. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/applovin_max.png +0 -0
  36. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/athena.png +0 -0
  37. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/clickhouse_img.png +0 -0
  38. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/freshdesk_ingestion.png +0 -0
  39. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/github.png +0 -0
  40. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/google_analytics_realtime_report.png +0 -0
  41. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/googleanalytics.png +0 -0
  42. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/ingestion_elasticsearch_img.png +0 -0
  43. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/kinesis.bigquery.png +0 -0
  44. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/linkedin_ads.png +0 -0
  45. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/personio.png +0 -0
  46. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/personio_duckdb.png +0 -0
  47. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/phantombuster.png +0 -0
  48. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/pipedrive.png +0 -0
  49. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/spanner_ingestion.png +0 -0
  50. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/stripe_postgres.png +0 -0
  51. {ingestr-0.13.42 → ingestr-0.13.44}/docs/media/tiktok.png +0 -0
  52. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/adjust.md +0 -0
  53. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/airtable.md +0 -0
  54. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/applovin.md +0 -0
  55. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/applovin_max.md +0 -0
  56. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/appsflyer.md +0 -0
  57. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/appstore.md +0 -0
  58. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/asana.md +0 -0
  59. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/athena.md +0 -0
  60. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/bigquery.md +0 -0
  61. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/chess.md +0 -0
  62. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/clickhouse.md +0 -0
  63. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/csv.md +0 -0
  64. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/custom_queries.md +0 -0
  65. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/databricks.md +0 -0
  66. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/db2.md +0 -0
  67. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/duckdb.md +0 -0
  68. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/dynamodb.md +0 -0
  69. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/elasticsearch.md +0 -0
  70. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/facebook-ads.md +0 -0
  71. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/frankfurter.md +0 -0
  72. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/freshdesk.md +0 -0
  73. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/gcs.md +0 -0
  74. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/github.md +0 -0
  75. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/google-ads.md +0 -0
  76. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/google_analytics.md +0 -0
  77. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/gorgias.md +0 -0
  78. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/gsheets.md +0 -0
  79. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/hubspot.md +0 -0
  80. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/kafka.md +0 -0
  81. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/kinesis.md +0 -0
  82. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/klaviyo.md +0 -0
  83. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/linkedin_ads.md +0 -0
  84. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/mongodb.md +0 -0
  85. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/mssql.md +0 -0
  86. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/mysql.md +0 -0
  87. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/notion.md +0 -0
  88. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/oracle.md +0 -0
  89. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/personio.md +0 -0
  90. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/phantombuster.md +0 -0
  91. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/pipedrive.md +0 -0
  92. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/postgres.md +0 -0
  93. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/redshift.md +0 -0
  94. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/s3.md +0 -0
  95. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/salesforce.md +0 -0
  96. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/sap-hana.md +0 -0
  97. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/shopify.md +0 -0
  98. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/slack.md +0 -0
  99. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/snowflake.md +0 -0
  100. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/spanner.md +0 -0
  101. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/sqlite.md +0 -0
  102. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/stripe.md +0 -0
  103. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/tiktok-ads.md +0 -0
  104. {ingestr-0.13.42 → ingestr-0.13.44}/docs/supported-sources/zendesk.md +0 -0
  105. {ingestr-0.13.42 → ingestr-0.13.44}/docs/tutorials/load-kinesis-bigquery.md +0 -0
  106. {ingestr-0.13.42 → ingestr-0.13.44}/docs/tutorials/load-personio-duckdb.md +0 -0
  107. {ingestr-0.13.42 → ingestr-0.13.44}/docs/tutorials/load-stripe-postgres.md +0 -0
  108. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/conftest.py +0 -0
  109. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/main.py +0 -0
  110. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/.gitignore +0 -0
  111. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/adjust/__init__.py +0 -0
  112. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/adjust/adjust_helpers.py +0 -0
  113. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/airtable/__init__.py +0 -0
  114. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/applovin/__init__.py +0 -0
  115. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/applovin_max/__init__.py +0 -0
  116. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/appsflyer/__init__.py +0 -0
  117. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/appsflyer/client.py +0 -0
  118. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/appstore/__init__.py +0 -0
  119. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/appstore/client.py +0 -0
  120. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/appstore/errors.py +0 -0
  121. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/appstore/models.py +0 -0
  122. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/appstore/resources.py +0 -0
  123. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/arrow/__init__.py +0 -0
  124. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/asana_source/__init__.py +0 -0
  125. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/asana_source/helpers.py +0 -0
  126. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/asana_source/settings.py +0 -0
  127. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/blob.py +0 -0
  128. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/chess/__init__.py +0 -0
  129. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/chess/helpers.py +0 -0
  130. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/chess/settings.py +0 -0
  131. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/collector/spinner.py +0 -0
  132. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/dynamodb/__init__.py +0 -0
  133. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/elasticsearch/__init__.py +0 -0
  134. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/errors.py +0 -0
  135. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/facebook_ads/__init__.py +0 -0
  136. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/facebook_ads/exceptions.py +0 -0
  137. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/facebook_ads/helpers.py +0 -0
  138. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/facebook_ads/settings.py +0 -0
  139. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/filesystem/__init__.py +0 -0
  140. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/filesystem/helpers.py +0 -0
  141. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/filesystem/readers.py +0 -0
  142. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/filters.py +0 -0
  143. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/frankfurter/__init__.py +0 -0
  144. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/frankfurter/helpers.py +0 -0
  145. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/freshdesk/__init__.py +0 -0
  146. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/freshdesk/freshdesk_client.py +0 -0
  147. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/freshdesk/settings.py +0 -0
  148. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/github/__init__.py +0 -0
  149. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/github/helpers.py +0 -0
  150. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/github/queries.py +0 -0
  151. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/github/settings.py +0 -0
  152. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_ads/__init__.py +0 -0
  153. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_ads/field.py +0 -0
  154. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_ads/metrics.py +0 -0
  155. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_ads/predicates.py +0 -0
  156. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_ads/reports.py +0 -0
  157. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_analytics/__init__.py +0 -0
  158. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_analytics/helpers.py +0 -0
  159. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_sheets/README.md +0 -0
  160. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_sheets/__init__.py +0 -0
  161. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_sheets/helpers/__init__.py +0 -0
  162. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_sheets/helpers/api_calls.py +0 -0
  163. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/google_sheets/helpers/data_processing.py +0 -0
  164. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/gorgias/__init__.py +0 -0
  165. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/gorgias/helpers.py +0 -0
  166. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/hubspot/__init__.py +0 -0
  167. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/hubspot/helpers.py +0 -0
  168. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/hubspot/settings.py +0 -0
  169. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/kafka/__init__.py +0 -0
  170. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/kafka/helpers.py +0 -0
  171. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/kinesis/__init__.py +0 -0
  172. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/kinesis/helpers.py +0 -0
  173. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/klaviyo/__init__.py +0 -0
  174. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/klaviyo/client.py +0 -0
  175. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/klaviyo/helpers.py +0 -0
  176. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/linkedin_ads/__init__.py +0 -0
  177. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/linkedin_ads/dimension_time_enum.py +0 -0
  178. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/linkedin_ads/helpers.py +0 -0
  179. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/loader.py +0 -0
  180. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/mongodb/__init__.py +0 -0
  181. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/mongodb/helpers.py +0 -0
  182. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/notion/__init__.py +0 -0
  183. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/notion/helpers/__init__.py +0 -0
  184. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/notion/helpers/client.py +0 -0
  185. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/notion/helpers/database.py +0 -0
  186. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/notion/settings.py +0 -0
  187. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/partition.py +0 -0
  188. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/personio/__init__.py +0 -0
  189. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/personio/helpers.py +0 -0
  190. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/phantombuster/__init__.py +0 -0
  191. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/phantombuster/client.py +0 -0
  192. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/pipedrive/__init__.py +0 -0
  193. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/pipedrive/helpers/__init__.py +0 -0
  194. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/pipedrive/helpers/custom_fields_munger.py +0 -0
  195. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/pipedrive/helpers/pages.py +0 -0
  196. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/pipedrive/settings.py +0 -0
  197. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/pipedrive/typing.py +0 -0
  198. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/resource.py +0 -0
  199. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/salesforce/__init__.py +0 -0
  200. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/salesforce/helpers.py +0 -0
  201. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/shopify/__init__.py +0 -0
  202. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/shopify/exceptions.py +0 -0
  203. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/shopify/helpers.py +0 -0
  204. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/shopify/settings.py +0 -0
  205. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/slack/__init__.py +0 -0
  206. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/slack/helpers.py +0 -0
  207. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/slack/settings.py +0 -0
  208. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/sql_database/__init__.py +0 -0
  209. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/sql_database/callbacks.py +0 -0
  210. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/stripe_analytics/__init__.py +0 -0
  211. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/stripe_analytics/helpers.py +0 -0
  212. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/stripe_analytics/settings.py +0 -0
  213. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/table_definition.py +0 -0
  214. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/telemetry/event.py +0 -0
  215. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/testdata/fakebqcredentials.json +0 -0
  216. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/tiktok_ads/__init__.py +0 -0
  217. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/tiktok_ads/tiktok_helpers.py +0 -0
  218. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/time.py +0 -0
  219. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/version.py +0 -0
  220. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/zendesk/__init__.py +0 -0
  221. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/zendesk/helpers/__init__.py +0 -0
  222. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/zendesk/helpers/api_helpers.py +0 -0
  223. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/zendesk/helpers/credentials.py +0 -0
  224. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/zendesk/helpers/talk_api.py +0 -0
  225. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/src/zendesk/settings.py +0 -0
  226. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/testdata/.gitignore +0 -0
  227. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/testdata/create_replace.csv +0 -0
  228. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/testdata/delete_insert_expected.csv +0 -0
  229. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/testdata/delete_insert_part1.csv +0 -0
  230. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/testdata/delete_insert_part2.csv +0 -0
  231. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/testdata/merge_expected.csv +0 -0
  232. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/testdata/merge_part1.csv +0 -0
  233. {ingestr-0.13.42 → ingestr-0.13.44}/ingestr/testdata/merge_part2.csv +0 -0
  234. {ingestr-0.13.42 → ingestr-0.13.44}/package-lock.json +0 -0
  235. {ingestr-0.13.42 → ingestr-0.13.44}/package.json +0 -0
  236. {ingestr-0.13.42 → ingestr-0.13.44}/pyproject.toml +0 -0
  237. {ingestr-0.13.42 → ingestr-0.13.44}/requirements-dev.txt +0 -0
  238. {ingestr-0.13.42 → ingestr-0.13.44}/requirements.in +0 -0
  239. {ingestr-0.13.42 → ingestr-0.13.44}/requirements.txt +0 -0
  240. {ingestr-0.13.42 → ingestr-0.13.44}/requirements_arm64.txt +0 -0
  241. {ingestr-0.13.42 → ingestr-0.13.44}/resources/demo.gif +0 -0
  242. {ingestr-0.13.42 → ingestr-0.13.44}/resources/demo.tape +0 -0
  243. {ingestr-0.13.42 → ingestr-0.13.44}/resources/ingestr.svg +0 -0
  244. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/AMPM.yml +0 -0
  245. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Acronyms.yml +0 -0
  246. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Colons.yml +0 -0
  247. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Contractions.yml +0 -0
  248. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/DateFormat.yml +0 -0
  249. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Ellipses.yml +0 -0
  250. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/EmDash.yml +0 -0
  251. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Exclamation.yml +0 -0
  252. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/FirstPerson.yml +0 -0
  253. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Gender.yml +0 -0
  254. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/GenderBias.yml +0 -0
  255. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/HeadingPunctuation.yml +0 -0
  256. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Headings.yml +0 -0
  257. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Latin.yml +0 -0
  258. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/LyHyphens.yml +0 -0
  259. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/OptionalPlurals.yml +0 -0
  260. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Ordinal.yml +0 -0
  261. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/OxfordComma.yml +0 -0
  262. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Parens.yml +0 -0
  263. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Passive.yml +0 -0
  264. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Periods.yml +0 -0
  265. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Quotes.yml +0 -0
  266. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Ranges.yml +0 -0
  267. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Semicolons.yml +0 -0
  268. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Slang.yml +0 -0
  269. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Spacing.yml +0 -0
  270. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Spelling.yml +0 -0
  271. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Units.yml +0 -0
  272. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/We.yml +0 -0
  273. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/Will.yml +0 -0
  274. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/WordList.yml +0 -0
  275. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/meta.json +0 -0
  276. {ingestr-0.13.42 → ingestr-0.13.44}/styles/Google/vocab.txt +0 -0
  277. {ingestr-0.13.42 → ingestr-0.13.44}/styles/bruin/Ingestr.yml +0 -0
  278. {ingestr-0.13.42 → ingestr-0.13.44}/styles/config/vocabularies/bruin/accept.txt +0 -0
  279. {ingestr-0.13.42 → ingestr-0.13.44}/test.env.template +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ingestr
3
- Version: 0.13.42
3
+ Version: 0.13.44
4
4
  Summary: ingestr is a command-line application that ingests data from various sources and stores them in any database.
5
5
  Project-URL: Homepage, https://github.com/bruin-data/ingestr
6
6
  Project-URL: Issues, https://github.com/bruin-data/ingestr/issues
@@ -114,6 +114,7 @@ export default defineConfig({
114
114
  { text: "Applovin", link: "/supported-sources/applovin.md"},
115
115
  { text: "Applovin Max", link: "/supported-sources/applovin_max.md"},
116
116
  { text: "Asana", link: "/supported-sources/asana.md" },
117
+ { text: "Attio", link: "/supported-sources/attio.md" },
117
118
  { text: "Chess.com", link: "/supported-sources/chess.md" },
118
119
  {
119
120
  text: "Facebook Ads",
@@ -0,0 +1,42 @@
1
+ # Attio
2
+ [Attio](https://attio.com/) is an AI-native CRM platform that helps companies build, scale, and grow their business.
3
+
4
+ ingestr supports Attio as a source.
5
+
6
+ ## URI format
7
+
8
+ The URI format for Attio is as follows:
9
+
10
+ ```plaintext
11
+ attio://?api_key=<api_key>
12
+ ```
13
+
14
+ URI parameters:
15
+ - `api_key`: the API key used for authentication with the Attio API
16
+
17
+ ## Setting up a Attio Integration
18
+
19
+ You can find your Attio API key by following the guide [here](https://attio.com/help/apps/other-apps/generating-an-api-key).
20
+
21
+ Let's say your `api_key` is key_123, here's a sample command that will copy the data from Attio into a DuckDB database:
22
+
23
+
24
+ ```bash
25
+ ingestr ingest \
26
+ --source-uri 'Attio://?api_key=key_123' \
27
+ --source-table 'objects' \
28
+ --dest-uri duckdb:///attio.duckdb \
29
+ --dest-table 'dest.objects'
30
+ ```
31
+
32
+ ## Tables
33
+
34
+ Attio source supports ingesting the following sources into separate tables:
35
+
36
+ - `objects`: Objects are the data types used to store facts about your customers. Fetches all objects.
37
+ - `records:{object_api_slug}`: Fetches all records of an object. For example: `records:companies`
38
+ - `lists`: Fetches all lists
39
+ - `list_entries:{list_id}`: Lists all items in a specific list. For example: `list_entries:8abc-123-456-789d-123`
40
+ - `all_list_entries:{object_api_slug}`: Fetches all the lists for an object, and then fetches all the entries from that list. For eg: Fetches all lists for an object, and then fetches all entries from those lists. For example: `all_list_entries:companies`
41
+
42
+ Use this as `--source-table` parameter in the `ingestr ingest` command.
@@ -0,0 +1,100 @@
1
+ from typing import Iterable, Iterator
2
+
3
+ import dlt
4
+ from dlt.sources import DltResource
5
+
6
+ from .helpers import AttioClient
7
+
8
+
9
+ @dlt.source(max_table_nesting=0)
10
+ def attio_source(
11
+ api_key: str,
12
+ params: list[str],
13
+ ) -> Iterable[DltResource]:
14
+
15
+ attio_client = AttioClient(api_key)
16
+
17
+ @dlt.resource(
18
+ name="objects",
19
+ write_disposition="replace",
20
+ columns={
21
+ "created_at": {"data_type": "timestamp", "partition": True},
22
+ },
23
+ )
24
+ def fetch_objects() -> Iterator[dict]:
25
+ if len(params) != 0:
26
+ raise ValueError("Objects table must be in the format `objects`")
27
+
28
+ path = "objects"
29
+ yield attio_client.fetch_data(path, "get")
30
+
31
+ @dlt.resource(
32
+ name="records",
33
+ write_disposition="replace",
34
+ columns={
35
+ "created_at": {"data_type": "timestamp", "partition": True},
36
+ },
37
+ )
38
+ def fetch_records() -> Iterator[dict]:
39
+ if len(params) != 1:
40
+ raise ValueError(
41
+ "Records table must be in the format `records:{object_api_slug}`"
42
+ )
43
+
44
+ object_id = params[0]
45
+ path = f"objects/{object_id}/records/query"
46
+
47
+ yield attio_client.fetch_data(path, "post")
48
+
49
+ @dlt.resource(
50
+ name="lists",
51
+ write_disposition="replace",
52
+ columns={
53
+ "created_at": {"data_type": "timestamp", "partition": True},
54
+ },
55
+ )
56
+ def fetch_lists() -> Iterator[dict]:
57
+ path = "lists"
58
+ yield attio_client.fetch_data(path, "get")
59
+
60
+ @dlt.resource(
61
+ name="list_entries",
62
+ write_disposition="replace",
63
+ columns={
64
+ "created_at": {"data_type": "timestamp", "partition": True},
65
+ },
66
+ )
67
+ def fetch_list_entries() -> Iterator[dict]:
68
+ if len(params) != 1:
69
+ raise ValueError(
70
+ "List entries table must be in the format `list_entries:{list_id}`"
71
+ )
72
+ path = f"lists/{params[0]}/entries/query"
73
+
74
+ yield attio_client.fetch_data(path, "post")
75
+
76
+ @dlt.resource(
77
+ name="all_list_entries",
78
+ write_disposition="replace",
79
+ columns={
80
+ "created_at": {"data_type": "timestamp", "partition": True},
81
+ },
82
+ )
83
+ def fetch_all_list_entries() -> Iterator[dict]:
84
+ if len(params) != 1:
85
+ raise ValueError(
86
+ "All list entries table must be in the format `all_list_entries:{object_api_slug}`"
87
+ )
88
+ path = "lists"
89
+ for lst in attio_client.fetch_data(path, "get"):
90
+ if params[0] in lst["parent_object"]:
91
+ path = f"lists/{lst['id']['list_id']}/entries/query"
92
+ yield from attio_client.fetch_data(path, "post")
93
+
94
+ return (
95
+ fetch_objects,
96
+ fetch_records,
97
+ fetch_lists,
98
+ fetch_list_entries,
99
+ fetch_all_list_entries,
100
+ )
@@ -0,0 +1,54 @@
1
+ from ingestr.src.http_client import create_client
2
+
3
+
4
+ class AttioClient:
5
+ def __init__(self, api_key: str):
6
+ self.base_url = "https://api.attio.com/v2"
7
+ self.headers = {
8
+ "Accept": "application/json",
9
+ "Authorization": f"Bearer {api_key}",
10
+ }
11
+ self.client = create_client()
12
+
13
+ def fetch_data(self, path: str, method: str, limit: int = 1000, params=None):
14
+ url = f"{self.base_url}/{path}"
15
+ if params is None:
16
+ params = {}
17
+ offset = 0
18
+ while True:
19
+ query_params = {**params, "limit": limit, "offset": offset}
20
+ if method == "get":
21
+ response = self.client.get(
22
+ url, headers=self.headers, params=query_params
23
+ )
24
+ else:
25
+ response = self.client.post(
26
+ url, headers=self.headers, params=query_params
27
+ )
28
+
29
+ if response.status_code != 200:
30
+ raise Exception(f"HTTP {response.status_code} error: {response.text}")
31
+
32
+ response_data = response.json()
33
+ if "data" not in response_data:
34
+ print(f"API Response: {response_data}")
35
+ raise Exception(
36
+ "Attio API returned a response without the expected data"
37
+ )
38
+
39
+ data = response_data["data"]
40
+
41
+ for item in data:
42
+ flat_item = flatten_item(item)
43
+ yield flat_item
44
+
45
+ if len(data) < limit:
46
+ break
47
+ offset += limit
48
+
49
+
50
+ def flatten_item(item: dict) -> dict:
51
+ if "id" in item:
52
+ for key, value in item["id"].items():
53
+ item[key] = value
54
+ return item
@@ -0,0 +1 @@
1
+ version = "v0.13.44"
@@ -413,6 +413,10 @@ class S3Destination:
413
413
  raise MissingValueError("secret_access_key", "S3")
414
414
 
415
415
  endpoint_url = params.get("endpoint_url", [None])[0]
416
+ if endpoint_url is not None:
417
+ parsed_endpoint = urlparse(endpoint_url)
418
+ if not parsed_endpoint.scheme or not parsed_endpoint.netloc:
419
+ raise ValueError("Invalid endpoint_url. Must be a valid URL.")
416
420
 
417
421
  creds = AwsCredentials(
418
422
  aws_access_key_id=access_key_id,
@@ -420,8 +424,21 @@ class S3Destination:
420
424
  endpoint_url=endpoint_url,
421
425
  )
422
426
 
423
- dest_table = self.validate_table(kwargs["dest_table"])
427
+ dest_table = kwargs["dest_table"]
428
+
429
+ # only validate if dest_table is not a full URI
430
+ if not parsed_uri.netloc:
431
+ dest_table = self.validate_table(dest_table)
432
+
424
433
  table_parts = dest_table.split("/")
434
+
435
+ if parsed_uri.path.strip("/"):
436
+ path_parts = parsed_uri.path.strip("/ ").split("/")
437
+ table_parts = path_parts + table_parts
438
+
439
+ if parsed_uri.netloc:
440
+ table_parts.insert(0, parsed_uri.netloc.strip())
441
+
425
442
  base_path = "/".join(table_parts[:-1])
426
443
 
427
444
  opts = {
@@ -444,10 +461,9 @@ class S3Destination:
444
461
  return table
445
462
 
446
463
  def dlt_run_params(self, uri: str, table: str, **kwargs):
447
- table = self.validate_table(table)
448
464
  table_parts = table.split("/")
449
465
  return {
450
- "table_name": table_parts[-1],
466
+ "table_name": table_parts[-1].strip(),
451
467
  }
452
468
 
453
469
  def post_load(self) -> None:
@@ -26,6 +26,7 @@ from ingestr.src.sources import (
26
26
  AppsflyerSource,
27
27
  ArrowMemoryMappedSource,
28
28
  AsanaSource,
29
+ AttioSource,
29
30
  ChessSource,
30
31
  DynamoDBSource,
31
32
  ElasticsearchSource,
@@ -157,6 +158,7 @@ class SourceDestinationFactory:
157
158
  "freshdesk": FreshdeskSource,
158
159
  "phantombuster": PhantombusterSource,
159
160
  "elasticsearch": ElasticsearchSource,
161
+ "attio": AttioSource,
160
162
  }
161
163
  destinations: Dict[str, Type[DestinationProtocol]] = {
162
164
  "bigquery": BigQueryDestination,
@@ -0,0 +1,17 @@
1
+ import requests
2
+ from dlt.sources.helpers.requests import Client
3
+
4
+ def create_client() -> requests.Session:
5
+ return Client(
6
+ raise_for_status=False,
7
+ retry_condition=retry_on_limit,
8
+ request_max_attempts=12,
9
+ ).session
10
+
11
+
12
+ def retry_on_limit(
13
+ response: requests.Response | None, exception: BaseException | None
14
+ ) -> bool:
15
+ if response is None:
16
+ return False
17
+ return response.status_code == 502
@@ -21,6 +21,7 @@ from urllib.parse import ParseResult, parse_qs, quote, urlencode, urlparse
21
21
  import pendulum
22
22
  from dlt.common.time import ensure_pendulum_datetime
23
23
  from dlt.extract import Incremental
24
+ from dlt.extract.exceptions import ResourcesNotFoundError
24
25
  from dlt.sources import incremental as dlt_incremental
25
26
  from dlt.sources.credentials import (
26
27
  ConnectionStringCredentials,
@@ -2392,3 +2393,29 @@ class ElasticsearchSource:
2392
2393
  verify_certs=verify_certs,
2393
2394
  incremental=incremental,
2394
2395
  ).with_resources(table)
2396
+
2397
+
2398
+ class AttioSource:
2399
+ def handles_incrementality(self) -> bool:
2400
+ return True
2401
+
2402
+ def dlt_source(self, uri: str, table: str, **kwargs):
2403
+ parsed_uri = urlparse(uri)
2404
+ query_params = parse_qs(parsed_uri.query)
2405
+ api_key = query_params.get("api_key")
2406
+
2407
+ if api_key is None:
2408
+ raise MissingValueError("api_key", "Attio")
2409
+
2410
+ parts = table.replace(" ", "").split(":")
2411
+ table_name = parts[0]
2412
+ params = parts[1:]
2413
+
2414
+ from ingestr.src.attio import attio_source
2415
+
2416
+ try:
2417
+ return attio_source(api_key=api_key[0], params=params).with_resources(
2418
+ table_name
2419
+ )
2420
+ except ResourcesNotFoundError:
2421
+ raise UnsupportedResourceError(table_name, "Attio")
@@ -1 +0,0 @@
1
- version = "v0.13.42"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes