ingestr 0.3.2__tar.gz → 0.4.0__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 (71) hide show
  1. {ingestr-0.3.2 → ingestr-0.4.0}/PKG-INFO +7 -1
  2. {ingestr-0.3.2 → ingestr-0.4.0}/README.md +5 -0
  3. {ingestr-0.3.2 → ingestr-0.4.0}/docs/.vitepress/config.mjs +1 -0
  4. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/overview.md +5 -0
  5. ingestr-0.4.0/docs/supported-sources/sap-hana.md +20 -0
  6. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/main.py +53 -26
  7. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/factory.py +1 -0
  8. ingestr-0.4.0/ingestr/src/version.py +1 -0
  9. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/testdata/test_append.db +0 -0
  10. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/testdata/test_create_replace.db +0 -0
  11. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/testdata/test_delete_insert_with_timerange.db +0 -0
  12. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/testdata/test_delete_insert_without_primary_key.db +0 -0
  13. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/testdata/test_merge_with_primary_key.db +0 -0
  14. {ingestr-0.3.2 → ingestr-0.4.0}/requirements.txt +2 -1
  15. ingestr-0.3.2/ingestr/src/version.py +0 -1
  16. {ingestr-0.3.2 → ingestr-0.4.0}/.dockerignore +0 -0
  17. {ingestr-0.3.2 → ingestr-0.4.0}/.github/workflows/deploy-docs.yml +0 -0
  18. {ingestr-0.3.2 → ingestr-0.4.0}/.github/workflows/docker.yml +0 -0
  19. {ingestr-0.3.2 → ingestr-0.4.0}/.gitignore +0 -0
  20. {ingestr-0.3.2 → ingestr-0.4.0}/Dockerfile +0 -0
  21. {ingestr-0.3.2 → ingestr-0.4.0}/LICENSE.md +0 -0
  22. {ingestr-0.3.2 → ingestr-0.4.0}/Makefile +0 -0
  23. {ingestr-0.3.2 → ingestr-0.4.0}/docs/.vitepress/theme/custom.css +0 -0
  24. {ingestr-0.3.2 → ingestr-0.4.0}/docs/.vitepress/theme/index.js +0 -0
  25. {ingestr-0.3.2 → ingestr-0.4.0}/docs/commands/example-uris.md +0 -0
  26. {ingestr-0.3.2 → ingestr-0.4.0}/docs/commands/ingest.md +0 -0
  27. {ingestr-0.3.2 → ingestr-0.4.0}/docs/getting-started/core-concepts.md +0 -0
  28. {ingestr-0.3.2 → ingestr-0.4.0}/docs/getting-started/incremental-loading.md +0 -0
  29. {ingestr-0.3.2 → ingestr-0.4.0}/docs/getting-started/quickstart.md +0 -0
  30. {ingestr-0.3.2 → ingestr-0.4.0}/docs/getting-started/telemetry.md +0 -0
  31. {ingestr-0.3.2 → ingestr-0.4.0}/docs/index.md +0 -0
  32. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/bigquery.md +0 -0
  33. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/csv.md +0 -0
  34. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/databricks.md +0 -0
  35. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/duckdb.md +0 -0
  36. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/mongodb.md +0 -0
  37. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/mssql.md +0 -0
  38. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/mysql.md +0 -0
  39. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/notion.md +0 -0
  40. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/oracle.md +0 -0
  41. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/postgres.md +0 -0
  42. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/redshift.md +0 -0
  43. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/snowflake.md +0 -0
  44. {ingestr-0.3.2 → ingestr-0.4.0}/docs/supported-sources/sqlite.md +0 -0
  45. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/main_test.py +0 -0
  46. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/destinations.py +0 -0
  47. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/destinations_test.py +0 -0
  48. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/factory_test.py +0 -0
  49. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/mongodb/__init__.py +0 -0
  50. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/mongodb/helpers.py +0 -0
  51. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/notion/__init__.py +0 -0
  52. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/notion/helpers/__init__.py +0 -0
  53. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/notion/helpers/client.py +0 -0
  54. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/notion/helpers/database.py +0 -0
  55. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/notion/settings.py +0 -0
  56. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/sources.py +0 -0
  57. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/sources_test.py +0 -0
  58. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/sql_database/__init__.py +0 -0
  59. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/sql_database/helpers.py +0 -0
  60. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/sql_database/override.py +0 -0
  61. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/sql_database/schema_types.py +0 -0
  62. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/telemetry/event.py +0 -0
  63. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/src/testdata/fakebqcredentials.json +0 -0
  64. {ingestr-0.3.2 → ingestr-0.4.0}/ingestr/testdata/.gitignore +0 -0
  65. {ingestr-0.3.2 → ingestr-0.4.0}/package-lock.json +0 -0
  66. {ingestr-0.3.2 → ingestr-0.4.0}/package.json +0 -0
  67. {ingestr-0.3.2 → ingestr-0.4.0}/pyproject.toml +0 -0
  68. {ingestr-0.3.2 → ingestr-0.4.0}/requirements-dev.txt +0 -0
  69. {ingestr-0.3.2 → ingestr-0.4.0}/resources/demo.gif +0 -0
  70. {ingestr-0.3.2 → ingestr-0.4.0}/resources/demo.tape +0 -0
  71. {ingestr-0.3.2 → ingestr-0.4.0}/resources/ingestr.svg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ingestr
3
- Version: 0.3.2
3
+ Version: 0.4.0
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
@@ -31,6 +31,7 @@ Requires-Dist: rich==13.7.1
31
31
  Requires-Dist: rudder-sdk-python==2.1.0
32
32
  Requires-Dist: snowflake-sqlalchemy==1.5.3
33
33
  Requires-Dist: sqlalchemy-bigquery==1.11.0
34
+ Requires-Dist: sqlalchemy-hana==2.0.0
34
35
  Requires-Dist: sqlalchemy-redshift==0.8.14
35
36
  Requires-Dist: sqlalchemy2-stubs==0.0.2a38
36
37
  Requires-Dist: sqlalchemy==1.4.52
@@ -150,6 +151,11 @@ Join our Slack community [here](https://join.slack.com/t/bruindatacommunity/shar
150
151
  <td>✅</td>
151
152
  <td>❌</td>
152
153
  </tr>
154
+ <tr>
155
+ <td>SAP Hana</td>
156
+ <td>✅</td>
157
+ <td>❌</td>
158
+ </tr>
153
159
  <tr>
154
160
  <td>SQLite</td>
155
161
  <td>✅</td>
@@ -110,6 +110,11 @@ Join our Slack community [here](https://join.slack.com/t/bruindatacommunity/shar
110
110
  <td>✅</td>
111
111
  <td>❌</td>
112
112
  </tr>
113
+ <tr>
114
+ <td>SAP Hana</td>
115
+ <td>✅</td>
116
+ <td>❌</td>
117
+ </tr>
113
118
  <tr>
114
119
  <td>SQLite</td>
115
120
  <td>✅</td>
@@ -58,6 +58,7 @@ export default defineConfig({
58
58
  { text: "MySQL", link: "/supported-sources/mysql.md" },
59
59
  { text: "Oracle", link: "/supported-sources/oracle.md" },
60
60
  { text: "Postgres", link: "/supported-sources/postgres.md" },
61
+ { text: "SAP Hana", link: "/supported-sources/sap-hana.md" },
61
62
  { text: "Snowflake", link: "/supported-sources/snowflake.md" },
62
63
  { text: "SQLite", link: "/supported-sources/sqlite.md" },
63
64
  ],
@@ -61,6 +61,11 @@ ingestr supports the following sources and destinations:
61
61
  <td>✅</td>
62
62
  <td>❌</td>
63
63
  </tr>
64
+ <tr>
65
+ <td>SAP Hana</td>
66
+ <td>✅</td>
67
+ <td>❌</td>
68
+ </tr>
64
69
  <tr>
65
70
  <td>SQLite</td>
66
71
  <td>✅</td>
@@ -0,0 +1,20 @@
1
+ # SAP HANA
2
+ SAP HANA is an in-memory, column-oriented, relational database management system.
3
+
4
+ ingestr supports SAP HANA as both a source and destination. It uses the [SQLAlchemy connector for SAP Hana](https://github.com/SAP/sqlalchemy-hana/), so the connection options there would all be valid.
5
+
6
+ ## URI Format
7
+ The URI format for SAP HANA is as follows:
8
+
9
+ ```plaintext
10
+ hana://user:password@host:port/dbname
11
+ ```
12
+
13
+ URI parameters:
14
+ - `user`: the username to connect to the database
15
+ - `password`: the password for the user
16
+ - `host`: the host address of the database server
17
+ - `port`: the port number the database server is listening on (default is 30015)
18
+ - `dbname`: the name of the database to connect to
19
+
20
+ The URI structure can be used both for sources and destinations. More details about SAP HANA’s JDBC and ODBC interfaces can be found [here](https://github.com/SAP/sqlalchemy-hana/).
@@ -1,5 +1,6 @@
1
1
  import hashlib
2
2
  from datetime import datetime
3
+ from enum import Enum
3
4
  from typing import Optional
4
5
 
5
6
  import dlt
@@ -83,6 +84,30 @@ class SpinnerCollector(Collector):
83
84
  self.status.stop()
84
85
 
85
86
 
87
+ class IncrementalStrategy(str, Enum):
88
+ create_replace = "replace"
89
+ append = "append"
90
+ delete_insert = "delete+insert"
91
+ merge = "merge"
92
+
93
+
94
+ class LoaderFileFormat(str, Enum):
95
+ jsonl = "jsonl"
96
+ parquet = "parquet"
97
+ insert_values = "insert_values"
98
+ csv = "csv"
99
+
100
+
101
+ class SqlBackend(str, Enum):
102
+ sqlalchemy = "sqlalchemy"
103
+ pyarrow = "pyarrow"
104
+
105
+
106
+ class Progress(str, Enum):
107
+ interactive = "interactive"
108
+ log = "log"
109
+
110
+
86
111
  @app.command()
87
112
  def ingest(
88
113
  source_uri: Annotated[
@@ -117,12 +142,12 @@ def ingest(
117
142
  ),
118
143
  ] = None, # type: ignore
119
144
  incremental_strategy: Annotated[
120
- str,
145
+ IncrementalStrategy,
121
146
  typer.Option(
122
- help="The incremental strategy to use, must be one of 'replace', 'append', 'delete+insert', or 'merge'",
147
+ help="The incremental strategy to use",
123
148
  envvar="INCREMENTAL_STRATEGY",
124
149
  ),
125
- ] = "replace", # type: ignore
150
+ ] = IncrementalStrategy.create_replace, # type: ignore
126
151
  interval_start: Annotated[
127
152
  Optional[datetime],
128
153
  typer.Option(
@@ -161,26 +186,26 @@ def ingest(
161
186
  ),
162
187
  ] = False, # type: ignore
163
188
  progress: Annotated[
164
- Optional[str],
189
+ Progress,
165
190
  typer.Option(
166
191
  help="The progress display type, must be one of 'interactive', 'log'",
167
192
  envvar="PROGRESS",
168
193
  ),
169
- ] = "interactive", # type: ignore
194
+ ] = Progress.interactive, # type: ignore
170
195
  sql_backend: Annotated[
171
- Optional[str],
196
+ SqlBackend,
172
197
  typer.Option(
173
- help="The SQL backend to use, must be one of 'sqlalchemy', 'pyarrow'",
198
+ help="The SQL backend to use",
174
199
  envvar="SQL_BACKEND",
175
200
  ),
176
- ] = "pyarrow", # type: ignore
201
+ ] = SqlBackend.pyarrow, # type: ignore
177
202
  loader_file_format: Annotated[
178
- Optional[str],
203
+ Optional[LoaderFileFormat],
179
204
  typer.Option(
180
- help="The file format to use when loading data, must be one of 'jsonl', 'parquet', 'default'",
205
+ help="The file format to use when loading data",
181
206
  envvar="LOADER_FILE_FORMAT",
182
207
  ),
183
- ] = "default", # type: ignore
208
+ ] = None, # type: ignore
184
209
  ):
185
210
  track(
186
211
  "command_triggered",
@@ -210,15 +235,15 @@ def ingest(
210
235
  original_incremental_strategy = incremental_strategy
211
236
 
212
237
  merge_key = None
213
- if incremental_strategy == "delete+insert":
238
+ if incremental_strategy == IncrementalStrategy.delete_insert:
214
239
  merge_key = incremental_key
215
- incremental_strategy = "merge"
240
+ incremental_strategy = IncrementalStrategy.merge
216
241
 
217
242
  m = hashlib.sha256()
218
243
  m.update(dest_table.encode("utf-8"))
219
244
 
220
245
  progressInstance: Collector = SpinnerCollector()
221
- if progress == "log":
246
+ if progress == Progress.log:
222
247
  progressInstance = LogCollector()
223
248
 
224
249
  pipeline = dlt.pipeline(
@@ -240,7 +265,7 @@ def ingest(
240
265
  f"[bold yellow] Destination:[/bold yellow] {factory.destination_scheme} / {dest_table}"
241
266
  )
242
267
  print(
243
- f"[bold yellow] Incremental Strategy:[/bold yellow] {incremental_strategy}"
268
+ f"[bold yellow] Incremental Strategy:[/bold yellow] {incremental_strategy.value}"
244
269
  )
245
270
  print(
246
271
  f"[bold yellow] Incremental Key:[/bold yellow] {incremental_key if incremental_key else 'None'}"
@@ -266,24 +291,24 @@ def ingest(
266
291
  merge_key=merge_key,
267
292
  interval_start=interval_start,
268
293
  interval_end=interval_end,
269
- sql_backend=sql_backend,
294
+ sql_backend=sql_backend.value,
270
295
  )
271
296
 
272
- if original_incremental_strategy == "delete+insert":
297
+ if original_incremental_strategy == IncrementalStrategy.delete_insert:
273
298
  dlt_source.incremental.primary_key = ()
274
299
 
275
300
  if (
276
301
  factory.destination_scheme in PARQUET_SUPPORTED_DESTINATIONS
277
- and loader_file_format == "default"
302
+ and loader_file_format is None
278
303
  ):
279
- loader_file_format = "parquet"
304
+ loader_file_format = LoaderFileFormat.parquet
280
305
 
281
306
  # if the source is a JSON returning source, we cannot use Parquet loader for BigQuery
282
- if factory.destination_scheme == 'bigquery' and factory.source_scheme in JSON_RETURNING_SOURCES:
283
- loader_file_format = "jsonl"
284
-
285
- elif loader_file_format == "default":
286
- loader_file_format = "jsonl"
307
+ if (
308
+ factory.destination_scheme == "bigquery"
309
+ and factory.source_scheme in JSON_RETURNING_SOURCES
310
+ ):
311
+ loader_file_format = None
287
312
 
288
313
  run_info = pipeline.run(
289
314
  dlt_source,
@@ -291,9 +316,11 @@ def ingest(
291
316
  uri=dest_uri,
292
317
  table=dest_table,
293
318
  ),
294
- write_disposition=incremental_strategy, # type: ignore
319
+ write_disposition=incremental_strategy.value, # type: ignore
295
320
  primary_key=(primary_key if primary_key and len(primary_key) > 0 else None), # type: ignore
296
- loader_file_format=loader_file_format, # type: ignore
321
+ loader_file_format=loader_file_format.value
322
+ if loader_file_format is not None
323
+ else None, # type: ignore
297
324
  )
298
325
 
299
326
  destination.post_load()
@@ -30,6 +30,7 @@ SQL_SOURCE_SCHEMES = [
30
30
  "sqlite",
31
31
  "oracle",
32
32
  "oracle+cx_oracle",
33
+ "hana",
33
34
  ]
34
35
 
35
36
 
@@ -0,0 +1 @@
1
+ __version__ = "0.4.0"
@@ -19,4 +19,5 @@ sqlalchemy-redshift==0.8.14
19
19
  SQLAlchemy==1.4.52
20
20
  sqlalchemy2-stubs==0.0.2a38
21
21
  tqdm==4.66.2
22
- typer==0.12.3
22
+ typer==0.12.3
23
+ sqlalchemy-hana==2.0.0
@@ -1 +0,0 @@
1
- __version__ = "0.3.2"
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
File without changes
File without changes
File without changes
File without changes